taskflow-core 0.2.0 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (157) hide show
  1. package/README.md +247 -862
  2. package/dist/agents.d.ts +12 -0
  3. package/dist/agents.d.ts.map +1 -1
  4. package/dist/agents.js +29 -1
  5. package/dist/agents.js.map +1 -1
  6. package/dist/build-info.d.ts +48 -0
  7. package/dist/build-info.d.ts.map +1 -0
  8. package/dist/build-info.js +112 -0
  9. package/dist/build-info.js.map +1 -0
  10. package/dist/build-info.json +4 -0
  11. package/dist/cwd-bridge.d.ts +61 -0
  12. package/dist/cwd-bridge.d.ts.map +1 -0
  13. package/dist/cwd-bridge.js +136 -0
  14. package/dist/cwd-bridge.js.map +1 -0
  15. package/dist/detached-runner.js +31 -5
  16. package/dist/detached-runner.js.map +1 -1
  17. package/dist/exec/driver.d.ts +6 -0
  18. package/dist/exec/driver.d.ts.map +1 -1
  19. package/dist/exec/driver.js +40 -18
  20. package/dist/exec/driver.js.map +1 -1
  21. package/dist/exec/kernel-policy.d.ts.map +1 -1
  22. package/dist/exec/kernel-policy.js +10 -0
  23. package/dist/exec/kernel-policy.js.map +1 -1
  24. package/dist/exec/step-kinds.d.ts +14 -1
  25. package/dist/exec/step-kinds.d.ts.map +1 -1
  26. package/dist/exec/step-kinds.js +126 -6
  27. package/dist/exec/step-kinds.js.map +1 -1
  28. package/dist/exec/step.d.ts +22 -0
  29. package/dist/exec/step.d.ts.map +1 -1
  30. package/dist/exec/step.js +40 -5
  31. package/dist/exec/step.js.map +1 -1
  32. package/dist/final-output.d.ts +53 -0
  33. package/dist/final-output.d.ts.map +1 -0
  34. package/dist/final-output.js +65 -0
  35. package/dist/final-output.js.map +1 -0
  36. package/dist/flowir/canonical-hash.d.ts.map +1 -1
  37. package/dist/flowir/canonical-hash.js +2 -0
  38. package/dist/flowir/canonical-hash.js.map +1 -1
  39. package/dist/flowir/compile.d.ts.map +1 -1
  40. package/dist/flowir/compile.js +17 -0
  41. package/dist/flowir/compile.js.map +1 -1
  42. package/dist/flowir/meta.d.ts +3 -0
  43. package/dist/flowir/meta.d.ts.map +1 -1
  44. package/dist/flowir/schema.d.ts +3 -0
  45. package/dist/flowir/schema.d.ts.map +1 -1
  46. package/dist/flowir/schema.js.map +1 -1
  47. package/dist/flowir/translate.d.ts.map +1 -1
  48. package/dist/flowir/translate.js +4 -0
  49. package/dist/flowir/translate.js.map +1 -1
  50. package/dist/host/runner-types.d.ts +16 -0
  51. package/dist/host/runner-types.d.ts.map +1 -1
  52. package/dist/index.d.ts +5 -0
  53. package/dist/index.d.ts.map +1 -1
  54. package/dist/index.js +9 -0
  55. package/dist/index.js.map +1 -1
  56. package/dist/interpolate.d.ts +4 -0
  57. package/dist/interpolate.d.ts.map +1 -1
  58. package/dist/interpolate.js +14 -0
  59. package/dist/interpolate.js.map +1 -1
  60. package/dist/resources/authority.d.ts +35 -0
  61. package/dist/resources/authority.d.ts.map +1 -0
  62. package/dist/resources/authority.js +67 -0
  63. package/dist/resources/authority.js.map +1 -0
  64. package/dist/resources/backend.d.ts +302 -0
  65. package/dist/resources/backend.d.ts.map +1 -0
  66. package/dist/resources/backend.js +16 -0
  67. package/dist/resources/backend.js.map +1 -0
  68. package/dist/resources/baseline.d.ts +116 -0
  69. package/dist/resources/baseline.d.ts.map +1 -0
  70. package/dist/resources/baseline.js +447 -0
  71. package/dist/resources/baseline.js.map +1 -0
  72. package/dist/resources/canonical-json.d.ts +7 -0
  73. package/dist/resources/canonical-json.d.ts.map +1 -0
  74. package/dist/resources/canonical-json.js +75 -0
  75. package/dist/resources/canonical-json.js.map +1 -0
  76. package/dist/resources/errors.d.ts +23 -0
  77. package/dist/resources/errors.d.ts.map +1 -0
  78. package/dist/resources/errors.js +89 -0
  79. package/dist/resources/errors.js.map +1 -0
  80. package/dist/resources/execution.d.ts +90 -0
  81. package/dist/resources/execution.d.ts.map +1 -0
  82. package/dist/resources/execution.js +581 -0
  83. package/dist/resources/execution.js.map +1 -0
  84. package/dist/resources/index.d.ts +15 -0
  85. package/dist/resources/index.d.ts.map +1 -0
  86. package/dist/resources/index.js +15 -0
  87. package/dist/resources/index.js.map +1 -0
  88. package/dist/resources/journal.d.ts +138 -0
  89. package/dist/resources/journal.d.ts.map +1 -0
  90. package/dist/resources/journal.js +438 -0
  91. package/dist/resources/journal.js.map +1 -0
  92. package/dist/resources/leases.d.ts +51 -0
  93. package/dist/resources/leases.d.ts.map +1 -0
  94. package/dist/resources/leases.js +354 -0
  95. package/dist/resources/leases.js.map +1 -0
  96. package/dist/resources/permits.d.ts +52 -0
  97. package/dist/resources/permits.d.ts.map +1 -0
  98. package/dist/resources/permits.js +240 -0
  99. package/dist/resources/permits.js.map +1 -0
  100. package/dist/resources/persistence.d.ts +63 -0
  101. package/dist/resources/persistence.d.ts.map +1 -0
  102. package/dist/resources/persistence.js +522 -0
  103. package/dist/resources/persistence.js.map +1 -0
  104. package/dist/resources/registry.d.ts +56 -0
  105. package/dist/resources/registry.d.ts.map +1 -0
  106. package/dist/resources/registry.js +139 -0
  107. package/dist/resources/registry.js.map +1 -0
  108. package/dist/resources/resolve.d.ts +49 -0
  109. package/dist/resources/resolve.d.ts.map +1 -0
  110. package/dist/resources/resolve.js +309 -0
  111. package/dist/resources/resolve.js.map +1 -0
  112. package/dist/resources/sandbox.d.ts +72 -0
  113. package/dist/resources/sandbox.d.ts.map +1 -0
  114. package/dist/resources/sandbox.js +952 -0
  115. package/dist/resources/sandbox.js.map +1 -0
  116. package/dist/resources/schema.d.ts +195 -0
  117. package/dist/resources/schema.d.ts.map +1 -0
  118. package/dist/resources/schema.js +231 -0
  119. package/dist/resources/schema.js.map +1 -0
  120. package/dist/resources/types.d.ts +36 -0
  121. package/dist/resources/types.d.ts.map +1 -0
  122. package/dist/resources/types.js +75 -0
  123. package/dist/resources/types.js.map +1 -0
  124. package/dist/resume.d.ts +76 -0
  125. package/dist/resume.d.ts.map +1 -0
  126. package/dist/resume.js +190 -0
  127. package/dist/resume.js.map +1 -0
  128. package/dist/runner-core.d.ts +29 -0
  129. package/dist/runner-core.d.ts.map +1 -1
  130. package/dist/runner-core.js +311 -36
  131. package/dist/runner-core.js.map +1 -1
  132. package/dist/runtime/phases/parallel.d.ts +3 -0
  133. package/dist/runtime/phases/parallel.d.ts.map +1 -1
  134. package/dist/runtime/phases/parallel.js.map +1 -1
  135. package/dist/runtime/phases/reduce.d.ts +47 -0
  136. package/dist/runtime/phases/reduce.d.ts.map +1 -0
  137. package/dist/runtime/phases/reduce.js +195 -0
  138. package/dist/runtime/phases/reduce.js.map +1 -0
  139. package/dist/runtime/phases/script.d.ts.map +1 -1
  140. package/dist/runtime/phases/script.js +47 -9
  141. package/dist/runtime/phases/script.js.map +1 -1
  142. package/dist/runtime.d.ts +67 -1
  143. package/dist/runtime.d.ts.map +1 -1
  144. package/dist/runtime.js +904 -79
  145. package/dist/runtime.js.map +1 -1
  146. package/dist/schema.d.ts +135 -5
  147. package/dist/schema.d.ts.map +1 -1
  148. package/dist/schema.js +338 -21
  149. package/dist/schema.js.map +1 -1
  150. package/dist/store.d.ts +56 -0
  151. package/dist/store.d.ts.map +1 -1
  152. package/dist/store.js +5 -1
  153. package/dist/store.js.map +1 -1
  154. package/dist/trace.d.ts +3 -0
  155. package/dist/trace.d.ts.map +1 -1
  156. package/dist/trace.js.map +1 -1
  157. package/package.json +4 -3
