@mobrienv/autoloop-harness 0.7.0

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 (70) hide show
  1. package/dist/artifacts.d.ts +50 -0
  2. package/dist/artifacts.js +333 -0
  3. package/dist/artifacts.js.map +1 -0
  4. package/dist/config-helpers.d.ts +36 -0
  5. package/dist/config-helpers.js +427 -0
  6. package/dist/config-helpers.js.map +1 -0
  7. package/dist/coordination.d.ts +1 -0
  8. package/dist/coordination.js +126 -0
  9. package/dist/coordination.js.map +1 -0
  10. package/dist/display.d.ts +21 -0
  11. package/dist/display.js +177 -0
  12. package/dist/display.js.map +1 -0
  13. package/dist/emit.d.ts +21 -0
  14. package/dist/emit.js +243 -0
  15. package/dist/emit.js.map +1 -0
  16. package/dist/events.d.ts +56 -0
  17. package/dist/events.js +9 -0
  18. package/dist/events.js.map +1 -0
  19. package/dist/index.d.ts +6 -0
  20. package/dist/index.js +272 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/iteration.d.ts +16 -0
  23. package/dist/iteration.js +153 -0
  24. package/dist/iteration.js.map +1 -0
  25. package/dist/metareview.d.ts +6 -0
  26. package/dist/metareview.js +104 -0
  27. package/dist/metareview.js.map +1 -0
  28. package/dist/metrics.d.ts +12 -0
  29. package/dist/metrics.js +177 -0
  30. package/dist/metrics.js.map +1 -0
  31. package/dist/parallel.d.ts +37 -0
  32. package/dist/parallel.js +242 -0
  33. package/dist/parallel.js.map +1 -0
  34. package/dist/pi-adapter.d.ts +1 -0
  35. package/dist/pi-adapter.js +220 -0
  36. package/dist/pi-adapter.js.map +1 -0
  37. package/dist/prompt.d.ts +46 -0
  38. package/dist/prompt.js +446 -0
  39. package/dist/prompt.js.map +1 -0
  40. package/dist/registry-bridge.d.ts +7 -0
  41. package/dist/registry-bridge.js +63 -0
  42. package/dist/registry-bridge.js.map +1 -0
  43. package/dist/scratchpad.d.ts +2 -0
  44. package/dist/scratchpad.js +65 -0
  45. package/dist/scratchpad.js.map +1 -0
  46. package/dist/stop.d.ts +5 -0
  47. package/dist/stop.js +81 -0
  48. package/dist/stop.js.map +1 -0
  49. package/dist/tools.d.ts +3 -0
  50. package/dist/tools.js +65 -0
  51. package/dist/tools.js.map +1 -0
  52. package/dist/types.d.ts +137 -0
  53. package/dist/types.js +2 -0
  54. package/dist/types.js.map +1 -0
  55. package/dist/wave/finalize-wave.d.ts +9 -0
  56. package/dist/wave/finalize-wave.js +86 -0
  57. package/dist/wave/finalize-wave.js.map +1 -0
  58. package/dist/wave/launch-branches.d.ts +6 -0
  59. package/dist/wave/launch-branches.js +313 -0
  60. package/dist/wave/launch-branches.js.map +1 -0
  61. package/dist/wave/parse-objectives.d.ts +3 -0
  62. package/dist/wave/parse-objectives.js +32 -0
  63. package/dist/wave/parse-objectives.js.map +1 -0
  64. package/dist/wave/types.d.ts +43 -0
  65. package/dist/wave/types.js +2 -0
  66. package/dist/wave/types.js.map +1 -0
  67. package/dist/wave.d.ts +6 -0
  68. package/dist/wave.js +158 -0
  69. package/dist/wave.js.map +1 -0
  70. package/package.json +100 -0
