@mobrienv/autoloop-harness 0.8.0 → 0.9.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/dist/acceptance.d.ts +31 -0
- package/dist/acceptance.js +69 -0
- package/dist/acceptance.js.map +1 -0
- package/dist/ask.d.ts +16 -0
- package/dist/ask.js +47 -0
- package/dist/ask.js.map +1 -0
- package/dist/backend/types.d.ts +3 -0
- package/dist/backend/types.js +3 -0
- package/dist/backend/types.js.map +1 -1
- package/dist/circuit-breaker.d.ts +27 -0
- package/dist/circuit-breaker.js +41 -0
- package/dist/circuit-breaker.js.map +1 -0
- package/dist/completion-lint.d.ts +29 -0
- package/dist/completion-lint.js +51 -0
- package/dist/completion-lint.js.map +1 -0
- package/dist/config-helpers.js +141 -8
- package/dist/config-helpers.js.map +1 -1
- package/dist/control/command-adapter.d.ts +19 -0
- package/dist/control/command-adapter.js +57 -0
- package/dist/control/command-adapter.js.map +1 -0
- package/dist/control/dispatch.js +14 -0
- package/dist/control/dispatch.js.map +1 -1
- package/dist/control/types.d.ts +11 -2
- package/dist/display.d.ts +9 -2
- package/dist/display.js +37 -1
- package/dist/display.js.map +1 -1
- package/dist/emit.d.ts +27 -0
- package/dist/emit.js +321 -2
- package/dist/emit.js.map +1 -1
- package/dist/events.d.ts +36 -3
- package/dist/fanout-runner.d.ts +25 -0
- package/dist/fanout-runner.js +54 -0
- package/dist/fanout-runner.js.map +1 -0
- package/dist/file-mod-audit.d.ts +29 -0
- package/dist/file-mod-audit.js +63 -0
- package/dist/file-mod-audit.js.map +1 -0
- package/dist/git-diff.d.ts +19 -0
- package/dist/git-diff.js +74 -0
- package/dist/git-diff.js.map +1 -0
- package/dist/hooks.d.ts +78 -0
- package/dist/hooks.js +239 -0
- package/dist/hooks.js.map +1 -0
- package/dist/index.d.ts +15 -2
- package/dist/index.js +181 -5
- package/dist/index.js.map +1 -1
- package/dist/intent.d.ts +45 -0
- package/dist/intent.js +127 -0
- package/dist/intent.js.map +1 -0
- package/dist/iteration-diff.d.ts +32 -0
- package/dist/iteration-diff.js +92 -0
- package/dist/iteration-diff.js.map +1 -0
- package/dist/iteration.d.ts +20 -0
- package/dist/iteration.js +383 -16
- package/dist/iteration.js.map +1 -1
- package/dist/metareview.d.ts +9 -1
- package/dist/metareview.js +68 -30
- package/dist/metareview.js.map +1 -1
- package/dist/notify.d.ts +9 -2
- package/dist/notify.js +16 -4
- package/dist/notify.js.map +1 -1
- package/dist/parallel.d.ts +16 -0
- package/dist/parallel.js +28 -1
- package/dist/parallel.js.map +1 -1
- package/dist/postconditions.d.ts +25 -0
- package/dist/postconditions.js +107 -0
- package/dist/postconditions.js.map +1 -0
- package/dist/postfire-verify.d.ts +31 -0
- package/dist/postfire-verify.js +64 -0
- package/dist/postfire-verify.js.map +1 -0
- package/dist/premature-quit.d.ts +25 -0
- package/dist/premature-quit.js +54 -0
- package/dist/premature-quit.js.map +1 -0
- package/dist/progress.d.ts +20 -0
- package/dist/progress.js +56 -0
- package/dist/progress.js.map +1 -0
- package/dist/prompt.js +8 -2
- package/dist/prompt.js.map +1 -1
- package/dist/provisional.d.ts +42 -0
- package/dist/provisional.js +92 -0
- package/dist/provisional.js.map +1 -0
- package/dist/registry-bridge.js +25 -0
- package/dist/registry-bridge.js.map +1 -1
- package/dist/resume.d.ts +61 -0
- package/dist/resume.js +226 -0
- package/dist/resume.js.map +1 -0
- package/dist/scratchpad.js +27 -8
- package/dist/scratchpad.js.map +1 -1
- package/dist/stage.d.ts +21 -0
- package/dist/stage.js +131 -0
- package/dist/stage.js.map +1 -0
- package/dist/stop.d.ts +29 -2
- package/dist/stop.js +106 -0
- package/dist/stop.js.map +1 -1
- package/dist/suspend-state.d.ts +32 -0
- package/dist/suspend-state.js +104 -0
- package/dist/suspend-state.js.map +1 -0
- package/dist/tamper.d.ts +21 -0
- package/dist/tamper.js +88 -0
- package/dist/tamper.js.map +1 -0
- package/dist/types.d.ts +247 -2
- package/dist/types.js +91 -1
- package/dist/types.js.map +1 -1
- package/dist/wave/finalize-wave.d.ts +15 -5
- package/dist/wave/finalize-wave.js +56 -2
- package/dist/wave/finalize-wave.js.map +1 -1
- package/dist/wave/launch-branches.d.ts +23 -2
- package/dist/wave/launch-branches.js +56 -3
- package/dist/wave/launch-branches.js.map +1 -1
- package/dist/wave/stage-branch-runner.d.ts +12 -0
- package/dist/wave/stage-branch-runner.js +130 -0
- package/dist/wave/stage-branch-runner.js.map +1 -0
- package/dist/wave/types.d.ts +40 -2
- package/dist/wave.d.ts +32 -1
- package/dist/wave.js +163 -34
- package/dist/wave.js.map +1 -1
- package/package.json +83 -3
package/dist/types.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type { AcpSession } from "@mobrienv/autoloop-backends/acp-client";
|
|
|
2
2
|
import type { ClaudeSdkSession } from "@mobrienv/autoloop-backends/claude-sdk-client";
|
|
3
3
|
import type { PiSession } from "@mobrienv/autoloop-backends/pi-rpc-client";
|
|
4
4
|
import type { AgentMap } from "@mobrienv/autoloop-core/agent-map";
|
|
5
|
+
import type { HookSpec } from "@mobrienv/autoloop-core/hooks-schema";
|
|
5
6
|
import type * as topo from "@mobrienv/autoloop-core/topology";
|
|
6
7
|
import type { LiveControlAdapter } from "./control/adapter.js";
|
|
7
8
|
import type { LoopEventEmitter } from "./events.js";
|
|
@@ -11,13 +12,22 @@ export interface LaunchMetadata {
|
|
|
11
12
|
trigger: TriggerSource;
|
|
12
13
|
createdAt: string;
|
|
13
14
|
parentRunId: string;
|
|
15
|
+
/**
|
|
16
|
+
* Absolute path to a single-file (`.toml`) preset, when the run was launched
|
|
17
|
+
* from one. Config and topology are loaded from this file instead of the
|
|
18
|
+
* `projectDir`'s `autoloops.toml` + `topology.toml`. Empty for directory
|
|
19
|
+
* presets.
|
|
20
|
+
*/
|
|
21
|
+
presetFile?: string;
|
|
14
22
|
}
|
|
15
23
|
export interface ProfileInfo {
|
|
16
24
|
active: string[];
|
|
17
25
|
fragments: Map<string, string>;
|
|
18
26
|
warnings: string[];
|
|
19
27
|
}
|
|
20
|
-
export type VerdictKind = "CONTINUE" | "REDIRECT" | "TAKEOVER" | "EXIT";
|
|
28
|
+
export type VerdictKind = "CONTINUE" | "REDIRECT" | "TAKEOVER" | "EXIT" | "UNKNOWN";
|
|
29
|
+
/** What to do when a metareview yields an UNKNOWN verdict. */
|
|
30
|
+
export type ReviewOnError = "hold" | "exit" | "continue";
|
|
21
31
|
export interface Verdict {
|
|
22
32
|
verdict: VerdictKind;
|
|
23
33
|
confidence: number;
|
|
@@ -26,6 +36,10 @@ export interface Verdict {
|
|
|
26
36
|
takeover_output?: string;
|
|
27
37
|
suggestions?: string[];
|
|
28
38
|
}
|
|
39
|
+
/** Live `command`-backend child process, tracked for signal-based interrupt. */
|
|
40
|
+
export interface CommandSession {
|
|
41
|
+
pid: number;
|
|
42
|
+
}
|
|
29
43
|
export interface LoopContext {
|
|
30
44
|
objective: string;
|
|
31
45
|
topology: topo.Topology;
|
|
@@ -39,11 +53,93 @@ export interface LoopContext {
|
|
|
39
53
|
maxIterationRuntimeMs?: number;
|
|
40
54
|
/** Loop wall-clock budget in ms (0 = disabled). */
|
|
41
55
|
maxRuntimeMs?: number;
|
|
56
|
+
/**
|
|
57
|
+
* Circuit-breaker: max transient/rate-limit pauses before the breaker opens
|
|
58
|
+
* and the run stops with a typed reason. Default 3.
|
|
59
|
+
*/
|
|
60
|
+
transientMaxPauses?: number;
|
|
61
|
+
/** Base backoff (ms) for the transient retry ladder. Default 5000. */
|
|
62
|
+
transientPauseMs?: number;
|
|
63
|
+
/** Upper bound (ms) on the exponential transient backoff. Default 30000. */
|
|
64
|
+
transientBackoffCapMs?: number;
|
|
65
|
+
/**
|
|
66
|
+
* Max times a premature quit (stall with authorized work remaining and no
|
|
67
|
+
* blocker) is re-armed before it escalates to attention. Default 1.
|
|
68
|
+
*/
|
|
69
|
+
prematureMaxRearms?: number;
|
|
42
70
|
};
|
|
43
71
|
completion: {
|
|
44
72
|
promise: string;
|
|
45
73
|
event: string;
|
|
46
74
|
requiredEvents: string[];
|
|
75
|
+
/**
|
|
76
|
+
* Ralph-parity ordering policy (opt-in, default false). When true, a
|
|
77
|
+
* completion claim via `event` is rejected if any other event was
|
|
78
|
+
* emitted after it within the same turn — set-membership alone is not
|
|
79
|
+
* enough. Order-insensitive behavior (unchanged) when false.
|
|
80
|
+
*/
|
|
81
|
+
mustBeLast: boolean;
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
84
|
+
* Permission-enforcement policies (orthogonal to completion gating).
|
|
85
|
+
*/
|
|
86
|
+
policy: {
|
|
87
|
+
/**
|
|
88
|
+
* Ralph-parity emit-boundary audit (opt-in, default false). After every
|
|
89
|
+
* iteration, diffs the working tree against HEAD; if the acting role has
|
|
90
|
+
* `disallowedTools`/`readOnly` and files changed, emits
|
|
91
|
+
* `policy.file_modification_violation` with the role + file list. Purely
|
|
92
|
+
* observational — never alters loop control flow on its own.
|
|
93
|
+
*/
|
|
94
|
+
fileModAudit: boolean;
|
|
95
|
+
};
|
|
96
|
+
/**
|
|
97
|
+
* Out-of-band acceptance gate. On a done-claim the HARNESS (not the agent's
|
|
98
|
+
* session) runs every `verifyCmds` entry in a clean shell; completion is
|
|
99
|
+
* accepted only when all exit 0. A failing command blocks completion and
|
|
100
|
+
* re-injects its output. Empty `verifyCmds` disables the gate.
|
|
101
|
+
*/
|
|
102
|
+
acceptance: {
|
|
103
|
+
verifyCmds: string[];
|
|
104
|
+
timeoutMs: number;
|
|
105
|
+
/**
|
|
106
|
+
* Declarative required-absence guards evaluated at the acceptance gate
|
|
107
|
+
* regardless of agent claims. Each defaults off (opt-in per preset) so
|
|
108
|
+
* existing loops are unaffected. They catch reward-hacks the LLM gates miss:
|
|
109
|
+
* leftover TODO/FIXME, skipped/only/xfail tests, committed secrets, and a
|
|
110
|
+
* dirty/untracked working tree.
|
|
111
|
+
*/
|
|
112
|
+
assertNoTodo: boolean;
|
|
113
|
+
assertNoSkippedTests: boolean;
|
|
114
|
+
assertNoSecrets: boolean;
|
|
115
|
+
assertCleanTree: boolean;
|
|
116
|
+
/**
|
|
117
|
+
* Anti-reward-hack screen: under bypassPermissions the maker can edit the
|
|
118
|
+
* very tests that gate it. When on, a test-backed done-claim is blocked if
|
|
119
|
+
* the run modified test files or inserted tamper patterns (skip/only/xfail,
|
|
120
|
+
* early exit, tautological assertions) on test paths. Default off.
|
|
121
|
+
*/
|
|
122
|
+
screenTestTamper: boolean;
|
|
123
|
+
/**
|
|
124
|
+
* Intent-binding acceptance criteria captured at loop start (the contract
|
|
125
|
+
* between what was asked and what is accepted). Sourced from
|
|
126
|
+
* `[acceptance].criteria` and an "Acceptance criteria" section of the
|
|
127
|
+
* objective. A criterion may bind a deterministic check with ` :: <shell
|
|
128
|
+
* cmd>`; checked criteria gate completion, unchecked ones are advisory.
|
|
129
|
+
*/
|
|
130
|
+
criteria: string[];
|
|
131
|
+
};
|
|
132
|
+
/**
|
|
133
|
+
* Human-in-the-loop. When an agent emits `ask.event`, the loop blocks until
|
|
134
|
+
* an operator responds (via the `respond` control verb) or `timeoutMs`
|
|
135
|
+
* elapses, then injects the answer into the next prompt as guidance.
|
|
136
|
+
* Disabled when `enabled` is false (ask.event is empty).
|
|
137
|
+
*/
|
|
138
|
+
ask: {
|
|
139
|
+
enabled: boolean;
|
|
140
|
+
event: string;
|
|
141
|
+
timeoutMs: number;
|
|
142
|
+
pollMs: number;
|
|
47
143
|
};
|
|
48
144
|
backend: {
|
|
49
145
|
kind: string;
|
|
@@ -55,6 +151,14 @@ export interface LoopContext {
|
|
|
55
151
|
trustAllTools: boolean;
|
|
56
152
|
agent: string;
|
|
57
153
|
model: string;
|
|
154
|
+
profile?: string;
|
|
155
|
+
disallowedTools: string[];
|
|
156
|
+
/**
|
|
157
|
+
* Opt-in cost-telemetry convention for `command`-kind backends: `"file"`
|
|
158
|
+
* reads a JSON usage object the wrapped command wrote to
|
|
159
|
+
* `$AUTOLOOP_USAGE_FILE`. Empty disables extraction (default).
|
|
160
|
+
*/
|
|
161
|
+
usageFrom: string;
|
|
58
162
|
};
|
|
59
163
|
review: {
|
|
60
164
|
enabled: boolean;
|
|
@@ -70,11 +174,52 @@ export interface LoopContext {
|
|
|
70
174
|
trustAllTools: boolean;
|
|
71
175
|
agent: string;
|
|
72
176
|
model: string;
|
|
177
|
+
profile?: string;
|
|
178
|
+
/**
|
|
179
|
+
* Fail-closed routing for an UNKNOWN verdict (malformed/empty/timed-out
|
|
180
|
+
* review, or confidence below `minConfidence`). Default `hold`: stop the
|
|
181
|
+
* loop and raise attention rather than silently continuing.
|
|
182
|
+
*/
|
|
183
|
+
onError: ReviewOnError;
|
|
184
|
+
/**
|
|
185
|
+
* A parsed verdict whose confidence is below this threshold is downgraded
|
|
186
|
+
* to UNKNOWN. Default 0.5. Set 0 to disable confidence gating.
|
|
187
|
+
*/
|
|
188
|
+
minConfidence: number;
|
|
73
189
|
};
|
|
74
190
|
parallel: {
|
|
75
191
|
enabled: boolean;
|
|
76
192
|
maxBranches: number;
|
|
77
193
|
branchTimeoutMs: number;
|
|
194
|
+
/** Loop-level default wave completion strategy (role `aggregate` overrides). */
|
|
195
|
+
aggregate: {
|
|
196
|
+
mode: "wait_for_all" | "first_success" | "timeout";
|
|
197
|
+
timeoutMs: number;
|
|
198
|
+
};
|
|
199
|
+
};
|
|
200
|
+
/**
|
|
201
|
+
* Fan-out `[[stage]]` execution knobs. `concurrency` bounds how many stage
|
|
202
|
+
* branches run at once run-wide (defaults to `defaultConcurrency()`, the
|
|
203
|
+
* same core/os-derived ceiling waves use); `branchTimeoutMs` bounds one
|
|
204
|
+
* branch's wall-clock time.
|
|
205
|
+
*/
|
|
206
|
+
stage: {
|
|
207
|
+
concurrency: number;
|
|
208
|
+
branchTimeoutMs: number;
|
|
209
|
+
};
|
|
210
|
+
hooks: {
|
|
211
|
+
preRun: string;
|
|
212
|
+
preIteration: string;
|
|
213
|
+
postIteration: string;
|
|
214
|
+
postRun: string;
|
|
215
|
+
strict: boolean;
|
|
216
|
+
/**
|
|
217
|
+
* Structured per-hook specs (legacy flat keys + `[[hook]]` entries),
|
|
218
|
+
* merged and template-expanded. This is the engine's source of truth;
|
|
219
|
+
* the flat fields above remain for backward compatibility with existing
|
|
220
|
+
* callers/tests but `specs` is what `runPhaseHooks` iterates.
|
|
221
|
+
*/
|
|
222
|
+
specs: HookSpec[];
|
|
78
223
|
};
|
|
79
224
|
memory: {
|
|
80
225
|
budgetChars: number;
|
|
@@ -85,6 +230,16 @@ export interface LoopContext {
|
|
|
85
230
|
harness: {
|
|
86
231
|
instructions: string;
|
|
87
232
|
};
|
|
233
|
+
/**
|
|
234
|
+
* Preset-declared progress metric: a command whose numeric stdout is the
|
|
235
|
+
* scalar (tests passing, coverage, tasks closed, ...) journaled per iteration
|
|
236
|
+
* to enable drift/convergence detection. Disabled when `metricCmd` is "".
|
|
237
|
+
*/
|
|
238
|
+
progress?: {
|
|
239
|
+
metricCmd: string;
|
|
240
|
+
name: string;
|
|
241
|
+
timeoutMs: number;
|
|
242
|
+
};
|
|
88
243
|
profiles: ProfileInfo;
|
|
89
244
|
paths: {
|
|
90
245
|
projectDir: string;
|
|
@@ -113,6 +268,13 @@ export interface LoopContext {
|
|
|
113
268
|
logLevel: string;
|
|
114
269
|
branchMode: boolean;
|
|
115
270
|
isolationMode: string;
|
|
271
|
+
/**
|
|
272
|
+
* Forces every fan-out stage branch to relaunch rather than reuse a
|
|
273
|
+
* journaled `stage.branch.finish` record from an interrupted prior
|
|
274
|
+
* attempt (`run --no-resume` / `resume --no-resume`). Lives on `runtime`
|
|
275
|
+
* (not config-derived `stage`) because it survives `reloadLoop`.
|
|
276
|
+
*/
|
|
277
|
+
noResume?: boolean;
|
|
116
278
|
};
|
|
117
279
|
launch: LaunchMetadata;
|
|
118
280
|
store: Record<string, unknown>;
|
|
@@ -141,13 +303,31 @@ export interface LoopContext {
|
|
|
141
303
|
claudeSdkSession: {
|
|
142
304
|
current: ClaudeSdkSession | undefined;
|
|
143
305
|
};
|
|
306
|
+
/**
|
|
307
|
+
* Live `command`-backend child process holder, aliased like the other
|
|
308
|
+
* session holders. Populated for the duration of an in-flight `command`
|
|
309
|
+
* iteration (async-spawned, not `execSync`) so `commandControlAdapter` can
|
|
310
|
+
* signal it (SIGUSR1 → SIGTERM → SIGKILL) for the `interrupt` verb. Cleared
|
|
311
|
+
* once the iteration's process exits.
|
|
312
|
+
*/
|
|
313
|
+
commandSession: {
|
|
314
|
+
current: CommandSession | undefined;
|
|
315
|
+
};
|
|
144
316
|
lastVerdict?: Verdict;
|
|
145
317
|
/** Optional structured-event emitter, forwarded from RunOptions.onEvent. */
|
|
146
318
|
onEvent?: LoopEventEmitter;
|
|
147
319
|
controlAdapter?: LiveControlAdapter;
|
|
320
|
+
/** Abort signal for the run; consulted while blocking on a human ask. */
|
|
321
|
+
signal?: AbortSignal;
|
|
148
322
|
}
|
|
149
323
|
export interface RunOptions {
|
|
150
324
|
workDir?: string;
|
|
325
|
+
/**
|
|
326
|
+
* Absolute path to a single-file (`.toml`) preset. When set, config and
|
|
327
|
+
* topology are loaded from this file rather than from `projectDir`'s
|
|
328
|
+
* `autoloops.toml` + `topology.toml`.
|
|
329
|
+
*/
|
|
330
|
+
presetFile?: string;
|
|
151
331
|
backendOverride?: Record<string, unknown>;
|
|
152
332
|
configOverride?: Record<string, unknown>;
|
|
153
333
|
logLevel?: string | null;
|
|
@@ -163,6 +343,11 @@ export interface RunOptions {
|
|
|
163
343
|
mergeStrategy?: string;
|
|
164
344
|
automerge?: boolean;
|
|
165
345
|
keepWorktree?: boolean;
|
|
346
|
+
/**
|
|
347
|
+
* Force every fan-out stage branch to relaunch rather than reuse a
|
|
348
|
+
* journaled `stage.branch.finish` record from an interrupted prior attempt.
|
|
349
|
+
*/
|
|
350
|
+
noResume?: boolean;
|
|
166
351
|
/**
|
|
167
352
|
* Optional abort signal. When provided, the CLI (or SDK caller) owns
|
|
168
353
|
* process signal handling; the harness only listens to this signal for
|
|
@@ -176,8 +361,68 @@ export interface RunOptions {
|
|
|
176
361
|
*/
|
|
177
362
|
onEvent?: LoopEventEmitter;
|
|
178
363
|
}
|
|
364
|
+
/**
|
|
365
|
+
* Versioned, exhaustive set of terminal `RunSummary.stopReason` values.
|
|
366
|
+
* Every literal string ever assigned to `RunSummary.stopReason` anywhere in
|
|
367
|
+
* this package must appear here. Consumers (e.g. ralph v3) can rely on this
|
|
368
|
+
* being a closed set instead of an unbounded `string`, and can use
|
|
369
|
+
* {@link STOP_REASONS} to validate values arriving over an untrusted
|
|
370
|
+
* boundary (e.g. a persisted journal or IPC payload) at runtime.
|
|
371
|
+
*
|
|
372
|
+
* Emission sites (see the enforcement test in
|
|
373
|
+
* `packages/harness/test/harness/stop-reason.test.ts`):
|
|
374
|
+
* - `stop.ts` — `max_iterations`, `backend_failed`, `backend_timeout`,
|
|
375
|
+
* `stalled`, `cost_budget`, `max_runtime`, `review_unknown`,
|
|
376
|
+
* `premature_quit`, `suspended`, and `completeLoop()` which echoes the
|
|
377
|
+
* `completion_event`/`completion_promise`/`verdict_*` literals its
|
|
378
|
+
* callers pass in.
|
|
379
|
+
* - `index.ts` — `interrupted`, `error`, and `verdict_unknown` /
|
|
380
|
+
* `verdict_exit` / `verdict_takeover` (via `completeLoop`).
|
|
381
|
+
* - `iteration.ts` — `completion_event`, `completion_promise` (via
|
|
382
|
+
* `completeLoop`), and a direct `interrupted` result.
|
|
383
|
+
* - `provisional.ts` — `completion_held` (non-terminal `failure.diagnostic`
|
|
384
|
+
* event emitted while a done-claim is parked in `awaiting_acceptance`).
|
|
385
|
+
* - `circuit-breaker.ts` — `auth_failed`, `quota_exhausted`, `rate_limited`,
|
|
386
|
+
* `transient_error`, `backend_failed` (consumed by
|
|
387
|
+
* `stopBackendErrorClass` in `stop.ts`).
|
|
388
|
+
* - `wave.ts` / `wave/finalize-wave.ts` — `parallel_wave_timeout`,
|
|
389
|
+
* `parallel_wave_failed` (terminal, via `stopAfterParallelWave`), and
|
|
390
|
+
* `parallel_wave_invalid` (terminal — `wave.ts` rejects a dispatch while
|
|
391
|
+
* another wave is already active, or an unparsable payload, and that
|
|
392
|
+
* rejection is *also* routed through `stopAfterParallelWave`, ending the
|
|
393
|
+
* run). Note: `parallel_wave_complete` is a distinct, non-terminal
|
|
394
|
+
* internal value used only to trigger `continueAfterParallelJoin`; it
|
|
395
|
+
* never reaches `RunSummary` and is intentionally **not** part of this
|
|
396
|
+
* union.
|
|
397
|
+
*
|
|
398
|
+
* Categories (23 values enumerated by the originating issue, plus two
|
|
399
|
+
* additional real terminal literals — `parallel_wave_invalid` and `suspended` —
|
|
400
|
+
* discovered during implementation; see the parallel-wave and hooks notes above):
|
|
401
|
+
* - success (3): `completed`, `completion_event`, `completion_promise`
|
|
402
|
+
* - failures (7): `backend_failed`, `backend_timeout`, `auth_failed`,
|
|
403
|
+
* `quota_exhausted`, `rate_limited`, `transient_error`, `review_unknown`
|
|
404
|
+
* - stops (7): `max_iterations`, `stalled`, `cost_budget`, `max_runtime`,
|
|
405
|
+
* `premature_quit`, `interrupted`, `suspended`
|
|
406
|
+
* - verdicts (3): `verdict_exit`, `verdict_takeover`, `verdict_unknown`
|
|
407
|
+
* - held (1): `completion_held`
|
|
408
|
+
* - parallel (3): `parallel_wave_timeout`, `parallel_wave_failed`,
|
|
409
|
+
* `parallel_wave_invalid`
|
|
410
|
+
* - error handling (1): `error`
|
|
411
|
+
*
|
|
412
|
+
* Naming-collision warning: `stopReason` is also a field name on the ACP
|
|
413
|
+
* per-turn protocol (`"end_turn" | "cancelled" | "refusal"`, see
|
|
414
|
+
* `packages/cli/src/acp/*.ts` and `packages/backends/src/acp-client.ts`) and
|
|
415
|
+
* on the wave-branch-parsing domain (`BranchResult.stopReason`,
|
|
416
|
+
* `WaveResult.reason` in `wave/types.ts`, which additionally include the
|
|
417
|
+
* synthetic `"branch_process_failed"` value parsed from untrusted
|
|
418
|
+
* subprocess stdout). Those are unrelated, wider domains — do not widen
|
|
419
|
+
* this union to cover them, and do not narrow them to this union.
|
|
420
|
+
*/
|
|
421
|
+
export declare const STOP_REASONS: readonly ["completed", "completion_event", "completion_promise", "backend_failed", "backend_timeout", "auth_failed", "quota_exhausted", "rate_limited", "transient_error", "review_unknown", "max_iterations", "stalled", "cost_budget", "max_runtime", "premature_quit", "interrupted", "suspended", "verdict_exit", "verdict_takeover", "verdict_unknown", "completion_held", "parallel_wave_timeout", "parallel_wave_failed", "parallel_wave_invalid", "error"];
|
|
422
|
+
/** See {@link STOP_REASONS} for documentation of every literal. */
|
|
423
|
+
export type StopReason = (typeof STOP_REASONS)[number];
|
|
179
424
|
export interface RunSummary {
|
|
180
425
|
iterations: number;
|
|
181
|
-
stopReason:
|
|
426
|
+
stopReason: StopReason;
|
|
182
427
|
runId?: string;
|
|
183
428
|
}
|
package/dist/types.js
CHANGED
|
@@ -1,2 +1,92 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Versioned, exhaustive set of terminal `RunSummary.stopReason` values.
|
|
3
|
+
* Every literal string ever assigned to `RunSummary.stopReason` anywhere in
|
|
4
|
+
* this package must appear here. Consumers (e.g. ralph v3) can rely on this
|
|
5
|
+
* being a closed set instead of an unbounded `string`, and can use
|
|
6
|
+
* {@link STOP_REASONS} to validate values arriving over an untrusted
|
|
7
|
+
* boundary (e.g. a persisted journal or IPC payload) at runtime.
|
|
8
|
+
*
|
|
9
|
+
* Emission sites (see the enforcement test in
|
|
10
|
+
* `packages/harness/test/harness/stop-reason.test.ts`):
|
|
11
|
+
* - `stop.ts` — `max_iterations`, `backend_failed`, `backend_timeout`,
|
|
12
|
+
* `stalled`, `cost_budget`, `max_runtime`, `review_unknown`,
|
|
13
|
+
* `premature_quit`, `suspended`, and `completeLoop()` which echoes the
|
|
14
|
+
* `completion_event`/`completion_promise`/`verdict_*` literals its
|
|
15
|
+
* callers pass in.
|
|
16
|
+
* - `index.ts` — `interrupted`, `error`, and `verdict_unknown` /
|
|
17
|
+
* `verdict_exit` / `verdict_takeover` (via `completeLoop`).
|
|
18
|
+
* - `iteration.ts` — `completion_event`, `completion_promise` (via
|
|
19
|
+
* `completeLoop`), and a direct `interrupted` result.
|
|
20
|
+
* - `provisional.ts` — `completion_held` (non-terminal `failure.diagnostic`
|
|
21
|
+
* event emitted while a done-claim is parked in `awaiting_acceptance`).
|
|
22
|
+
* - `circuit-breaker.ts` — `auth_failed`, `quota_exhausted`, `rate_limited`,
|
|
23
|
+
* `transient_error`, `backend_failed` (consumed by
|
|
24
|
+
* `stopBackendErrorClass` in `stop.ts`).
|
|
25
|
+
* - `wave.ts` / `wave/finalize-wave.ts` — `parallel_wave_timeout`,
|
|
26
|
+
* `parallel_wave_failed` (terminal, via `stopAfterParallelWave`), and
|
|
27
|
+
* `parallel_wave_invalid` (terminal — `wave.ts` rejects a dispatch while
|
|
28
|
+
* another wave is already active, or an unparsable payload, and that
|
|
29
|
+
* rejection is *also* routed through `stopAfterParallelWave`, ending the
|
|
30
|
+
* run). Note: `parallel_wave_complete` is a distinct, non-terminal
|
|
31
|
+
* internal value used only to trigger `continueAfterParallelJoin`; it
|
|
32
|
+
* never reaches `RunSummary` and is intentionally **not** part of this
|
|
33
|
+
* union.
|
|
34
|
+
*
|
|
35
|
+
* Categories (23 values enumerated by the originating issue, plus two
|
|
36
|
+
* additional real terminal literals — `parallel_wave_invalid` and `suspended` —
|
|
37
|
+
* discovered during implementation; see the parallel-wave and hooks notes above):
|
|
38
|
+
* - success (3): `completed`, `completion_event`, `completion_promise`
|
|
39
|
+
* - failures (7): `backend_failed`, `backend_timeout`, `auth_failed`,
|
|
40
|
+
* `quota_exhausted`, `rate_limited`, `transient_error`, `review_unknown`
|
|
41
|
+
* - stops (7): `max_iterations`, `stalled`, `cost_budget`, `max_runtime`,
|
|
42
|
+
* `premature_quit`, `interrupted`, `suspended`
|
|
43
|
+
* - verdicts (3): `verdict_exit`, `verdict_takeover`, `verdict_unknown`
|
|
44
|
+
* - held (1): `completion_held`
|
|
45
|
+
* - parallel (3): `parallel_wave_timeout`, `parallel_wave_failed`,
|
|
46
|
+
* `parallel_wave_invalid`
|
|
47
|
+
* - error handling (1): `error`
|
|
48
|
+
*
|
|
49
|
+
* Naming-collision warning: `stopReason` is also a field name on the ACP
|
|
50
|
+
* per-turn protocol (`"end_turn" | "cancelled" | "refusal"`, see
|
|
51
|
+
* `packages/cli/src/acp/*.ts` and `packages/backends/src/acp-client.ts`) and
|
|
52
|
+
* on the wave-branch-parsing domain (`BranchResult.stopReason`,
|
|
53
|
+
* `WaveResult.reason` in `wave/types.ts`, which additionally include the
|
|
54
|
+
* synthetic `"branch_process_failed"` value parsed from untrusted
|
|
55
|
+
* subprocess stdout). Those are unrelated, wider domains — do not widen
|
|
56
|
+
* this union to cover them, and do not narrow them to this union.
|
|
57
|
+
*/
|
|
58
|
+
export const STOP_REASONS = [
|
|
59
|
+
// success (3)
|
|
60
|
+
"completed",
|
|
61
|
+
"completion_event",
|
|
62
|
+
"completion_promise",
|
|
63
|
+
// failures (7)
|
|
64
|
+
"backend_failed",
|
|
65
|
+
"backend_timeout",
|
|
66
|
+
"auth_failed",
|
|
67
|
+
"quota_exhausted",
|
|
68
|
+
"rate_limited",
|
|
69
|
+
"transient_error",
|
|
70
|
+
"review_unknown",
|
|
71
|
+
// stops (7)
|
|
72
|
+
"max_iterations",
|
|
73
|
+
"stalled",
|
|
74
|
+
"cost_budget",
|
|
75
|
+
"max_runtime",
|
|
76
|
+
"premature_quit",
|
|
77
|
+
"interrupted",
|
|
78
|
+
"suspended",
|
|
79
|
+
// verdicts (3)
|
|
80
|
+
"verdict_exit",
|
|
81
|
+
"verdict_takeover",
|
|
82
|
+
"verdict_unknown",
|
|
83
|
+
// held (1)
|
|
84
|
+
"completion_held",
|
|
85
|
+
// parallel (3)
|
|
86
|
+
"parallel_wave_timeout",
|
|
87
|
+
"parallel_wave_failed",
|
|
88
|
+
"parallel_wave_invalid",
|
|
89
|
+
// error handling (1)
|
|
90
|
+
"error",
|
|
91
|
+
];
|
|
2
92
|
//# sourceMappingURL=types.js.map
|
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAsWA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwDG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,cAAc;IACd,WAAW;IACX,kBAAkB;IAClB,oBAAoB;IACpB,eAAe;IACf,gBAAgB;IAChB,iBAAiB;IACjB,aAAa;IACb,iBAAiB;IACjB,cAAc;IACd,iBAAiB;IACjB,gBAAgB;IAChB,YAAY;IACZ,gBAAgB;IAChB,SAAS;IACT,aAAa;IACb,aAAa;IACb,gBAAgB;IAChB,aAAa;IACb,WAAW;IACX,eAAe;IACf,cAAc;IACd,kBAAkB;IAClB,iBAAiB;IACjB,WAAW;IACX,iBAAiB;IACjB,eAAe;IACf,uBAAuB;IACvB,sBAAsB;IACtB,uBAAuB;IACvB,qBAAqB;IACrB,OAAO;CACC,CAAC"}
|
|
@@ -1,9 +1,19 @@
|
|
|
1
1
|
import type { IterationContext } from "../prompt.js";
|
|
2
|
-
import type { LoopContext, RunSummary } from "../types.js";
|
|
3
|
-
import type { BranchResult, IterateFn } from "./types.js";
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
import type { LoopContext, RunSummary, StopReason } from "../types.js";
|
|
3
|
+
import type { AggregateConfig, AggregateOutcome, BranchResult, IterateFn, WaveJoinReason } from "./types.js";
|
|
4
|
+
/**
|
|
5
|
+
* Finalize a joined wave under its configured aggregate strategy.
|
|
6
|
+
* - `wait_for_all` (default): unchanged semantics — any branch timeout or
|
|
7
|
+
* non-success stop reason fails the whole wave.
|
|
8
|
+
* - `first_success`: the wave completes as soon as ONE branch succeeds, even
|
|
9
|
+
* though its siblings were cancelled (not treated as failures).
|
|
10
|
+
* - `timeout`: if the wall-clock deadline was hit, the wave completes if at
|
|
11
|
+
* least one branch had already succeeded, else it is a wave timeout.
|
|
12
|
+
*/
|
|
13
|
+
export declare function finalizeParallelWave(loop: LoopContext, iter: IterationContext, waveId: string, results: BranchResult[], aggregate: AggregateConfig, aggregateOutcome: AggregateOutcome): {
|
|
14
|
+
reason: WaveJoinReason;
|
|
6
15
|
waveId: string;
|
|
7
16
|
};
|
|
17
|
+
export declare function branchSuccessStatus(status: string): boolean;
|
|
8
18
|
export declare function continueAfterParallelJoin(loop: LoopContext, iter: IterationContext, waveId: string, emittedTopic: string, totalElapsedMs: number, iterateFn: IterateFn): Promise<RunSummary>;
|
|
9
|
-
export declare function stopAfterParallelWave(loop: LoopContext, iter: IterationContext, reason:
|
|
19
|
+
export declare function stopAfterParallelWave(loop: LoopContext, iter: IterationContext, reason: StopReason, waveId: string): RunSummary;
|
|
@@ -2,7 +2,30 @@ import { joinCsv, jsonField } from "@mobrienv/autoloop-core";
|
|
|
2
2
|
import { appendEvent, appendHarnessEvent, } from "@mobrienv/autoloop-core/journal";
|
|
3
3
|
import * as topology from "@mobrienv/autoloop-core/topology";
|
|
4
4
|
import { parallelDispatchBase, parallelJoinedTopic } from "../emit.js";
|
|
5
|
-
|
|
5
|
+
/**
|
|
6
|
+
* Finalize a joined wave under its configured aggregate strategy.
|
|
7
|
+
* - `wait_for_all` (default): unchanged semantics — any branch timeout or
|
|
8
|
+
* non-success stop reason fails the whole wave.
|
|
9
|
+
* - `first_success`: the wave completes as soon as ONE branch succeeds, even
|
|
10
|
+
* though its siblings were cancelled (not treated as failures).
|
|
11
|
+
* - `timeout`: if the wall-clock deadline was hit, the wave completes if at
|
|
12
|
+
* least one branch had already succeeded, else it is a wave timeout.
|
|
13
|
+
*/
|
|
14
|
+
export function finalizeParallelWave(loop, iter, waveId, results, aggregate, aggregateOutcome) {
|
|
15
|
+
appendWaveAggregate(loop, iter, waveId, aggregate, aggregateOutcome);
|
|
16
|
+
if (aggregate.mode === "first_success") {
|
|
17
|
+
if (aggregateOutcome.satisfiedByBranchId) {
|
|
18
|
+
return { reason: "parallel_wave_complete", waveId };
|
|
19
|
+
}
|
|
20
|
+
return finalizeNoSuccess(loop, iter, waveId, results);
|
|
21
|
+
}
|
|
22
|
+
if (aggregate.mode === "timeout" && aggregateOutcome.aggregateTimedOut) {
|
|
23
|
+
const anySucceeded = results.some((r) => branchSuccessStatus(r.stopReason));
|
|
24
|
+
if (anySucceeded)
|
|
25
|
+
return { reason: "parallel_wave_complete", waveId };
|
|
26
|
+
return finalizeNoSuccess(loop, iter, waveId, results);
|
|
27
|
+
}
|
|
28
|
+
// wait_for_all (default), or timeout mode that resolved before its deadline.
|
|
6
29
|
const timedOut = results
|
|
7
30
|
.filter((r) => r.stopReason === "backend_timeout")
|
|
8
31
|
.map((r) => r.branchId);
|
|
@@ -23,7 +46,38 @@ export function finalizeParallelWave(loop, iter, waveId, results) {
|
|
|
23
46
|
}
|
|
24
47
|
return { reason: "parallel_wave_complete", waveId };
|
|
25
48
|
}
|
|
26
|
-
|
|
49
|
+
/** No branch succeeded (first_success/timeout modes without a winner):
|
|
50
|
+
* prefer a `wave.timeout` verdict when any branch actually timed out
|
|
51
|
+
* (backend- or aggregate-level), otherwise `wave.failed`. */
|
|
52
|
+
function finalizeNoSuccess(loop, iter, waveId, results) {
|
|
53
|
+
const timedOut = results
|
|
54
|
+
.filter((r) => r.stopReason === "backend_timeout" ||
|
|
55
|
+
r.stopReason === "wave_aggregate_timeout")
|
|
56
|
+
.map((r) => r.branchId);
|
|
57
|
+
if (timedOut.length > 0) {
|
|
58
|
+
appendEvent(loop.paths.journalFile, loop.runtime.runId, String(iter.iteration), "wave.timeout", jsonField("wave_id", waveId) +
|
|
59
|
+
", " +
|
|
60
|
+
jsonField("timed_out_branches", joinCsv(timedOut)));
|
|
61
|
+
return { reason: "parallel_wave_timeout", waveId };
|
|
62
|
+
}
|
|
63
|
+
const failed = results
|
|
64
|
+
.filter((r) => !branchSuccessStatus(r.stopReason))
|
|
65
|
+
.map((r) => r.branchId);
|
|
66
|
+
appendEvent(loop.paths.journalFile, loop.runtime.runId, String(iter.iteration), "wave.failed", jsonField("wave_id", waveId) +
|
|
67
|
+
", " +
|
|
68
|
+
jsonField("failed_branches", joinCsv(failed)));
|
|
69
|
+
return { reason: "parallel_wave_failed", waveId };
|
|
70
|
+
}
|
|
71
|
+
function appendWaveAggregate(loop, iter, waveId, aggregate, aggregateOutcome) {
|
|
72
|
+
appendEvent(loop.paths.journalFile, loop.runtime.runId, String(iter.iteration), "wave.aggregate", jsonField("wave_id", waveId) +
|
|
73
|
+
", " +
|
|
74
|
+
jsonField("mode", aggregate.mode) +
|
|
75
|
+
", " +
|
|
76
|
+
jsonField("satisfied_by_branch_id", aggregateOutcome.satisfiedByBranchId ?? "") +
|
|
77
|
+
", " +
|
|
78
|
+
jsonField("aggregate_timed_out", String(aggregateOutcome.aggregateTimedOut)));
|
|
79
|
+
}
|
|
80
|
+
export function branchSuccessStatus(status) {
|
|
27
81
|
return (status === "max_iterations" ||
|
|
28
82
|
status === "completion_event" ||
|
|
29
83
|
status === "completion_promise");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"finalize-wave.js","sourceRoot":"","sources":["../../src/wave/finalize-wave.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EACL,WAAW,EACX,kBAAkB,GACnB,MAAM,iCAAiC,CAAC;AACzC,OAAO,KAAK,QAAQ,MAAM,kCAAkC,CAAC;AAC7D,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"finalize-wave.js","sourceRoot":"","sources":["../../src/wave/finalize-wave.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EACL,WAAW,EACX,kBAAkB,GACnB,MAAM,iCAAiC,CAAC;AACzC,OAAO,KAAK,QAAQ,MAAM,kCAAkC,CAAC;AAC7D,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAWvE;;;;;;;;GAQG;AACH,MAAM,UAAU,oBAAoB,CAClC,IAAiB,EACjB,IAAsB,EACtB,MAAc,EACd,OAAuB,EACvB,SAA0B,EAC1B,gBAAkC;IAElC,mBAAmB,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,gBAAgB,CAAC,CAAC;IAErE,IAAI,SAAS,CAAC,IAAI,KAAK,eAAe,EAAE,CAAC;QACvC,IAAI,gBAAgB,CAAC,mBAAmB,EAAE,CAAC;YACzC,OAAO,EAAE,MAAM,EAAE,wBAAwB,EAAE,MAAM,EAAE,CAAC;QACtD,CAAC;QACD,OAAO,iBAAiB,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IACxD,CAAC;IAED,IAAI,SAAS,CAAC,IAAI,KAAK,SAAS,IAAI,gBAAgB,CAAC,iBAAiB,EAAE,CAAC;QACvE,MAAM,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,mBAAmB,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;QAC5E,IAAI,YAAY;YAAE,OAAO,EAAE,MAAM,EAAE,wBAAwB,EAAE,MAAM,EAAE,CAAC;QACtE,OAAO,iBAAiB,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IACxD,CAAC;IAED,6EAA6E;IAC7E,MAAM,QAAQ,GAAG,OAAO;SACrB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,KAAK,iBAAiB,CAAC;SACjD,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IAC1B,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,WAAW,CACT,IAAI,CAAC,KAAK,CAAC,WAAW,EACtB,IAAI,CAAC,OAAO,CAAC,KAAK,EAClB,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,EACtB,cAAc,EACd,SAAS,CAAC,SAAS,EAAE,MAAM,CAAC;YAC1B,IAAI;YACJ,SAAS,CAAC,oBAAoB,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CACrD,CAAC;QACF,OAAO,EAAE,MAAM,EAAE,uBAAuB,EAAE,MAAM,EAAE,CAAC;IACrD,CAAC;IACD,MAAM,MAAM,GAAG,OAAO;SACnB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;SACjD,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IAC1B,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,WAAW,CACT,IAAI,CAAC,KAAK,CAAC,WAAW,EACtB,IAAI,CAAC,OAAO,CAAC,KAAK,EAClB,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,EACtB,aAAa,EACb,SAAS,CAAC,SAAS,EAAE,MAAM,CAAC;YAC1B,IAAI;YACJ,SAAS,CAAC,iBAAiB,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAChD,CAAC;QACF,OAAO,EAAE,MAAM,EAAE,sBAAsB,EAAE,MAAM,EAAE,CAAC;IACpD,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,wBAAwB,EAAE,MAAM,EAAE,CAAC;AACtD,CAAC;AAED;;6DAE6D;AAC7D,SAAS,iBAAiB,CACxB,IAAiB,EACjB,IAAsB,EACtB,MAAc,EACd,OAAuB;IAEvB,MAAM,QAAQ,GAAG,OAAO;SACrB,MAAM,CACL,CAAC,CAAC,EAAE,EAAE,CACJ,CAAC,CAAC,UAAU,KAAK,iBAAiB;QAClC,CAAC,CAAC,UAAU,KAAK,wBAAwB,CAC5C;SACA,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IAC1B,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,WAAW,CACT,IAAI,CAAC,KAAK,CAAC,WAAW,EACtB,IAAI,CAAC,OAAO,CAAC,KAAK,EAClB,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,EACtB,cAAc,EACd,SAAS,CAAC,SAAS,EAAE,MAAM,CAAC;YAC1B,IAAI;YACJ,SAAS,CAAC,oBAAoB,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CACrD,CAAC;QACF,OAAO,EAAE,MAAM,EAAE,uBAAuB,EAAE,MAAM,EAAE,CAAC;IACrD,CAAC;IACD,MAAM,MAAM,GAAG,OAAO;SACnB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;SACjD,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IAC1B,WAAW,CACT,IAAI,CAAC,KAAK,CAAC,WAAW,EACtB,IAAI,CAAC,OAAO,CAAC,KAAK,EAClB,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,EACtB,aAAa,EACb,SAAS,CAAC,SAAS,EAAE,MAAM,CAAC;QAC1B,IAAI;QACJ,SAAS,CAAC,iBAAiB,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAChD,CAAC;IACF,OAAO,EAAE,MAAM,EAAE,sBAAsB,EAAE,MAAM,EAAE,CAAC;AACpD,CAAC;AAED,SAAS,mBAAmB,CAC1B,IAAiB,EACjB,IAAsB,EACtB,MAAc,EACd,SAA0B,EAC1B,gBAAkC;IAElC,WAAW,CACT,IAAI,CAAC,KAAK,CAAC,WAAW,EACtB,IAAI,CAAC,OAAO,CAAC,KAAK,EAClB,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,EACtB,gBAAgB,EAChB,SAAS,CAAC,SAAS,EAAE,MAAM,CAAC;QAC1B,IAAI;QACJ,SAAS,CAAC,MAAM,EAAE,SAAS,CAAC,IAAI,CAAC;QACjC,IAAI;QACJ,SAAS,CACP,wBAAwB,EACxB,gBAAgB,CAAC,mBAAmB,IAAI,EAAE,CAC3C;QACD,IAAI;QACJ,SAAS,CACP,qBAAqB,EACrB,MAAM,CAAC,gBAAgB,CAAC,iBAAiB,CAAC,CAC3C,CACJ,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,MAAc;IAChD,OAAO,CACL,MAAM,KAAK,gBAAgB;QAC3B,MAAM,KAAK,kBAAkB;QAC7B,MAAM,KAAK,oBAAoB,CAChC,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAC7C,IAAiB,EACjB,IAAsB,EACtB,MAAc,EACd,YAAoB,EACpB,cAAsB,EACtB,SAAoB;IAEpB,MAAM,WAAW,GAAG,mBAAmB,CAAC,YAAY,CAAC,CAAC;IACtD,oBAAoB,CAClB,IAAI,EACJ,IAAI,EACJ,MAAM,EACN,YAAY,EACZ,WAAW,EACX,cAAc,CACf,CAAC;IACF,kBAAkB,CAChB,IAAI,CAAC,KAAK,CAAC,WAAW,EACtB,IAAI,CAAC,OAAO,CAAC,KAAK,EAClB,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,EACtB,WAAW,EACX,MAAM,CACP,CAAC;IACF,OAAO,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,qBAAqB,CACnC,IAAiB,EACjB,IAAsB,EACtB,MAAkB,EAClB,MAAc;IAEd,MAAM,MAAM,GACV,SAAS,CAAC,QAAQ,EAAE,MAAM,CAAC;QAC3B,IAAI;QACJ,SAAS,CAAC,WAAW,EAAE,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC9C,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,SAAS,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACtD,WAAW,CACT,IAAI,CAAC,KAAK,CAAC,WAAW,EACtB,IAAI,CAAC,OAAO,CAAC,KAAK,EAClB,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,EACtB,WAAW,EACX,MAAM,CACP,CAAC;IACF,OAAO,EAAE,UAAU,EAAE,IAAI,CAAC,SAAS,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC;AAC5D,CAAC;AAED,SAAS,wBAAwB,CAC/B,IAAsB,EACtB,YAAoB;IAEpB,IAAI,YAAY,KAAK,kBAAkB;QAAE,OAAO,IAAI,CAAC,WAAW,CAAC;IACjE,OAAO,oBAAoB,CAAC,YAAY,CAAC,IAAI,IAAI,CAAC,WAAW,CAAC;AAChE,CAAC;AAED,SAAS,uBAAuB,CAC9B,IAAsB,EACtB,YAAoB,EACpB,WAAmB;IAEnB,IAAI,YAAY,KAAK,kBAAkB;QAAE,OAAO,IAAI,CAAC,WAAW,CAAC;IACjE,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,SAAS,iBAAiB,CACxB,IAAiB,EACjB,IAAsB,EACtB,YAAoB,EACpB,YAAoB;IAEpB,IAAI,YAAY,KAAK,kBAAkB;QAAE,OAAO,IAAI,CAAC,YAAY,CAAC;IAClE,OAAO,QAAQ,CAAC,cAAc,CAAC,IAAI,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;AAC9D,CAAC;AAED,SAAS,kBAAkB,CACzB,IAAiB,EACjB,IAAsB,EACtB,YAAoB,EACpB,YAAoB;IAEpB,IAAI,YAAY,KAAK,kBAAkB;QAAE,OAAO,IAAI,CAAC,aAAa,CAAC;IACnE,OAAO,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;AAC7D,CAAC;AAED,SAAS,oBAAoB,CAC3B,IAAiB,EACjB,IAAsB,EACtB,MAAc,EACd,YAAoB,EACpB,WAAmB,EACnB,YAAoB;IAEpB,MAAM,YAAY,GAAG,wBAAwB,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;IAClE,MAAM,iBAAiB,GAAG,uBAAuB,CAC/C,IAAI,EACJ,YAAY,EACZ,WAAW,CACZ,CAAC;IACF,MAAM,WAAW,GAAG,iBAAiB,CAAC,IAAI,EAAE,IAAI,EAAE,YAAY,EAAE,YAAY,CAAC,CAAC;IAC9E,MAAM,YAAY,GAAG,kBAAkB,CACrC,IAAI,EACJ,IAAI,EACJ,YAAY,EACZ,YAAY,CACb,CAAC;IACF,WAAW,CACT,IAAI,CAAC,KAAK,CAAC,WAAW,EACtB,IAAI,CAAC,OAAO,CAAC,KAAK,EAClB,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,EACtB,kBAAkB,EAClB,SAAS,CAAC,SAAS,EAAE,MAAM,CAAC;QAC1B,IAAI;QACJ,SAAS,CAAC,eAAe,EAAE,YAAY,CAAC;QACxC,IAAI;QACJ,SAAS,CAAC,cAAc,EAAE,WAAW,CAAC;QACtC,IAAI;QACJ,SAAS,CAAC,eAAe,EAAE,YAAY,CAAC;QACxC,IAAI;QACJ,SAAS,CAAC,qBAAqB,EAAE,iBAAiB,CAAC;QACnD,IAAI;QACJ,SAAS,CAAC,cAAc,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;QAC/C,IAAI;QACJ,SAAS,CAAC,eAAe,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;QACjD,IAAI;QACJ,SAAS,CAAC,YAAY,EAAE,MAAM,CAAC,YAAY,CAAC,CAAC,CAChD,CAAC;AACJ,CAAC"}
|
|
@@ -1,6 +1,27 @@
|
|
|
1
1
|
import type { IterationContext } from "../prompt.js";
|
|
2
2
|
import type { LoopContext } from "../types.js";
|
|
3
|
-
import type { BranchResult, BranchSpec } from "./types.js";
|
|
3
|
+
import type { AggregateConfig, AggregateOutcome, BranchResult, BranchSpec } from "./types.js";
|
|
4
4
|
export declare function prepareParallelBranches(loop: LoopContext, iter: IterationContext, waveId: string, waveDir: string, emittedTopic: string, objectives: string[]): BranchSpec[];
|
|
5
5
|
export declare function launchParallelBranches(loop: LoopContext, specs: BranchSpec[]): BranchSpec[];
|
|
6
|
-
export
|
|
6
|
+
export interface JoinResult {
|
|
7
|
+
results: BranchResult[];
|
|
8
|
+
aggregateOutcome: AggregateOutcome;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Poll all branches to completion. The default `wait_for_all` aggregate mode
|
|
12
|
+
* blocks until every branch has a result (unchanged from prior behavior). Two
|
|
13
|
+
* additional modes let a wave resolve early:
|
|
14
|
+
* - `first_success`: return as soon as one branch succeeds, terminating the
|
|
15
|
+
* remaining pending branches (their results are synthesized as cancelled).
|
|
16
|
+
* - `timeout`: bound the whole wave's wall clock; branches still pending at
|
|
17
|
+
* the deadline are terminated and synthesized as timed out.
|
|
18
|
+
*/
|
|
19
|
+
export declare function joinParallelBranches(loop: LoopContext, iter: IterationContext, waveId: string, pending: BranchSpec[], aggregate: AggregateConfig, waveStartMs: number): JoinResult;
|
|
20
|
+
/**
|
|
21
|
+
* Write the `launch.json` a `branch-run` subprocess reads to drive one
|
|
22
|
+
* isolated branch iteration. Exported so the fan-out stage runner
|
|
23
|
+
* (`wave/stage-branch-runner.ts`) can launch stage branches through the exact
|
|
24
|
+
* same supervisor/`branch-run` spawn machinery as parallel-wave branches,
|
|
25
|
+
* rather than a second bespoke spawner.
|
|
26
|
+
*/
|
|
27
|
+
export declare function writeBranchLaunch(spec: BranchSpec, loop: LoopContext): void;
|