@@ -0,0 +1,75 @@
1
+ import * as path from "node:path";
2
+ export function normalizeCanonicalPrefix(prefix) {
3
+ if (typeof prefix !== "string" || prefix.length === 0 || !path.isAbsolute(prefix)) {
4
+ throw new Error(`canonicalPrefix must be a non-empty absolute path: ${JSON.stringify(prefix)}`);
5
+ }
6
+ return path.normalize(prefix);
7
+ }
8
+ export function normalizeLeaseKey(key) {
9
+ if (typeof key.resourceDomainId !== "string" || key.resourceDomainId.trim().length === 0) {
10
+ throw new Error("resourceDomainId must be a non-empty string");
11
+ }
12
+ return {
13
+ resourceDomainId: key.resourceDomainId,
14
+ canonicalPrefix: normalizeCanonicalPrefix(key.canonicalPrefix),
15
+ };
16
+ }
17
+ export function canonicalPrefixContains(parent, child) {
18
+ const rel = path.relative(parent, child);
19
+ return rel === "" || (rel !== ".." && !rel.startsWith(`..${path.sep}`) && !path.isAbsolute(rel));
20
+ }
21
+ export function canonicalLeaseKeysOverlap(a, b) {
22
+ if (a.resourceDomainId !== b.resourceDomainId)
23
+ return false;
24
+ return canonicalPrefixContains(a.canonicalPrefix, b.canonicalPrefix) ||
25
+ canonicalPrefixContains(b.canonicalPrefix, a.canonicalPrefix);
26
+ }
27
+ export function compareLeaseKeys(a, b) {
28
+ return a.resourceDomainId.localeCompare(b.resourceDomainId) ||
29
+ a.canonicalPrefix.localeCompare(b.canonicalPrefix);
30
+ }
31
+ export function sameExecutionOwner(a, b) {
32
+ return a.runId === b.runId &&
33
+ a.phaseId === b.phaseId &&
34
+ a.attemptId === b.attemptId &&
35
+ a.unitId === b.unitId &&
36
+ a.ancestry.length === b.ancestry.length &&
37
+ a.ancestry.every((value, index) => value === b.ancestry[index]);
38
+ }
39
+ export function cloneExecutionOwner(owner) {
40
+ return {
41
+ runId: owner.runId,
42
+ phaseId: owner.phaseId,
43
+ attemptId: owner.attemptId,
44
+ unitId: owner.unitId,
45
+ ancestry: [...owner.ancestry],
46
+ };
47
+ }
48
+ /** Reduce same-domain writable scopes to a deterministic minimal prefix cover. */
49
+ export function minimalCanonicalScopeCover(scopes) {
50
+ const sorted = scopes.map(normalizeLeaseKey).sort(compareLeaseKeys);
51
+ const result = [];
52
+ for (const scope of sorted) {
53
+ if (result.some((existing) => existing.resourceDomainId === scope.resourceDomainId &&
54
+ canonicalPrefixContains(existing.canonicalPrefix, scope.canonicalPrefix))) {
55
+ continue;
56
+ }
57
+ for (let i = result.length - 1; i >= 0; i--) {
58
+ const existing = result[i];
59
+ if (existing.resourceDomainId === scope.resourceDomainId &&
60
+ canonicalPrefixContains(scope.canonicalPrefix, existing.canonicalPrefix)) {
61
+ result.splice(i, 1);
62
+ }
63
+ }
64
+ result.push(scope);
65
+ result.sort(compareLeaseKeys);
66
+ }
67
+ return result;
68
+ }
69
+ export function sameCanonicalScopes(a, b) {
70
+ const aa = minimalCanonicalScopeCover(a);
71
+ const bb = minimalCanonicalScopeCover(b);
72
+ return aa.length === bb.length && aa.every((scope, index) => scope.resourceDomainId === bb[index].resourceDomainId &&
73
+ scope.canonicalPrefix === bb[index].canonicalPrefix);
74
+ }
75
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/resources/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Resume overrides + immutable history — 0.2.0 dogfood issue 5.
3
+ *
4
+ * Resume creates a NEW RunState (new runId, `parentRunId` pointing at the
5
+ * original) and never mutates or overwrites the original run file. Reusable
6
+ * completed phase states are copied into the child; the target failed/paused
7
+ * phase + its transitive downstream dependents are cleared so they re-run.
8
+ *
9
+ * An optional `ResumeOverrides` API re-runs exactly one phase with a patched
10
+ * task/model/timeout/idleTimeout (applied to the CHILD's def only — the parent
11
+ * def is untouched). When no overrides are supplied, ordinary resume forks a
12
+ * new run that preserves all `done` phases and lets the runtime re-run the
13
+ * non-done (failed/paused/running) ones.
14
+ *
15
+ * The fork/apply helpers are pure so they can be unit-tested without touching
16
+ * the runtime or the filesystem. `forkRunForResume` fails closed when the
17
+ * stored definition or requested overrides are invalid. The host adapters
18
+ * (pi / MCP) call it and hand the child RunState to `executeTaskflow`.
19
+ */
20
+ import { type Phase, type Taskflow } from "./schema.ts";
21
+ import { type RunState } from "./store.ts";
22
+ /** Overrides for re-running exactly one phase on resume. `phaseId` is required;
23
+ * at least one of the other fields must be supplied. All values are applied to
24
+ * the CHILD's def only (the parent def + persisted file are never touched). */
25
+ export interface ResumeOverrides {
26
+ phaseId: string;
27
+ task?: string;
28
+ model?: string;
29
+ timeout?: number;
30
+ idleTimeout?: number;
31
+ }
32
+ /** Runs are resumable only when execution stopped non-terminally. Completed and
33
+ * blocked runs are immutable terminal history; use a fresh run or recompute. */
34
+ export declare function validateResumeRun(prev: RunState): {
35
+ ok: boolean;
36
+ errors: string[];
37
+ };
38
+ /** Validate resume overrides against a prior run. Returns structured errors.
39
+ * Checks: phaseId exists, at least one override field is present, and field
40
+ * values pass the normal Taskflow validator after applying the overrides. */
41
+ export declare function validateResumeOverrides(prev: RunState, ov: ResumeOverrides): {
42
+ ok: boolean;
43
+ errors: string[];
44
+ };
45
+ /** One resume validation contract for every host. Overrides are allowed to
46
+ * repair an invalid stored definition, so callers must not pre-validate the
47
+ * unpatched parent before dispatching here. */
48
+ export declare function validateResumeRequest(prev: RunState, overrides?: ResumeOverrides): {
49
+ ok: boolean;
50
+ errors: string[];
51
+ };
52
+ /** Apply resume overrides to a deep-cloned def (the parent def is never
53
+ * mutated). Returns the child def. Pure. */
54
+ export declare function applyResumeOverrides(def: Taskflow, ov: ResumeOverrides): Taskflow;
55
+ /** Compute the transitive DOWNSTREAM dependents of `target` (phases that depend
56
+ * on target, directly or transitively, via `dependsOn` ∪ `from`). Excludes the
57
+ * target itself. Sorted for deterministic output. */
58
+ export declare function transitiveDownstream(phases: Phase[], target: string): string[];
59
+ /** Fork a prior run into a NEW child RunState for resume. The child gets a fresh
60
+ * runId + `parentRunId` pointing at the parent; the parent is never mutated.
61
+ *
62
+ * - With `overrides`: the child def is patched (overrides applied to the target
63
+ * phase); the target + its transitive downstream are cleared (removed) so
64
+ * they re-run; other `done` phases are copied (within-run resume cache hits).
65
+ * - Without `overrides` (ordinary resume): the child def is a deep clone of the
66
+ * parent def; ALL `done` phases are copied; non-done (failed/paused/running)
67
+ * phases are omitted so the runtime re-runs them.
68
+ *
69
+ * `prev` is never mutated. Returns the child RunState (ready for
70
+ * `executeTaskflow`). */
71
+ export declare function forkRunForResume(prev: RunState, opts?: {
72
+ overrides?: ResumeOverrides;
73
+ cwd?: string;
74
+ host?: string;
75
+ }): RunState;
76
+ //# sourceMappingURL=resume.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resume.d.ts","sourceRoot":"","sources":["../src/resume.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAoC,KAAK,KAAK,EAAE,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC1F,OAAO,EAA6B,KAAK,QAAQ,EAAE,MAAM,YAAY,CAAC;AAGtE;;gFAEgF;AAChF,MAAM,WAAW,eAAe;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB;AAQD;gFACgF;AAChF,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,QAAQ,GAAG;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAOnF;AAED;;8EAE8E;AAC9E,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,eAAe,GAAG;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAoC9G;AAED;;+CAE+C;AAC/C,wBAAgB,qBAAqB,CACpC,IAAI,EAAE,QAAQ,EACd,SAAS,CAAC,EAAE,eAAe,GACzB;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAEnC;AAED;6CAC6C;AAC7C,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,QAAQ,EAAE,EAAE,EAAE,eAAe,GAAG,QAAQ,CASjF;AAED;;sDAEsD;AACtD,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAkB9E;AAED;;;;;;;;;;;0BAW0B;AAC1B,wBAAgB,gBAAgB,CAC/B,IAAI,EAAE,QAAQ,EACd,IAAI,GAAE;IAAE,SAAS,CAAC,EAAE,eAAe,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAO,GACrE,QAAQ,CA8CV"}
package/dist/resume.js ADDED
@@ -0,0 +1,190 @@
1
+ /**
2
+ * Resume overrides + immutable history — 0.2.0 dogfood issue 5.
3
+ *
4
+ * Resume creates a NEW RunState (new runId, `parentRunId` pointing at the
5
+ * original) and never mutates or overwrites the original run file. Reusable
6
+ * completed phase states are copied into the child; the target failed/paused
7
+ * phase + its transitive downstream dependents are cleared so they re-run.
8
+ *
9
+ * An optional `ResumeOverrides` API re-runs exactly one phase with a patched
10
+ * task/model/timeout/idleTimeout (applied to the CHILD's def only — the parent
11
+ * def is untouched). When no overrides are supplied, ordinary resume forks a
12
+ * new run that preserves all `done` phases and lets the runtime re-run the
13
+ * non-done (failed/paused/running) ones.
14
+ *
15
+ * The fork/apply helpers are pure so they can be unit-tested without touching
16
+ * the runtime or the filesystem. `forkRunForResume` fails closed when the
17
+ * stored definition or requested overrides are invalid. The host adapters
18
+ * (pi / MCP) call it and hand the child RunState to `executeTaskflow`.
19
+ */
20
+ import { validateTaskflow, dependenciesOf } from "./schema.js";
21
+ import { newRunId } from "./store.js";
22
+ import { getBuildInfo } from "./build-info.js";
23
+ function resumeStatusErrors(prev) {
24
+ return prev.status === "failed" || prev.status === "paused"
25
+ ? []
26
+ : [`Run '${prev.runId}' has status '${prev.status}' and is not resumable (expected failed or paused)`];
27
+ }
28
+ /** Runs are resumable only when execution stopped non-terminally. Completed and
29
+ * blocked runs are immutable terminal history; use a fresh run or recompute. */
30
+ export function validateResumeRun(prev) {
31
+ const errors = resumeStatusErrors(prev);
32
+ const validation = validateTaskflow(prev.def);
33
+ if (!validation.ok) {
34
+ errors.push(...validation.errors.map((error) => `stored run definition is invalid: ${error}`));
35
+ }
36
+ return { ok: errors.length === 0, errors };
37
+ }
38
+ /** Validate resume overrides against a prior run. Returns structured errors.
39
+ * Checks: phaseId exists, at least one override field is present, and field
40
+ * values pass the normal Taskflow validator after applying the overrides. */
41
+ export function validateResumeOverrides(prev, ov) {
42
+ // An override may intentionally repair an old/invalid stored definition, so
43
+ // validate the patched child below rather than rejecting the parent shape.
44
+ const errors = resumeStatusErrors(prev);
45
+ if (!ov.phaseId || typeof ov.phaseId !== "string") {
46
+ errors.push("resume overrides require a 'phaseId'");
47
+ return { ok: false, errors };
48
+ }
49
+ const phase = prev.def.phases.find((p) => p.id === ov.phaseId);
50
+ if (!phase) {
51
+ errors.push(`resume overrides target phase '${ov.phaseId}' not found in run '${prev.runId}' (flow '${prev.flowName}')`);
52
+ return { ok: false, errors };
53
+ }
54
+ // At least one override field must be supplied (besides phaseId).
55
+ const hasAny = ov.task !== undefined || ov.model !== undefined || ov.timeout !== undefined || ov.idleTimeout !== undefined;
56
+ if (!hasAny) {
57
+ errors.push("resume overrides require at least one of: task, model, timeout, idleTimeout (besides phaseId)");
58
+ }
59
+ // Field value sanity (the full def is re-validated after apply, but these
60
+ // give precise messages before constructing a child def).
61
+ if (ov.timeout !== undefined && (typeof ov.timeout !== "number" || !Number.isFinite(ov.timeout) || ov.timeout < 1000)) {
62
+ errors.push(`resume override 'timeout' must be a number >= 1000 ms, got ${ov.timeout}`);
63
+ }
64
+ if (ov.idleTimeout !== undefined && (typeof ov.idleTimeout !== "number" || !Number.isFinite(ov.idleTimeout) || ov.idleTimeout < 0)) {
65
+ errors.push(`resume override 'idleTimeout' must be a non-negative finite number (ms), got ${ov.idleTimeout}`);
66
+ }
67
+ if (errors.length)
68
+ return { ok: false, errors };
69
+ // Apply + validate the child def with the normal Taskflow validator so
70
+ // structural constraints (e.g. a patched task introducing a bad ref) are
71
+ // caught before the child run starts.
72
+ const childDef = applyResumeOverrides(prev.def, ov);
73
+ const v = validateTaskflow(childDef);
74
+ if (!v.ok) {
75
+ errors.push(...v.errors.map((e) => `resume override produced an invalid flow: ${e}`));
76
+ }
77
+ return { ok: errors.length === 0, errors };
78
+ }
79
+ /** One resume validation contract for every host. Overrides are allowed to
80
+ * repair an invalid stored definition, so callers must not pre-validate the
81
+ * unpatched parent before dispatching here. */
82
+ export function validateResumeRequest(prev, overrides) {
83
+ return overrides ? validateResumeOverrides(prev, overrides) : validateResumeRun(prev);
84
+ }
85
+ /** Apply resume overrides to a deep-cloned def (the parent def is never
86
+ * mutated). Returns the child def. Pure. */
87
+ export function applyResumeOverrides(def, ov) {
88
+ const child = structuredClone(def);
89
+ const phase = child.phases.find((p) => p.id === ov.phaseId);
90
+ if (!phase)
91
+ return child; // validateResumeOverrides reports the missing phase
92
+ if (ov.task !== undefined)
93
+ phase.task = ov.task;
94
+ if (ov.model !== undefined)
95
+ phase.model = ov.model;
96
+ if (ov.timeout !== undefined)
97
+ phase.timeout = ov.timeout;
98
+ if (ov.idleTimeout !== undefined)
99
+ phase.idleTimeout = ov.idleTimeout;
100
+ return child;
101
+ }
102
+ /** Compute the transitive DOWNSTREAM dependents of `target` (phases that depend
103
+ * on target, directly or transitively, via `dependsOn` ∪ `from`). Excludes the
104
+ * target itself. Sorted for deterministic output. */
105
+ export function transitiveDownstream(phases, target) {
106
+ const byId = new Map(phases.map((p) => [p.id, p]));
107
+ const seen = new Set();
108
+ const queue = [];
109
+ for (const p of phases) {
110
+ if (dependenciesOf(p).includes(target))
111
+ queue.push(p.id);
112
+ }
113
+ while (queue.length) {
114
+ const id = queue.shift();
115
+ if (seen.has(id))
116
+ continue;
117
+ seen.add(id);
118
+ const p = byId.get(id);
119
+ if (!p)
120
+ continue;
121
+ for (const dep of phases) {
122
+ if (dependenciesOf(dep).includes(id) && !seen.has(dep.id))
123
+ queue.push(dep.id);
124
+ }
125
+ }
126
+ return Array.from(seen).sort();
127
+ }
128
+ /** Fork a prior run into a NEW child RunState for resume. The child gets a fresh
129
+ * runId + `parentRunId` pointing at the parent; the parent is never mutated.
130
+ *
131
+ * - With `overrides`: the child def is patched (overrides applied to the target
132
+ * phase); the target + its transitive downstream are cleared (removed) so
133
+ * they re-run; other `done` phases are copied (within-run resume cache hits).
134
+ * - Without `overrides` (ordinary resume): the child def is a deep clone of the
135
+ * parent def; ALL `done` phases are copied; non-done (failed/paused/running)
136
+ * phases are omitted so the runtime re-runs them.
137
+ *
138
+ * `prev` is never mutated. Returns the child RunState (ready for
139
+ * `executeTaskflow`). */
140
+ export function forkRunForResume(prev, opts = {}) {
141
+ const ov = opts.overrides;
142
+ const validation = validateResumeRequest(prev, ov);
143
+ if (!validation.ok) {
144
+ throw new Error(`Cannot resume run '${prev.runId}': ${validation.errors.join("; ")}`);
145
+ }
146
+ const childDef = ov ? applyResumeOverrides(prev.def, ov) : structuredClone(prev.def);
147
+ // Phases to clear (re-run): the target + its transitive downstream (when
148
+ // overrides are supplied). Without overrides, nothing is force-cleared here —
149
+ // non-done phases are simply omitted and the runtime re-runs them.
150
+ const clearSet = new Set();
151
+ if (ov) {
152
+ clearSet.add(ov.phaseId);
153
+ for (const id of transitiveDownstream(prev.def.phases, ov.phaseId))
154
+ clearSet.add(id);
155
+ }
156
+ const phases = {};
157
+ for (const [id, ps] of Object.entries(prev.phases)) {
158
+ if (clearSet.has(id))
159
+ continue; // re-run
160
+ // Copy only completed (done) phases — failed/paused/running/skipped are
161
+ // re-run by the runtime. Deep-clone so the child cannot mutate nested
162
+ // usage/gate/read metadata retained by the immutable parent object.
163
+ if (ps.status === "done")
164
+ phases[id] = structuredClone(ps);
165
+ }
166
+ const build = getBuildInfo();
167
+ return {
168
+ runId: newRunId(prev.flowName),
169
+ flowName: prev.flowName,
170
+ def: childDef,
171
+ args: structuredClone(prev.args),
172
+ status: "running",
173
+ phases,
174
+ createdAt: Date.now(),
175
+ updatedAt: Date.now(),
176
+ cwd: opts.cwd ?? prev.cwd,
177
+ parentRunId: prev.runId,
178
+ // Preserve workspace provenance/authority so a resume cannot silently
179
+ // escape or downgrade the parent's cwd boundary.
180
+ ...(prev.invocationRootSnapshot !== undefined ? { invocationRootSnapshot: structuredClone(prev.invocationRootSnapshot) } : {}),
181
+ ...(prev.cwdRootBinding !== undefined ? { cwdRootBinding: structuredClone(prev.cwdRootBinding) } : {}),
182
+ // The child is executed by the CURRENT build and CURRENT host. A caller that
183
+ // does not supply host preserves the parent for backwards compatibility.
184
+ ...(opts.host !== undefined || prev.host !== undefined ? { host: opts.host ?? prev.host } : {}),
185
+ packageVersion: build.packageVersion,
186
+ gitCommit: build.gitCommit,
187
+ schemaVersion: build.schemaVersion,
188
+ };
189
+ }
190
+ //# sourceMappingURL=resume.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resume.js","sourceRoot":"","sources":["../src/resume.ts"],"names":[],"mappings":"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"}
@@ -40,9 +40,14 @@ export interface EventAccumulator {
40
40
  messages: CoreMessage[];
41
41
  usage: UsageStats;
42
42
  model?: string;
43
+ /** Last non-empty assistant text, mirrored for the shared process supervisor. */
44
+ finalText: string;
43
45
  stopReason?: string;
44
46
  errorMessage?: string;
45
47
  lastActivity: string;
48
+ /** Shared-supervisor aliases populated from Pi's message lifecycle. */
49
+ fatalError?: string;
50
+ terminalSeen?: boolean;
46
51
  /** Set when message cap was hit — output gets a truncation notice. */
47
52
  truncated?: boolean;
48
53
  }