package/dist/stop.js ADDED
@@ -0,0 +1,81 @@
1
+ import { jsonField } from "@mobrienv/autoloop-core";
2
+ import { appendEvent } from "@mobrienv/autoloop-core/journal";
3
+ import { lastNChars, log } from "./display.js";
4
+ import { registryComplete, registryStop } from "./registry-bridge.js";
5
+ export function stopMaxIterations(loop, iteration) {
6
+ const completed = iteration <= 1 ? 0 : iteration - 1;
7
+ log(loop, "warn", `loop stop reason=max_iterations completed_iterations=${completed} max_iterations=${loop.limits.maxIterations}`);
8
+ loop.onEvent?.({
9
+ type: "progress",
10
+ runId: loop.runtime.runId,
11
+ iteration: completed,
12
+ recentEvent: "loop.stop",
13
+ allowedRoles: [],
14
+ outcome: "stop:max_iterations",
15
+ });
16
+ log(loop, "info", `Reached iteration limit: ${completed}/${loop.limits.maxIterations} iterations completed.`);
17
+ appendEvent(loop.paths.journalFile, loop.runtime.runId, "", "loop.stop", jsonField("reason", "max_iterations") +
18
+ ", " +
19
+ jsonField("completed_iterations", String(completed)) +
20
+ ", " +
21
+ jsonField("stopped_before_iteration", String(iteration)) +
22
+ ", " +
23
+ jsonField("max_iterations", String(loop.limits.maxIterations)));
24
+ registryStop(loop, completed, "max_iterations");
25
+ return { iterations: completed, stopReason: "max_iterations" };
26
+ }
27
+ export function stopBackendFailed(loop, iteration, output) {
28
+ log(loop, "error", `loop stop reason=backend_failed iteration=${iteration}`);
29
+ loop.onEvent?.({
30
+ type: "progress",
31
+ runId: loop.runtime.runId,
32
+ iteration,
33
+ recentEvent: "loop.stop",
34
+ allowedRoles: [],
35
+ outcome: "stop:backend_failed",
36
+ });
37
+ loop.onEvent?.({
38
+ type: "failure.diagnostic",
39
+ output,
40
+ stopReason: "backend_failed",
41
+ });
42
+ const tail = lastNChars(output, 500);
43
+ appendEvent(loop.paths.journalFile, loop.runtime.runId, String(iteration), "loop.stop", jsonField("reason", "backend_failed") +
44
+ ", " +
45
+ jsonField("iteration", String(iteration)) +
46
+ ", " +
47
+ jsonField("output_tail", tail));
48
+ registryStop(loop, iteration, "backend_failed");
49
+ return { iterations: iteration, stopReason: "backend_failed" };
50
+ }
51
+ export function stopBackendTimeout(loop, iteration, output) {
52
+ log(loop, "error", `loop stop reason=backend_timeout iteration=${iteration}`);
53
+ loop.onEvent?.({
54
+ type: "progress",
55
+ runId: loop.runtime.runId,
56
+ iteration,
57
+ recentEvent: "loop.stop",
58
+ allowedRoles: [],
59
+ outcome: "stop:backend_timeout",
60
+ });
61
+ loop.onEvent?.({
62
+ type: "failure.diagnostic",
63
+ output,
64
+ stopReason: "backend_timeout",
65
+ });
66
+ const tail = lastNChars(output, 500);
67
+ appendEvent(loop.paths.journalFile, loop.runtime.runId, String(iteration), "loop.stop", jsonField("reason", "backend_timeout") +
68
+ ", " +
69
+ jsonField("iteration", String(iteration)) +
70
+ ", " +
71
+ jsonField("output_tail", tail));
72
+ registryStop(loop, iteration, "backend_timeout");
73
+ return { iterations: iteration, stopReason: "backend_timeout" };
74
+ }
75
+ export function completeLoop(loop, iteration, reason) {
76
+ log(loop, "info", `loop complete reason=${reason}`);
77
+ appendEvent(loop.paths.journalFile, loop.runtime.runId, String(iteration), "loop.complete", jsonField("reason", reason));
78
+ registryComplete(loop, iteration, reason);
79
+ return { iterations: iteration, stopReason: reason };
80
+ }
81
+ //# sourceMappingURL=stop.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stop.js","sourceRoot":"","sources":["../src/stop.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { LoopContext } from "./index.js";
2
+ export declare function emitToolScript(loop: LoopContext): string;
3
+ export declare function piAdapterScript(loop: LoopContext): string;
package/dist/tools.js ADDED
@@ -0,0 +1,65 @@
1
+ import { joinCsv, shellQuote } from "@mobrienv/autoloop-core";
2
+ export function emitToolScript(loop) {
3
+ return ("#!/bin/sh\n" +
4
+ "set -eu\n" +
5
+ "export AUTOLOOP_PROJECT_DIR=" +
6
+ shellQuote(loop.paths.projectDir) +
7
+ "\n" +
8
+ "export AUTOLOOP_STATE_DIR=" +
9
+ shellQuote(loop.paths.stateDir) +
10
+ "\n" +
11
+ "export AUTOLOOP_JOURNAL_FILE=" +
12
+ shellQuote(loop.paths.journalFile) +
13
+ "\n" +
14
+ "export AUTOLOOP_EVENTS_FILE=" +
15
+ shellQuote(loop.paths.journalFile) +
16
+ "\n" +
17
+ "export AUTOLOOP_MEMORY_FILE=" +
18
+ shellQuote(loop.paths.memoryFile) +
19
+ "\n" +
20
+ "export AUTOLOOP_TASKS_FILE=" +
21
+ shellQuote(loop.paths.tasksFile) +
22
+ "\n" +
23
+ "export AUTOLOOP_RUN_ID=" +
24
+ shellQuote(loop.runtime.runId) +
25
+ "\n" +
26
+ "export AUTOLOOP_COMPLETION_EVENT=" +
27
+ shellQuote(loop.completion.event) +
28
+ "\n" +
29
+ "export AUTOLOOP_REQUIRED_EVENTS=" +
30
+ shellQuote(joinCsv(loop.completion.requiredEvents)) +
31
+ "\n" +
32
+ "export AUTOLOOP_BIN=" +
33
+ shellQuote(loop.paths.toolPath) +
34
+ "\n" +
35
+ "stdout_file=$(mktemp)\n" +
36
+ "stderr_file=$(mktemp)\n" +
37
+ "cleanup() {\n" +
38
+ ' rm -f "$stdout_file" "$stderr_file"\n' +
39
+ "}\n" +
40
+ "trap cleanup EXIT\n" +
41
+ "if " +
42
+ loop.runtime.selfCommand +
43
+ ' "$@" >"$stdout_file" 2>"$stderr_file"; then\n' +
44
+ " status=0\n" +
45
+ "else\n" +
46
+ " status=$?\n" +
47
+ "fi\n" +
48
+ 'cat "$stderr_file" >&2\n' +
49
+ 'if [ "${1:-}" = "emit" ]; then\n' +
50
+ " inner=$(sed -n 's/^%{:exit_code => \\([0-9][0-9]*\\),.*$/\\1/p' \"$stdout_file\" | tail -n 1)\n" +
51
+ ' if [ -n "$inner" ]; then\n' +
52
+ ' exit "$inner"\n' +
53
+ " fi\n" +
54
+ "fi\n" +
55
+ 'cat "$stdout_file"\n' +
56
+ 'exit "$status"\n');
57
+ }
58
+ export function piAdapterScript(loop) {
59
+ return ("#!/bin/sh\n" +
60
+ "set -eu\n" +
61
+ "exec " +
62
+ loop.runtime.selfCommand +
63
+ ' pi-adapter "$@"\n');
64
+ }
65
+ //# sourceMappingURL=tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.js","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAG9D,MAAM,UAAU,cAAc,CAAC,IAAiB;IAC9C,OAAO,CACL,aAAa;QACb,WAAW;QACX,8BAA8B;QAC9B,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC;QACjC,IAAI;QACJ,4BAA4B;QAC5B,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC;QAC/B,IAAI;QACJ,+BAA+B;QAC/B,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC;QAClC,IAAI;QACJ,8BAA8B;QAC9B,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC;QAClC,IAAI;QACJ,8BAA8B;QAC9B,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC;QACjC,IAAI;QACJ,6BAA6B;QAC7B,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC;QAChC,IAAI;QACJ,yBAAyB;QACzB,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC;QAC9B,IAAI;QACJ,mCAAmC;QACnC,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC;QACjC,IAAI;QACJ,kCAAkC;QAClC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;QACnD,IAAI;QACJ,sBAAsB;QACtB,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC;QAC/B,IAAI;QACJ,yBAAyB;QACzB,yBAAyB;QACzB,eAAe;QACf,yCAAyC;QACzC,KAAK;QACL,qBAAqB;QACrB,KAAK;QACL,IAAI,CAAC,OAAO,CAAC,WAAW;QACxB,gDAAgD;QAChD,cAAc;QACd,QAAQ;QACR,eAAe;QACf,MAAM;QACN,0BAA0B;QAC1B,kCAAkC;QAClC,mGAAmG;QACnG,8BAA8B;QAC9B,qBAAqB;QACrB,QAAQ;QACR,MAAM;QACN,sBAAsB;QACtB,kBAAkB,CACnB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,IAAiB;IAC/C,OAAO,CACL,aAAa;QACb,WAAW;QACX,OAAO;QACP,IAAI,CAAC,OAAO,CAAC,WAAW;QACxB,oBAAoB,CACrB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,137 @@
1
+ import type { AcpSession } from "@mobrienv/autoloop-backends/acp-client";
2
+ import type { AgentMap } from "@mobrienv/autoloop-core/agent-map";
3
+ import type * as topo from "@mobrienv/autoloop-core/topology";
4
+ import type { LoopEventEmitter } from "./events.js";
5
+ export type TriggerSource = "cli" | "chain" | "branch";
6
+ export interface LaunchMetadata {
7
+ preset: string;
8
+ trigger: TriggerSource;
9
+ createdAt: string;
10
+ parentRunId: string;
11
+ }
12
+ export interface ProfileInfo {
13
+ active: string[];
14
+ fragments: Map<string, string>;
15
+ warnings: string[];
16
+ }
17
+ export type VerdictKind = "CONTINUE" | "REDIRECT" | "TAKEOVER" | "EXIT";
18
+ export interface Verdict {
19
+ verdict: VerdictKind;
20
+ confidence: number;
21
+ reasoning: string;
22
+ redirect_prompt?: string;
23
+ takeover_output?: string;
24
+ suggestions?: string[];
25
+ }
26
+ export interface LoopContext {
27
+ objective: string;
28
+ topology: topo.Topology;
29
+ limits: {
30
+ maxIterations: number;
31
+ };
32
+ completion: {
33
+ promise: string;
34
+ event: string;
35
+ requiredEvents: string[];
36
+ };
37
+ backend: {
38
+ kind: string;
39
+ command: string;
40
+ args: string[];
41
+ promptMode: string;
42
+ timeoutMs: number;
43
+ };
44
+ review: {
45
+ enabled: boolean;
46
+ every: number;
47
+ adversarialFirst: boolean;
48
+ kind: string;
49
+ command: string;
50
+ args: string[];
51
+ promptMode: string;
52
+ prompt: string;
53
+ timeoutMs: number;
54
+ };
55
+ parallel: {
56
+ enabled: boolean;
57
+ maxBranches: number;
58
+ branchTimeoutMs: number;
59
+ };
60
+ memory: {
61
+ budgetChars: number;
62
+ };
63
+ tasks: {
64
+ budgetChars: number;
65
+ };
66
+ harness: {
67
+ instructions: string;
68
+ };
69
+ profiles: ProfileInfo;
70
+ paths: {
71
+ projectDir: string;
72
+ workDir: string;
73
+ stateDir: string;
74
+ journalFile: string;
75
+ memoryFile: string;
76
+ runMemoryFile: string;
77
+ tasksFile: string;
78
+ registryFile: string;
79
+ toolPath: string;
80
+ piAdapterPath: string;
81
+ baseStateDir: string;
82
+ mainProjectDir: string;
83
+ worktreeBranch: string;
84
+ worktreePath: string;
85
+ worktreeMetaDir: string;
86
+ };
87
+ runtime: {
88
+ runId: string;
89
+ selfCommand: string;
90
+ promptOverride: string | null;
91
+ backendOverride: Record<string, unknown>;
92
+ logLevel: string;
93
+ branchMode: boolean;
94
+ isolationMode: string;
95
+ };
96
+ launch: LaunchMetadata;
97
+ store: Record<string, unknown>;
98
+ agentMap: AgentMap | null;
99
+ kiroSession?: AcpSession;
100
+ lastVerdict?: Verdict;
101
+ /** Optional structured-event emitter, forwarded from RunOptions.onEvent. */
102
+ onEvent?: LoopEventEmitter;
103
+ }
104
+ export interface RunOptions {
105
+ workDir?: string;
106
+ backendOverride?: Record<string, unknown>;
107
+ logLevel?: string | null;
108
+ prompt?: string | null;
109
+ chain?: string | null;
110
+ trigger?: TriggerSource;
111
+ parentRunId?: string;
112
+ profiles?: string[];
113
+ noDefaultProfiles?: boolean;
114
+ worktree?: boolean;
115
+ noWorktree?: boolean;
116
+ isolationMode?: string;
117
+ mergeStrategy?: string;
118
+ automerge?: boolean;
119
+ keepWorktree?: boolean;
120
+ /**
121
+ * Optional abort signal. When provided, the CLI (or SDK caller) owns
122
+ * process signal handling; the harness only listens to this signal for
123
+ * graceful teardown. Without a signal the harness runs to completion
124
+ * and no signal-handling is installed.
125
+ */
126
+ signal?: AbortSignal;
127
+ /**
128
+ * Optional structured-event listener. Emitted alongside the existing
129
+ * terminal output; SDK consumers can drive custom UIs from this stream.
130
+ */
131
+ onEvent?: LoopEventEmitter;
132
+ }
133
+ export interface RunSummary {
134
+ iterations: number;
135
+ stopReason: string;
136
+ runId?: string;
137
+ }
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,9 @@
1
+ import type { IterationContext } from "../prompt.js";
2
+ import type { LoopContext, RunSummary } from "../types.js";
3
+ import type { BranchResult, IterateFn } from "./types.js";
4
+ export declare function finalizeParallelWave(loop: LoopContext, iter: IterationContext, waveId: string, results: BranchResult[]): {
5
+ reason: string;
6
+ waveId: string;
7
+ };
8
+ 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: string, waveId: string): RunSummary;
@@ -0,0 +1,86 @@
1
+ import { joinCsv, jsonField } from "@mobrienv/autoloop-core";
2
+ import { appendEvent, appendHarnessEvent, } from "@mobrienv/autoloop-core/journal";
3
+ import * as topology from "@mobrienv/autoloop-core/topology";
4
+ import { parallelDispatchBase, parallelJoinedTopic } from "../emit.js";
5
+ export function finalizeParallelWave(loop, iter, waveId, results) {
6
+ const timedOut = results
7
+ .filter((r) => r.stopReason === "backend_timeout")
8
+ .map((r) => r.branchId);
9
+ if (timedOut.length > 0) {
10
+ appendEvent(loop.paths.journalFile, loop.runtime.runId, String(iter.iteration), "wave.timeout", jsonField("wave_id", waveId) +
11
+ ", " +
12
+ jsonField("timed_out_branches", joinCsv(timedOut)));
13
+ return { reason: "parallel_wave_timeout", waveId };
14
+ }
15
+ const failed = results
16
+ .filter((r) => !branchSuccessStatus(r.stopReason))
17
+ .map((r) => r.branchId);
18
+ if (failed.length > 0) {
19
+ appendEvent(loop.paths.journalFile, loop.runtime.runId, String(iter.iteration), "wave.failed", jsonField("wave_id", waveId) +
20
+ ", " +
21
+ jsonField("failed_branches", joinCsv(failed)));
22
+ return { reason: "parallel_wave_failed", waveId };
23
+ }
24
+ return { reason: "parallel_wave_complete", waveId };
25
+ }
26
+ function branchSuccessStatus(status) {
27
+ return (status === "max_iterations" ||
28
+ status === "completion_event" ||
29
+ status === "completion_promise");
30
+ }
31
+ export async function continueAfterParallelJoin(loop, iter, waveId, emittedTopic, totalElapsedMs, iterateFn) {
32
+ const joinedTopic = parallelJoinedTopic(emittedTopic);
33
+ appendWaveJoinFinish(loop, iter, waveId, emittedTopic, joinedTopic, totalElapsedMs);
34
+ appendHarnessEvent(loop.paths.journalFile, loop.runtime.runId, String(iter.iteration), joinedTopic, waveId);
35
+ return iterateFn(loop, iter.iteration + 1);
36
+ }
37
+ export function stopAfterParallelWave(loop, iter, reason, waveId) {
38
+ const fields = jsonField("reason", reason) +
39
+ ", " +
40
+ jsonField("iteration", String(iter.iteration)) +
41
+ (waveId ? `, ${jsonField("wave_id", waveId)}` : "");
42
+ appendEvent(loop.paths.journalFile, loop.runtime.runId, String(iter.iteration), "loop.stop", fields);
43
+ return { iterations: iter.iteration, stopReason: reason };
44
+ }
45
+ function joinedResumeRoutingBasis(iter, emittedTopic) {
46
+ if (emittedTopic === "explore.parallel")
47
+ return iter.recentEvent;
48
+ return parallelDispatchBase(emittedTopic) || iter.recentEvent;
49
+ }
50
+ function joinedResumeRecentEvent(iter, emittedTopic, joinedTopic) {
51
+ if (emittedTopic === "explore.parallel")
52
+ return iter.recentEvent;
53
+ return joinedTopic;
54
+ }
55
+ function joinedResumeRoles(loop, iter, emittedTopic, routingBasis) {
56
+ if (emittedTopic === "explore.parallel")
57
+ return iter.allowedRoles;
58
+ return topology.suggestedRoles(loop.topology, routingBasis);
59
+ }
60
+ function joinedResumeEvents(loop, iter, emittedTopic, routingBasis) {
61
+ if (emittedTopic === "explore.parallel")
62
+ return iter.allowedEvents;
63
+ return topology.allowedEvents(loop.topology, routingBasis);
64
+ }
65
+ function appendWaveJoinFinish(loop, iter, waveId, emittedTopic, joinedTopic, totalElapsed) {
66
+ const routingBasis = joinedResumeRoutingBasis(iter, emittedTopic);
67
+ const resumeRecentEvent = joinedResumeRecentEvent(iter, emittedTopic, joinedTopic);
68
+ const resumeRoles = joinedResumeRoles(loop, iter, emittedTopic, routingBasis);
69
+ const resumeEvents = joinedResumeEvents(loop, iter, emittedTopic, routingBasis);
70
+ appendEvent(loop.paths.journalFile, loop.runtime.runId, String(iter.iteration), "wave.join.finish", jsonField("wave_id", waveId) +
71
+ ", " +
72
+ jsonField("trigger_topic", emittedTopic) +
73
+ ", " +
74
+ jsonField("joined_topic", joinedTopic) +
75
+ ", " +
76
+ jsonField("routing_basis", routingBasis) +
77
+ ", " +
78
+ jsonField("resume_recent_event", resumeRecentEvent) +
79
+ ", " +
80
+ jsonField("resume_roles", joinCsv(resumeRoles)) +
81
+ ", " +
82
+ jsonField("resume_events", joinCsv(resumeEvents)) +
83
+ ", " +
84
+ jsonField("elapsed_ms", String(totalElapsed)));
85
+ }
86
+ //# sourceMappingURL=finalize-wave.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finalize-wave.js","sourceRoot":"","sources":["../../src/wave/finalize-wave.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import type { IterationContext } from "../prompt.js";
2
+ import type { LoopContext } from "../types.js";
3
+ import type { BranchResult, BranchSpec } from "./types.js";
4
+ export declare function prepareParallelBranches(loop: LoopContext, iter: IterationContext, waveId: string, waveDir: string, emittedTopic: string, objectives: string[]): BranchSpec[];
5
+ export declare function launchParallelBranches(loop: LoopContext, specs: BranchSpec[]): BranchSpec[];
6
+ export declare function joinParallelBranches(loop: LoopContext, iter: IterationContext, waveId: string, pending: BranchSpec[]): BranchResult[];