taskflow-core 0.1.8 → 0.2.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 (115) hide show
  1. package/README.md +80 -25
  2. package/dist/deterministic.d.ts +8 -0
  3. package/dist/deterministic.d.ts.map +1 -1
  4. package/dist/deterministic.js +23 -1
  5. package/dist/deterministic.js.map +1 -1
  6. package/dist/exec/driver.d.ts +47 -0
  7. package/dist/exec/driver.d.ts.map +1 -0
  8. package/dist/exec/driver.js +397 -0
  9. package/dist/exec/driver.js.map +1 -0
  10. package/dist/exec/events.d.ts +76 -0
  11. package/dist/exec/events.d.ts.map +1 -0
  12. package/dist/exec/events.js +108 -0
  13. package/dist/exec/events.js.map +1 -0
  14. package/dist/exec/fold.d.ts +45 -0
  15. package/dist/exec/fold.d.ts.map +1 -0
  16. package/dist/exec/fold.js +122 -0
  17. package/dist/exec/fold.js.map +1 -0
  18. package/dist/exec/index.d.ts +17 -0
  19. package/dist/exec/index.d.ts.map +1 -0
  20. package/dist/exec/index.js +17 -0
  21. package/dist/exec/index.js.map +1 -0
  22. package/dist/exec/kernel-policy.d.ts +35 -0
  23. package/dist/exec/kernel-policy.d.ts.map +1 -0
  24. package/dist/exec/kernel-policy.js +184 -0
  25. package/dist/exec/kernel-policy.js.map +1 -0
  26. package/dist/exec/step-kinds.d.ts +41 -0
  27. package/dist/exec/step-kinds.d.ts.map +1 -0
  28. package/dist/exec/step-kinds.js +574 -0
  29. package/dist/exec/step-kinds.js.map +1 -0
  30. package/dist/exec/step.d.ts +93 -0
  31. package/dist/exec/step.d.ts.map +1 -0
  32. package/dist/exec/step.js +436 -0
  33. package/dist/exec/step.js.map +1 -0
  34. package/dist/flowir/canonical-hash.d.ts +101 -0
  35. package/dist/flowir/canonical-hash.d.ts.map +1 -0
  36. package/dist/flowir/canonical-hash.js +219 -0
  37. package/dist/flowir/canonical-hash.js.map +1 -0
  38. package/dist/flowir/compile.d.ts +49 -0
  39. package/dist/flowir/compile.d.ts.map +1 -0
  40. package/dist/flowir/compile.js +219 -0
  41. package/dist/flowir/compile.js.map +1 -0
  42. package/dist/flowir/cond.d.ts +76 -0
  43. package/dist/flowir/cond.d.ts.map +1 -0
  44. package/dist/flowir/cond.js +214 -0
  45. package/dist/flowir/cond.js.map +1 -0
  46. package/dist/flowir/index.d.ts +20 -23
  47. package/dist/flowir/index.d.ts.map +1 -1
  48. package/dist/flowir/index.js +47 -35
  49. package/dist/flowir/index.js.map +1 -1
  50. package/dist/flowir/meta.d.ts +4 -4
  51. package/dist/flowir/meta.d.ts.map +1 -1
  52. package/dist/flowir/phasefp.d.ts.map +1 -1
  53. package/dist/flowir/phasefp.js +13 -1
  54. package/dist/flowir/phasefp.js.map +1 -1
  55. package/dist/flowir/schema.d.ts +260 -0
  56. package/dist/flowir/schema.d.ts.map +1 -0
  57. package/dist/flowir/schema.js +234 -0
  58. package/dist/flowir/schema.js.map +1 -0
  59. package/dist/flowir/translate.d.ts.map +1 -1
  60. package/dist/flowir/translate.js +3 -0
  61. package/dist/flowir/translate.js.map +1 -1
  62. package/dist/host/runner-types.d.ts +3 -0
  63. package/dist/host/runner-types.d.ts.map +1 -1
  64. package/dist/index.d.ts +2 -0
  65. package/dist/index.d.ts.map +1 -1
  66. package/dist/index.js +2 -0
  67. package/dist/index.js.map +1 -1
  68. package/dist/rates.d.ts +121 -0
  69. package/dist/rates.d.ts.map +1 -0
  70. package/dist/rates.js +187 -0
  71. package/dist/rates.js.map +1 -0
  72. package/dist/replay.d.ts +43 -50
  73. package/dist/replay.d.ts.map +1 -1
  74. package/dist/replay.js +629 -19
  75. package/dist/replay.js.map +1 -1
  76. package/dist/runner-core.d.ts +24 -0
  77. package/dist/runner-core.d.ts.map +1 -1
  78. package/dist/runner-core.js +225 -32
  79. package/dist/runner-core.js.map +1 -1
  80. package/dist/runtime/phases/approval.d.ts +23 -0
  81. package/dist/runtime/phases/approval.d.ts.map +1 -0
  82. package/dist/runtime/phases/approval.js +38 -0
  83. package/dist/runtime/phases/approval.js.map +1 -0
  84. package/dist/runtime/phases/expand.d.ts +29 -0
  85. package/dist/runtime/phases/expand.d.ts.map +1 -0
  86. package/dist/runtime/phases/expand.js +126 -0
  87. package/dist/runtime/phases/expand.js.map +1 -0
  88. package/dist/runtime/phases/parallel.d.ts +26 -0
  89. package/dist/runtime/phases/parallel.d.ts.map +1 -0
  90. package/dist/runtime/phases/parallel.js +15 -0
  91. package/dist/runtime/phases/parallel.js.map +1 -0
  92. package/dist/runtime/phases/race.d.ts +31 -0
  93. package/dist/runtime/phases/race.d.ts.map +1 -0
  94. package/dist/runtime/phases/race.js +220 -0
  95. package/dist/runtime/phases/race.js.map +1 -0
  96. package/dist/runtime/phases/script.d.ts +38 -0
  97. package/dist/runtime/phases/script.d.ts.map +1 -0
  98. package/dist/runtime/phases/script.js +139 -0
  99. package/dist/runtime/phases/script.js.map +1 -0
  100. package/dist/runtime.d.ts +29 -16
  101. package/dist/runtime.d.ts.map +1 -1
  102. package/dist/runtime.js +554 -292
  103. package/dist/runtime.js.map +1 -1
  104. package/dist/schema.d.ts +36 -4
  105. package/dist/schema.d.ts.map +1 -1
  106. package/dist/schema.js +86 -10
  107. package/dist/schema.js.map +1 -1
  108. package/dist/store.d.ts +6 -0
  109. package/dist/store.d.ts.map +1 -1
  110. package/dist/store.js.map +1 -1
  111. package/dist/trace.d.ts +4 -1
  112. package/dist/trace.d.ts.map +1 -1
  113. package/dist/trace.js +33 -26
  114. package/dist/trace.js.map +1 -1
  115. package/package.json +5 -4
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Approval phase — human-in-the-loop pause (approve / reject / edit).
3
+ */
4
+ import { emptyUsage } from "../../usage.js";
5
+ /**
6
+ * Build PhaseState for an approval outcome (interactive or auto-reject).
7
+ */
8
+ export function approvalDecisionToPhaseState(phaseId, decision, opts) {
9
+ if (opts.auto) {
10
+ return {
11
+ id: phaseId,
12
+ status: "done",
13
+ output: "(auto-rejected: no interactive approver available)",
14
+ approval: { decision: "reject", auto: true },
15
+ gate: { verdict: "block", reason: "(auto-rejected: no interactive approver available)" },
16
+ usage: emptyUsage(),
17
+ inputHash: opts.inputHash,
18
+ reads: opts.reads,
19
+ endedAt: Date.now(),
20
+ };
21
+ }
22
+ const note = decision.note?.trim();
23
+ const ps = {
24
+ id: phaseId,
25
+ status: "done",
26
+ output: note || `(${decision.decision})`,
27
+ approval: { decision: decision.decision, note },
28
+ usage: emptyUsage(),
29
+ inputHash: opts.inputHash,
30
+ reads: opts.reads,
31
+ endedAt: Date.now(),
32
+ };
33
+ if (decision.decision === "reject") {
34
+ ps.gate = { verdict: "block", reason: note || "Rejected by user" };
35
+ }
36
+ return ps;
37
+ }
38
+ //# sourceMappingURL=approval.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"approval.js","sourceRoot":"","sources":["../../../src/runtime/phases/approval.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAa5C;;GAEG;AACH,MAAM,UAAU,4BAA4B,CAC3C,OAAe,EACf,QAA0B,EAC1B,IAKC;IAED,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACf,OAAO;YACN,EAAE,EAAE,OAAO;YACX,MAAM,EAAE,MAAM;YACd,MAAM,EAAE,oDAAoD;YAC5D,QAAQ,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE;YAC5C,IAAI,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,oDAAoD,EAAE;YACxF,KAAK,EAAE,UAAU,EAAE;YACnB,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE;SACnB,CAAC;IACH,CAAC;IAED,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC;IACnC,MAAM,EAAE,GAAe;QACtB,EAAE,EAAE,OAAO;QACX,MAAM,EAAE,MAAM;QACd,MAAM,EAAE,IAAI,IAAI,IAAI,QAAQ,CAAC,QAAQ,GAAG;QACxC,QAAQ,EAAE,EAAE,QAAQ,EAAE,QAAQ,CAAC,QAAQ,EAAE,IAAI,EAAE;QAC/C,KAAK,EAAE,UAAU,EAAE;QACnB,SAAS,EAAE,IAAI,CAAC,SAAS;QACzB,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE;KACnB,CAAC;IACF,IAAI,QAAQ,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACpC,EAAE,CAAC,IAAI,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,IAAI,kBAAkB,EAAE,CAAC;IACpE,CAAC;IACD,OAAO,EAAE,CAAC;AACX,CAAC"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Expand phase helpers — pure transforms for fragment prep + graft promote.
3
+ * Execution still wires through flow|def path in runtime.ts; logic lives here
4
+ * so expand does not keep growing executePhaseInner.
5
+ */
6
+ import type { Phase, Taskflow } from "../../schema.ts";
7
+ import type { PhaseState, RunState } from "../../store.ts";
8
+ import { emptyUsage } from "../../usage.ts";
9
+ export type ExpandMode = "nested" | "graft";
10
+ export declare function resolveExpandMode(phase: Phase): ExpandMode;
11
+ export declare function resolveMaxNodes(phase: Phase, hardCap: number): number;
12
+ /**
13
+ * Prefix every phase id (and rewrite dependsOn/from + template step refs) so
14
+ * graft fragments never collide with parent phase ids and internal edges stay valid.
15
+ */
16
+ export declare function prefixGraftFragment(fragment: Taskflow, expandPhaseId: string): Taskflow;
17
+ /**
18
+ * Copy child phase states onto the parent run (graft promote).
19
+ * Skips ids that already exist on the parent.
20
+ * Returns whether any phase was promoted (caller should zero expand usage to avoid double-count).
21
+ */
22
+ export declare function promoteGraftPhases(parent: RunState, childPhases: Record<string, PhaseState>): {
23
+ promoted: number;
24
+ promotedIds: string[];
25
+ warnings: string[];
26
+ };
27
+ /** Empty usage helper for expand phase after graft (avoid double-count in rollup). */
28
+ export declare function emptyUsageForGraftExpand(): ReturnType<typeof emptyUsage>;
29
+ //# sourceMappingURL=expand.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expand.d.ts","sourceRoot":"","sources":["../../../src/runtime/phases/expand.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAE5C,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,OAAO,CAAC;AAE5C,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,KAAK,GAAG,UAAU,CAE1D;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAMrE;AAUD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,GAAG,QAAQ,CA2DvF;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CACjC,MAAM,EAAE,QAAQ,EAChB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,GACrC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,CAyBjE;AAED,sFAAsF;AACtF,wBAAgB,wBAAwB,IAAI,UAAU,CAAC,OAAO,UAAU,CAAC,CAExE"}
@@ -0,0 +1,126 @@
1
+ /**
2
+ * Expand phase helpers — pure transforms for fragment prep + graft promote.
3
+ * Execution still wires through flow|def path in runtime.ts; logic lives here
4
+ * so expand does not keep growing executePhaseInner.
5
+ */
6
+ import { emptyUsage } from "../../usage.js";
7
+ export function resolveExpandMode(phase) {
8
+ return phase.expandMode === "graft" ? "graft" : "nested";
9
+ }
10
+ export function resolveMaxNodes(phase, hardCap) {
11
+ const n = phase.maxNodes;
12
+ if (typeof n === "number" && Number.isFinite(n)) {
13
+ return Math.min(hardCap, Math.max(1, Math.floor(n)));
14
+ }
15
+ return Math.min(50, hardCap);
16
+ }
17
+ /** Rewrite `{steps.<oldId>...}` placeholders using a phase id map. */
18
+ function rewriteStepRefs(text, idMap) {
19
+ return text.replace(/\{steps\.([a-zA-Z0-9_-]+)/g, (full, id) => {
20
+ const mapped = idMap.get(id);
21
+ return mapped ? `{steps.${mapped}` : full;
22
+ });
23
+ }
24
+ /**
25
+ * Prefix every phase id (and rewrite dependsOn/from + template step refs) so
26
+ * graft fragments never collide with parent phase ids and internal edges stay valid.
27
+ */
28
+ export function prefixGraftFragment(fragment, expandPhaseId) {
29
+ const prefix = `${expandPhaseId}-`;
30
+ const idMap = new Map(fragment.phases.map((p) => [p.id, prefix + p.id]));
31
+ return {
32
+ ...fragment,
33
+ name: fragment.name || `${expandPhaseId}-graft`,
34
+ phases: fragment.phases.map((p) => {
35
+ const np = { ...p, id: idMap.get(p.id) ?? prefix + p.id };
36
+ if (p.dependsOn?.length) {
37
+ np.dependsOn = p.dependsOn.map((d) => idMap.get(d) ?? d);
38
+ }
39
+ if (p.from?.length) {
40
+ np.from = p.from.map((d) => idMap.get(d) ?? d);
41
+ }
42
+ // Rewrite string templates that reference sibling phase ids.
43
+ const fields = ["task", "over", "when", "until", "input", "judge", "def"];
44
+ for (const f of fields) {
45
+ const v = np[f];
46
+ if (typeof v === "string") {
47
+ np[f] = rewriteStepRefs(v, idMap);
48
+ }
49
+ }
50
+ if (Array.isArray(np.run)) {
51
+ np.run = np.run.map((r) => (typeof r === "string" ? rewriteStepRefs(r, idMap) : r));
52
+ }
53
+ else if (typeof np.run === "string") {
54
+ np.run = rewriteStepRefs(np.run, idMap);
55
+ }
56
+ if (Array.isArray(np.eval)) {
57
+ np.eval = np.eval.map((e) => (typeof e === "string" ? rewriteStepRefs(e, idMap) : e));
58
+ }
59
+ if (Array.isArray(np.context)) {
60
+ np.context = np.context.map((c) => (typeof c === "string" ? rewriteStepRefs(c, idMap) : c));
61
+ }
62
+ if (np.branches?.length) {
63
+ np.branches = np.branches.map((b) => {
64
+ const nb = { ...b };
65
+ if (typeof nb.task === "string")
66
+ nb.task = rewriteStepRefs(nb.task, idMap);
67
+ return nb;
68
+ });
69
+ }
70
+ if (np.with && typeof np.with === "object") {
71
+ const nw = {};
72
+ for (const [k, v] of Object.entries(np.with)) {
73
+ nw[k] = typeof v === "string" ? rewriteStepRefs(v, idMap) : v;
74
+ }
75
+ np.with = nw;
76
+ }
77
+ const score = np.score;
78
+ if (score && typeof score === "object") {
79
+ const ns = { ...score };
80
+ if (typeof ns.target === "string")
81
+ ns.target = rewriteStepRefs(ns.target, idMap);
82
+ if (ns.judge && typeof ns.judge === "object" && typeof ns.judge.task === "string") {
83
+ ns.judge = { ...ns.judge, task: rewriteStepRefs(ns.judge.task, idMap) };
84
+ }
85
+ np.score = ns;
86
+ }
87
+ return np;
88
+ }),
89
+ };
90
+ }
91
+ /**
92
+ * Copy child phase states onto the parent run (graft promote).
93
+ * Skips ids that already exist on the parent.
94
+ * Returns whether any phase was promoted (caller should zero expand usage to avoid double-count).
95
+ */
96
+ export function promoteGraftPhases(parent, childPhases) {
97
+ const warnings = [];
98
+ let promoted = 0;
99
+ const promotedIds = [];
100
+ // Collision ownership is defined by the authored definition, not by which
101
+ // authored phases happen to have reached the scheduler and acquired state
102
+ // rows. A graft may execute before a later authored phase with the same id;
103
+ // promoting into that gap would steal ownership and zero the expand's residual
104
+ // usage even though the authored phase subsequently overwrites the row.
105
+ const authoredIds = new Set(parent.def.phases.map((phase) => phase.id));
106
+ for (const [cid, cps] of Object.entries(childPhases)) {
107
+ if (authoredIds.has(cid) || parent.phases[cid]) {
108
+ warnings.push(`expand graft skipped promote of '${cid}' (id is authored or already exists on parent)`);
109
+ continue;
110
+ }
111
+ // Keep child usage for audit; expand phase usage must be zeroed by caller
112
+ // so run-level aggregateUsage does not double-count.
113
+ parent.phases[cid] = { ...cps, id: cid };
114
+ promoted++;
115
+ promotedIds.push(cid);
116
+ }
117
+ if (promoted > 0) {
118
+ warnings.push(`expand graft: promoted ${promoted} phase(s) onto parent run`);
119
+ }
120
+ return { promoted, promotedIds, warnings };
121
+ }
122
+ /** Empty usage helper for expand phase after graft (avoid double-count in rollup). */
123
+ export function emptyUsageForGraftExpand() {
124
+ return emptyUsage();
125
+ }
126
+ //# sourceMappingURL=expand.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expand.js","sourceRoot":"","sources":["../../../src/runtime/phases/expand.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAI5C,MAAM,UAAU,iBAAiB,CAAC,KAAY;IAC7C,OAAQ,KAAiC,CAAC,UAAU,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC;AACvF,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,KAAY,EAAE,OAAe;IAC5D,MAAM,CAAC,GAAI,KAA+B,CAAC,QAAQ,CAAC;IACpD,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;QACjD,OAAO,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACtD,CAAC;IACD,OAAO,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;AAC9B,CAAC;AAED,sEAAsE;AACtE,SAAS,eAAe,CAAC,IAAY,EAAE,KAA0B;IAChE,OAAO,IAAI,CAAC,OAAO,CAAC,4BAA4B,EAAE,CAAC,IAAI,EAAE,EAAU,EAAE,EAAE;QACtE,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC7B,OAAO,MAAM,CAAC,CAAC,CAAC,UAAU,MAAM,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IAC3C,CAAC,CAAC,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,QAAkB,EAAE,aAAqB;IAC5E,MAAM,MAAM,GAAG,GAAG,aAAa,GAAG,CAAC;IACnC,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACzE,OAAO;QACN,GAAG,QAAQ;QACX,IAAI,EAAE,QAAQ,CAAC,IAAI,IAAI,GAAG,aAAa,QAAQ;QAC/C,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;YACjC,MAAM,EAAE,GAAU,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,MAAM,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC;YACjE,IAAI,CAAC,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC;gBACzB,EAAE,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;YAC1D,CAAC;YACD,IAAI,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC;gBACpB,EAAE,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;YAChD,CAAC;YACD,6DAA6D;YAC7D,MAAM,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,CAAU,CAAC;YACnF,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;gBACxB,MAAM,CAAC,GAAI,EAA8B,CAAC,CAAC,CAAC,CAAC;gBAC7C,IAAI,OAAO,CAAC,KAAK,QAAQ,EAAE,CAAC;oBAC1B,EAA8B,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;gBAChE,CAAC;YACF,CAAC;YACD,IAAI,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC3B,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACrF,CAAC;iBAAM,IAAI,OAAO,EAAE,CAAC,GAAG,KAAK,QAAQ,EAAE,CAAC;gBACvC,EAAE,CAAC,GAAG,GAAG,eAAe,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;YACzC,CAAC;YACD,IAAI,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC5B,EAAE,CAAC,IAAI,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACvF,CAAC;YACD,IAAI,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC/B,EAAE,CAAC,OAAO,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC7F,CAAC;YACD,IAAI,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;gBACzB,EAAE,CAAC,QAAQ,GAAG,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;oBACnC,MAAM,EAAE,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC;oBACpB,IAAI,OAAO,EAAE,CAAC,IAAI,KAAK,QAAQ;wBAAE,EAAE,CAAC,IAAI,GAAG,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;oBAC3E,OAAO,EAAE,CAAC;gBACX,CAAC,CAAC,CAAC;YACJ,CAAC;YACD,IAAI,EAAE,CAAC,IAAI,IAAI,OAAO,EAAE,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC5C,MAAM,EAAE,GAA4B,EAAE,CAAC;gBACvC,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;oBAC9C,EAAE,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC/D,CAAC;gBACD,EAAE,CAAC,IAAI,GAAG,EAAE,CAAC;YACd,CAAC;YACD,MAAM,KAAK,GAAI,EAAmE,CAAC,KAAK,CAAC;YACzF,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;gBACxC,MAAM,EAAE,GAAG,EAAE,GAAG,KAAK,EAAE,CAAC;gBACxB,IAAI,OAAO,EAAE,CAAC,MAAM,KAAK,QAAQ;oBAAE,EAAE,CAAC,MAAM,GAAG,eAAe,CAAC,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;gBACjF,IAAI,EAAE,CAAC,KAAK,IAAI,OAAO,EAAE,CAAC,KAAK,KAAK,QAAQ,IAAI,OAAO,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;oBACnF,EAAE,CAAC,KAAK,GAAG,EAAE,GAAG,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,eAAe,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC;gBACzE,CAAC;gBACA,EAA0B,CAAC,KAAK,GAAG,EAAE,CAAC;YACxC,CAAC;YACD,OAAO,EAAE,CAAC;QACX,CAAC,CAAC;KACF,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CACjC,MAAgB,EAChB,WAAuC;IAEvC,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,MAAM,WAAW,GAAa,EAAE,CAAC;IACjC,0EAA0E;IAC1E,0EAA0E;IAC1E,4EAA4E;IAC5E,+EAA+E;IAC/E,wEAAwE;IACxE,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;IACxE,KAAK,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,CAAC;QACtD,IAAI,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;YAChD,QAAQ,CAAC,IAAI,CAAC,oCAAoC,GAAG,gDAAgD,CAAC,CAAC;YACvG,SAAS;QACV,CAAC;QACD,0EAA0E;QAC1E,qDAAqD;QACrD,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC;QACzC,QAAQ,EAAE,CAAC;QACX,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACvB,CAAC;IACD,IAAI,QAAQ,GAAG,CAAC,EAAE,CAAC;QAClB,QAAQ,CAAC,IAAI,CAAC,0BAA0B,QAAQ,2BAA2B,CAAC,CAAC;IAC9E,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,CAAC;AAC5C,CAAC;AAED,sFAAsF;AACtF,MAAM,UAAU,wBAAwB;IACvC,OAAO,UAAU,EAAE,CAAC;AACrB,CAAC"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Parallel phase — wait for all branches (static fan-out).
3
+ * Scheduling stays injected (`runFanout`); this module only shapes the call.
4
+ */
5
+ import type { Phase } from "../../schema.ts";
6
+ import type { RunResult } from "../../runner-core.ts";
7
+ import type { PhaseState } from "../../store.ts";
8
+ export interface ParallelBranch {
9
+ agent: string;
10
+ task: string;
11
+ }
12
+ export interface ParallelFanout {
13
+ (branches: ParallelBranch[]): Promise<RunResult[]>;
14
+ }
15
+ export interface ParallelMerge {
16
+ (phaseId: string, results: RunResult[], inputHash: string, parseJson: boolean): PhaseState;
17
+ }
18
+ /**
19
+ * Run all parallel branches and merge into one PhaseState.
20
+ */
21
+ export declare function executeParallelBranches(phase: Phase, branches: ParallelBranch[], runFanout: ParallelFanout, mergePhaseState: ParallelMerge, opts: {
22
+ inputHash: string;
23
+ parseJson: boolean;
24
+ reads?: PhaseState["reads"];
25
+ }): Promise<PhaseState>;
26
+ //# sourceMappingURL=parallel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parallel.d.ts","sourceRoot":"","sources":["../../../src/runtime/phases/parallel.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEjD,MAAM,WAAW,cAAc;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,cAAc;IAC9B,CAAC,QAAQ,EAAE,cAAc,EAAE,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;CACnD;AAED,MAAM,WAAW,aAAa;IAC7B,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,GAAG,UAAU,CAAC;CAC3F;AAED;;GAEG;AACH,wBAAsB,uBAAuB,CAC5C,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,cAAc,EAAE,EAC1B,SAAS,EAAE,cAAc,EACzB,eAAe,EAAE,aAAa,EAC9B,IAAI,EAAE;IACL,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC;CAC5B,GACC,OAAO,CAAC,UAAU,CAAC,CAKrB"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Parallel phase — wait for all branches (static fan-out).
3
+ * Scheduling stays injected (`runFanout`); this module only shapes the call.
4
+ */
5
+ /**
6
+ * Run all parallel branches and merge into one PhaseState.
7
+ */
8
+ export async function executeParallelBranches(phase, branches, runFanout, mergePhaseState, opts) {
9
+ const results = await runFanout(branches);
10
+ const ps = mergePhaseState(phase.id, results, opts.inputHash, opts.parseJson);
11
+ if (opts.reads)
12
+ ps.reads = opts.reads;
13
+ return ps;
14
+ }
15
+ //# sourceMappingURL=parallel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parallel.js","sourceRoot":"","sources":["../../../src/runtime/phases/parallel.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAmBH;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC5C,KAAY,EACZ,QAA0B,EAC1B,SAAyB,EACzB,eAA8B,EAC9B,IAIC;IAED,MAAM,OAAO,GAAG,MAAM,SAAS,CAAC,QAAQ,CAAC,CAAC;IAC1C,MAAM,EAAE,GAAG,eAAe,CAAC,KAAK,CAAC,EAAE,EAAE,OAAO,EAAE,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;IAC9E,IAAI,IAAI,CAAC,KAAK;QAAE,EAAE,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;IACtC,OAAO,EAAE,CAAC;AACX,CAAC"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Race phase — first **successful** branch wins (not first-settled).
3
+ */
4
+ import type { Phase } from "../../schema.ts";
5
+ import type { RunResult } from "../../runner-core.ts";
6
+ import type { PhaseState } from "../../store.ts";
7
+ export interface RaceBranch {
8
+ agent: string;
9
+ task: string;
10
+ }
11
+ export interface RaceRunOne {
12
+ (agent: string, task: string, signal?: AbortSignal): Promise<RunResult>;
13
+ }
14
+ export interface RaceIsFailed {
15
+ (r: RunResult): boolean;
16
+ }
17
+ /**
18
+ * First **successful** branch wins. Failed settles do not terminate the race.
19
+ * If all fail → race fails. cancelLosers aborts others after a success (best-effort).
20
+ * Final usage aggregates every branch result. A non-cooperative branch that
21
+ * ignores abort is bounded by a finite accounting deadline; if it remains
22
+ * outstanding the race fails closed with budgetTruncated so no downstream
23
+ * phase can run against an incomplete usage snapshot.
24
+ */
25
+ export declare function executeRaceBranches(phase: Phase, branches: RaceBranch[], runOne: RaceRunOne, isFailed: RaceIsFailed, opts: {
26
+ inputHash: string;
27
+ parseJson: boolean;
28
+ readRefs?: PhaseState["reads"];
29
+ parentSignal?: AbortSignal;
30
+ }): Promise<PhaseState>;
31
+ //# sourceMappingURL=race.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"race.d.ts","sourceRoot":"","sources":["../../../src/runtime/phases/race.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAsBjD,MAAM,WAAW,UAAU;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,UAAU;IAC1B,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;CACxE;AAED,MAAM,WAAW,YAAY;IAC5B,CAAC,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC;CACxB;AAED;;;;;;;GAOG;AACH,wBAAsB,mBAAmB,CACxC,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,UAAU,EAAE,EACtB,MAAM,EAAE,UAAU,EAClB,QAAQ,EAAE,YAAY,EACtB,IAAI,EAAE;IACL,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC;IAC/B,YAAY,CAAC,EAAE,WAAW,CAAC;CAC3B,GACC,OAAO,CAAC,UAAU,CAAC,CAkMrB"}
@@ -0,0 +1,220 @@
1
+ /**
2
+ * Race phase — first **successful** branch wins (not first-settled).
3
+ */
4
+ import { emptyUsage, aggregateUsage } from "../../usage.js";
5
+ import { safeParse } from "../../interpolate.js";
6
+ /**
7
+ * A race cannot return a successful result while loser usage is still unknown:
8
+ * doing so lets the next phase spend against an incomplete budget snapshot.
9
+ * Give every branch the same finite accounting window as an ordinary agent
10
+ * call (60s by default), capped so a hostile/injected runner can never strand
11
+ * the workflow forever even when it ignores AbortSignal.
12
+ */
13
+ const DEFAULT_ACCOUNTING_TIMEOUT_MS = 60_000;
14
+ const MAX_ACCOUNTING_TIMEOUT_MS = 300_000;
15
+ function accountingTimeoutMs(phase) {
16
+ const configured = phase.timeout;
17
+ if (typeof configured !== "number" || !Number.isFinite(configured) || configured < 1000) {
18
+ return DEFAULT_ACCOUNTING_TIMEOUT_MS;
19
+ }
20
+ return Math.min(configured, MAX_ACCOUNTING_TIMEOUT_MS);
21
+ }
22
+ /**
23
+ * First **successful** branch wins. Failed settles do not terminate the race.
24
+ * If all fail → race fails. cancelLosers aborts others after a success (best-effort).
25
+ * Final usage aggregates every branch result. A non-cooperative branch that
26
+ * ignores abort is bounded by a finite accounting deadline; if it remains
27
+ * outstanding the race fails closed with budgetTruncated so no downstream
28
+ * phase can run against an incomplete usage snapshot.
29
+ */
30
+ export async function executeRaceBranches(phase, branches, runOne, isFailed, opts) {
31
+ if (branches.length < 2) {
32
+ return {
33
+ id: phase.id,
34
+ status: "failed",
35
+ error: `race phase '${phase.id}': needs at least 2 branches`,
36
+ endedAt: Date.now(),
37
+ usage: emptyUsage(),
38
+ inputHash: opts.inputHash,
39
+ };
40
+ }
41
+ const cancelLosers = phase.cancelLosers !== false;
42
+ const controllers = branches.map(() => new AbortController());
43
+ const accountingTimeout = accountingTimeoutMs(phase);
44
+ const accountingDeadline = Date.now() + accountingTimeout;
45
+ const settled = [];
46
+ let winner;
47
+ let accountingTimedOut = false;
48
+ let wake;
49
+ const gate = new Promise((r) => {
50
+ wake = r;
51
+ });
52
+ const onParentAbort = () => {
53
+ for (const c of controllers) {
54
+ try {
55
+ c.abort();
56
+ }
57
+ catch {
58
+ /* ignore */
59
+ }
60
+ }
61
+ // Unblock the wait loop so non-cooperative runners hit the accounting deadline
62
+ // instead of hanging forever (AGENTS: never hang forever).
63
+ wake();
64
+ };
65
+ if (opts.parentSignal) {
66
+ if (opts.parentSignal.aborted)
67
+ onParentAbort();
68
+ else
69
+ opts.parentSignal.addEventListener("abort", onParentAbort, { once: true });
70
+ }
71
+ try {
72
+ const branchPromises = branches.map(async (b, i) => {
73
+ let result;
74
+ try {
75
+ result = await runOne(b.agent, b.task, controllers[i].signal);
76
+ }
77
+ catch (e) {
78
+ const msg = e instanceof Error ? e.message : String(e);
79
+ result = {
80
+ agent: b.agent,
81
+ task: b.task,
82
+ exitCode: 1,
83
+ output: "",
84
+ stderr: msg,
85
+ usage: emptyUsage(),
86
+ stopReason: "error",
87
+ errorMessage: msg,
88
+ };
89
+ }
90
+ const entry = { i, result };
91
+ settled.push(entry);
92
+ // Parent cancellation wins over a late branch success. The branch still
93
+ // enters `settled` so its usage is accounted, but it can never revive the
94
+ // cancelled run or provide a successful race output.
95
+ if (!winner && opts.parentSignal?.aborted !== true && !isFailed(result)) {
96
+ winner = entry;
97
+ if (cancelLosers) {
98
+ for (let j = 0; j < controllers.length; j++) {
99
+ if (j !== i) {
100
+ try {
101
+ controllers[j].abort();
102
+ }
103
+ catch {
104
+ /* ignore */
105
+ }
106
+ }
107
+ }
108
+ }
109
+ wake();
110
+ }
111
+ else if (settled.length >= branches.length) {
112
+ wake();
113
+ }
114
+ return entry;
115
+ });
116
+ const allSettled = Promise.allSettled(branchPromises).then(() => undefined);
117
+ let deadlineTimer;
118
+ const deadline = new Promise((resolve) => {
119
+ deadlineTimer = setTimeout(() => {
120
+ accountingTimedOut = true;
121
+ for (const c of controllers) {
122
+ try {
123
+ c.abort();
124
+ }
125
+ catch {
126
+ /* ignore */
127
+ }
128
+ }
129
+ resolve();
130
+ }, Math.max(0, accountingDeadline - Date.now()));
131
+ });
132
+ try {
133
+ // First wait for a winner, complete failure, parent abort, or the finite
134
+ // deadline. Then keep the phase quarantined until every branch reports
135
+ // its usage. This preserves honest budgets without an unbounded wait.
136
+ await Promise.race([gate, allSettled, deadline]);
137
+ if (settled.length < branches.length && !accountingTimedOut) {
138
+ await Promise.race([allSettled, deadline]);
139
+ }
140
+ }
141
+ finally {
142
+ if (deadlineTimer)
143
+ clearTimeout(deadlineTimer);
144
+ }
145
+ const totalUsage = aggregateUsage(settled.map((s) => s.result.usage ?? emptyUsage()));
146
+ const outstanding = branches.length - settled.length;
147
+ const parentAborted = opts.parentSignal?.aborted === true;
148
+ if (parentAborted) {
149
+ const warnings = ["race: parent run aborted; branch successes were discarded"];
150
+ if (outstanding > 0) {
151
+ warnings.push(`race: ${outstanding} branch(es) did not report usage within ${accountingTimeout}ms; downstream execution is disabled`);
152
+ }
153
+ return {
154
+ id: phase.id,
155
+ status: "failed",
156
+ error: `race phase '${phase.id}' aborted by parent`,
157
+ usage: totalUsage,
158
+ inputHash: opts.inputHash,
159
+ endedAt: Date.now(),
160
+ budgetTruncated: outstanding > 0 || undefined,
161
+ warnings,
162
+ ...(opts.readRefs ? { reads: opts.readRefs } : {}),
163
+ };
164
+ }
165
+ if (outstanding > 0) {
166
+ return {
167
+ id: phase.id,
168
+ status: "failed",
169
+ error: `race phase '${phase.id}': ${outstanding} branch(es) did not report usage within ${accountingTimeout}ms; refusing to continue with incomplete budget accounting`,
170
+ usage: totalUsage,
171
+ inputHash: opts.inputHash,
172
+ endedAt: Date.now(),
173
+ budgetTruncated: true,
174
+ warnings: [
175
+ `race: accounting deadline reached with ${outstanding} outstanding branch(es); downstream execution is disabled`,
176
+ ],
177
+ ...(opts.readRefs ? { reads: opts.readRefs } : {}),
178
+ };
179
+ }
180
+ if (!winner) {
181
+ const errs = settled
182
+ .map((s) => s.result.errorMessage || s.result.stderr || `branch ${s.i + 1} failed`)
183
+ .filter(Boolean);
184
+ const warnings = ["race: all branches failed"];
185
+ return {
186
+ id: phase.id,
187
+ status: "failed",
188
+ error: `race phase '${phase.id}': all ${branches.length} branches failed${errs.length ? `: ${errs.slice(0, 3).join("; ")}` : ""}`,
189
+ usage: totalUsage,
190
+ inputHash: opts.inputHash,
191
+ endedAt: Date.now(),
192
+ warnings,
193
+ ...(opts.readRefs ? { reads: opts.readRefs } : {}),
194
+ };
195
+ }
196
+ const w = winner.result;
197
+ const warnings = [`race: branch ${winner.i + 1}/${branches.length} won (first success)`];
198
+ if (cancelLosers && branches.length > 1) {
199
+ warnings.push(`race: cancelLosers aborted ${branches.length - 1} loser branch(es) (best-effort AbortSignal)`);
200
+ }
201
+ return {
202
+ id: phase.id,
203
+ status: "done",
204
+ output: w.output,
205
+ json: opts.parseJson ? safeParse(w.output) : undefined,
206
+ usage: totalUsage,
207
+ model: w.model,
208
+ inputHash: opts.inputHash,
209
+ endedAt: Date.now(),
210
+ warnings,
211
+ ...(opts.readRefs ? { reads: opts.readRefs } : {}),
212
+ };
213
+ }
214
+ finally {
215
+ if (opts.parentSignal) {
216
+ opts.parentSignal.removeEventListener("abort", onParentAbort);
217
+ }
218
+ }
219
+ }
220
+ //# sourceMappingURL=race.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"race.js","sourceRoot":"","sources":["../../../src/runtime/phases/race.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Script phase — zero-token shell command execution.
3
+ * Isolated from runtime.ts so S5 strangler can flip kinds without growing the monolith.
4
+ */
5
+ import type { Phase } from "../../schema.ts";
6
+ import type { PhaseState } from "../../store.ts";
7
+ export interface ScriptRunResult {
8
+ stdout: string;
9
+ stderr: string;
10
+ code: number | null;
11
+ stdoutOversize: boolean;
12
+ timedOut: boolean;
13
+ }
14
+ /**
15
+ * Spawn the script command and capture stdout/stderr with timeout + size caps.
16
+ */
17
+ export declare function runScriptCommand(opts: {
18
+ /** Interpolated argv (array form) or single shell string as [cmd]. */
19
+ interpRunText: string[];
20
+ /** Original `run` shape: array → no shell; string → shell true. */
21
+ arrayForm: boolean;
22
+ cwd: string;
23
+ signal?: AbortSignal;
24
+ stdinInput?: string;
25
+ timeoutMs: number;
26
+ }): Promise<ScriptRunResult>;
27
+ /** Map a successful/failed script process result to PhaseState. */
28
+ export declare function scriptResultToPhaseState(phase: Phase, result: ScriptRunResult, opts: {
29
+ inputHash: string;
30
+ timeoutMs: number;
31
+ reads?: PhaseState["reads"];
32
+ }): PhaseState;
33
+ /** Spawn error → failed phase (not cacheable — transient). */
34
+ export declare function scriptSpawnErrorToPhaseState(phaseId: string, err: unknown, opts: {
35
+ inputHash: string;
36
+ reads?: PhaseState["reads"];
37
+ }): PhaseState;
38
+ //# sourceMappingURL=script.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"script.d.ts","sourceRoot":"","sources":["../../../src/runtime/phases/script.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAOjD,MAAM,WAAW,eAAe;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,cAAc,EAAE,OAAO,CAAC;IACxB,QAAQ,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,EAAE;IAC5C,sEAAsE;IACtE,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,mEAAmE;IACnE,SAAS,EAAE,OAAO,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CAClB,GAAG,OAAO,CAAC,eAAe,CAAC,CA6E3B;AAED,mEAAmE;AACnE,wBAAgB,wBAAwB,CACvC,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,eAAe,EACvB,IAAI,EAAE;IACL,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC;CAC5B,GACC,UAAU,CA4BZ;AAED,8DAA8D;AAC9D,wBAAgB,4BAA4B,CAC3C,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,OAAO,EACZ,IAAI,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,CAAA;CAAE,GACtD,UAAU,CAYZ"}