@@ -61,6 +66,13 @@ export declare function mapWithConcurrencyLimit<TIn, TOut>(items: TIn[], concurr
61
66
  * numeric STRING (e.g. "1234"), and `number += string` silently corrupts to
62
67
  * string concatenation / NaN. This guard keeps usage accounting honest. */
63
68
  export declare function num(v: unknown): number;
69
+ /** Register a detached process group with the host-wide supervisor. Script
70
+ * phases and agent runners share this registry so external host termination
71
+ * cannot leave either kind of child mutating the workspace. */
72
+ export declare function registerProcessTree(pid: number): void;
73
+ /** Remove a process group after its stdio has closed and all descendants have
74
+ * been synchronously reaped. */
75
+ export declare function unregisterProcessTree(pid: number): void;
64
76
  /** Signal the whole process tree rooted at a spawned subagent. POSIX children
65
77
  * are process-group leaders (`detached:true` at spawn), so a negative pid
66
78
  * reaches every descendant in the group. Windows has no equivalent signal;
@@ -90,6 +102,17 @@ export interface SubagentAccumulator {
90
102
  fatalError?: string;
91
103
  /** Set by hosts whose protocol has an authoritative terminal event. */
92
104
  terminalSeen?: boolean;
105
+ /** Optional host-native terminal reason, used by completion policies. */
106
+ stopReason?: string;
107
+ }
108
+ export type CompletionEventClassification = "ignore" | "activity" | "terminal-candidate" | "fatal";
109
+ /** Optional host protocol layered over ordinary process exit. A terminal event
110
+ * is only a candidate: the shared supervisor waits a grace period, revokes the
111
+ * candidate on later activity, and commits only after canCommitTerminal passes. */
112
+ export interface CompletionPolicy<TAcc extends SubagentAccumulator> {
113
+ terminalGraceMs: number;
114
+ classifyEvent(acc: TAcc, event: unknown): CompletionEventClassification;
115
+ canCommitTerminal(acc: TAcc): boolean;
93
116
  }
94
117
  /** Standard "unknown agent" RunResult — identical across every host runner. */
95
118
  export declare function unknownAgentResult(agentName: string, task: string, agents: AgentConfig[]): RunResult;
@@ -106,11 +129,17 @@ export interface RunSubagentProcessOptions<TAcc extends SubagentAccumulator> {
106
129
  cwd: string;
107
130
  /** Execution knobs (forwarded from the phase's RunOptions). */
108
131
  idleTimeoutMs?: number;
132
+ /** @internal SIGTERM-to-SIGKILL grace. Defaults to 5s; injectable for
133
+ * deterministic supervisor tests. */
134
+ terminationGraceMs?: number;
109
135
  signal?: AbortSignal;
110
136
  onLive?: (live: LiveUpdate) => void;
111
137
  /** Per-host event folding: the host's accumulator + its line parser. */
112
138
  acc: TAcc;
113
139
  foldLine: (acc: TAcc, line: string) => LiveUpdate | null;
140
+ completionPolicy?: CompletionPolicy<TAcc>;
141
+ /** Synchronous notification at the terminal-reap linearization point. */
142
+ onTerminalCommit?: () => void;
114
143
  /** Fail closed when the CLI exits zero before its authoritative terminal event. */
115
144
  requireTerminalEvent?: boolean;
116
145
  terminalEventLabel?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"runner-core.d.ts","sourceRoot":"","sources":["../src/runner-core.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"runner-core.d.ts","sourceRoot":"","sources":["../src/runner-core.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAoB,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEzE,OAAO,EAAc,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AACzD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAIjF,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAE7G,wBAAgB,QAAQ,CAAC,CAAC,EAAE,SAAS,GAAG,OAAO,CAE9C;AAUD,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,SAAS,GAAG,OAAO,CAQtD;AAED;;+EAE+E;AAC/E,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAc9E;AAED;4EAC4E;AAC5E,eAAO,MAAM,2BAA2B,iDAAiD,CAAC;AAE1F,wEAAwE;AACxE,eAAO,MAAM,qBAAqB,OAAO,CAAC;AAE1C,qEAAqE;AACrE,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CActD;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAyBpE;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,WAAW,EAAE,GAAG,MAAM,CAU9D;AAED,sEAAsE;AACtE,MAAM,WAAW,gBAAgB;IAChC,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,KAAK,EAAE,UAAU,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iFAAiF;IACjF,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,uEAAuE;IACvE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,sEAAsE;IACtE,SAAS,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,wBAAgB,cAAc,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,gBAAgB,CAE/D;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,gBAAgB,EAAE,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAyCpF;AAwCD,0EAA0E;AAC1E,wBAAsB,uBAAuB,CAAC,GAAG,EAAE,IAAI,EACtD,KAAK,EAAE,GAAG,EAAE,EACZ,WAAW,EAAE,MAAM,EACnB,EAAE,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAC7C,OAAO,CAAC,IAAI,EAAE,CAAC,CAcjB;AAkBD;;;4EAG4E;AAC5E,wBAAgB,GAAG,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,CAGtC;AAOD;;+DAE+D;AAC/D,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAErD;AAED;gCACgC;AAChC,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAEvD;AAED;;;0EAG0E;AAC1E,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,EAAE,YAAY,GAAG,IAAI,CAyBhG;AAqDD,mFAAmF;AACnF,eAAO,MAAM,uBAAuB,QAAa,CAAC;AAElD;;yEAEyE;AACzE,eAAO,MAAM,4BAA4B,OAAO,CAAC;AAEjD;;;8EAG8E;AAC9E,eAAO,MAAM,qBAAqB,QAAc,CAAC;AAEjD;;gFAEgF;AAChF,MAAM,WAAW,mBAAmB;IACnC,KAAK,EAAE,UAAU,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+EAA+E;IAC/E,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,6EAA6E;IAC7E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uEAAuE;IACvE,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,yEAAyE;IACzE,UAAU,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,6BAA6B,GAAG,QAAQ,GAAG,UAAU,GAAG,oBAAoB,GAAG,OAAO,CAAC;AAEnG;;mFAEmF;AACnF,MAAM,WAAW,gBAAgB,CAAC,IAAI,SAAS,mBAAmB;IACjE,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,GAAG,6BAA6B,CAAC;IACxE,iBAAiB,CAAC,GAAG,EAAE,IAAI,GAAG,OAAO,CAAC;CACtC;AAED,+EAA+E;AAC/E,wBAAgB,kBAAkB,CACjC,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,WAAW,EAAE,GACnB,SAAS,CAYX;AAED,MAAM,WAAW,yBAAyB,CAAC,IAAI,SAAS,mBAAmB;IAC1E,2DAA2D;IAC3D,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;gFAC4E;IAC5E,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,+DAA+D;IAC/D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;yCACqC;IACrC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC;IACpC,wEAAwE;IACxE,GAAG,EAAE,IAAI,CAAC;IACV,QAAQ,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,KAAK,UAAU,GAAG,IAAI,CAAC;IACzD,gBAAgB,CAAC,EAAE,gBAAgB,CAAC,IAAI,CAAC,CAAC;IAC1C,yEAAyE;IACzE,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B,mFAAmF;IACnF,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;;iFAGiF;AACjF,wBAAsB,kBAAkB,CAAC,IAAI,SAAS,mBAAmB,EACxE,IAAI,EAAE,yBAAyB,CAAC,IAAI,CAAC,GACnC,OAAO,CAAC,SAAS,CAAC,CAsdpB"}