taskflow-core 0.2.1 → 0.2.3

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 (78) hide show
  1. package/README.md +5 -4
  2. package/dist/agents.d.ts +2 -2
  3. package/dist/agents.d.ts.map +1 -1
  4. package/dist/build-info.d.ts +48 -0
  5. package/dist/build-info.d.ts.map +1 -0
  6. package/dist/build-info.js +112 -0
  7. package/dist/build-info.js.map +1 -0
  8. package/dist/build-info.json +4 -0
  9. package/dist/detached-control.d.ts +52 -0
  10. package/dist/detached-control.d.ts.map +1 -0
  11. package/dist/detached-control.js +251 -0
  12. package/dist/detached-control.js.map +1 -0
  13. package/dist/detached-runner.js +183 -30
  14. package/dist/detached-runner.js.map +1 -1
  15. package/dist/exec/driver.d.ts +5 -0
  16. package/dist/exec/driver.d.ts.map +1 -1
  17. package/dist/exec/driver.js +27 -16
  18. package/dist/exec/driver.js.map +1 -1
  19. package/dist/exec/kernel-policy.d.ts.map +1 -1
  20. package/dist/exec/kernel-policy.js +10 -0
  21. package/dist/exec/kernel-policy.js.map +1 -1
  22. package/dist/exec/step-kinds.d.ts +14 -1
  23. package/dist/exec/step-kinds.d.ts.map +1 -1
  24. package/dist/exec/step-kinds.js +98 -3
  25. package/dist/exec/step-kinds.js.map +1 -1
  26. package/dist/exec/step.d.ts +21 -0
  27. package/dist/exec/step.d.ts.map +1 -1
  28. package/dist/exec/step.js +22 -5
  29. package/dist/exec/step.js.map +1 -1
  30. package/dist/final-output.d.ts +53 -0
  31. package/dist/final-output.d.ts.map +1 -0
  32. package/dist/final-output.js +65 -0
  33. package/dist/final-output.js.map +1 -0
  34. package/dist/flowir/canonical-hash.d.ts.map +1 -1
  35. package/dist/flowir/canonical-hash.js +2 -0
  36. package/dist/flowir/canonical-hash.js.map +1 -1
  37. package/dist/flowir/compile.d.ts.map +1 -1
  38. package/dist/flowir/compile.js +4 -0
  39. package/dist/flowir/compile.js.map +1 -1
  40. package/dist/flowir/meta.d.ts +3 -0
  41. package/dist/flowir/meta.d.ts.map +1 -1
  42. package/dist/flowir/schema.d.ts +3 -0
  43. package/dist/flowir/schema.d.ts.map +1 -1
  44. package/dist/flowir/schema.js.map +1 -1
  45. package/dist/flowir/translate.d.ts.map +1 -1
  46. package/dist/flowir/translate.js +4 -0
  47. package/dist/flowir/translate.js.map +1 -1
  48. package/dist/index.d.ts +4 -0
  49. package/dist/index.d.ts.map +1 -1
  50. package/dist/index.js +4 -0
  51. package/dist/index.js.map +1 -1
  52. package/dist/resume.d.ts +76 -0
  53. package/dist/resume.d.ts.map +1 -0
  54. package/dist/resume.js +190 -0
  55. package/dist/resume.js.map +1 -0
  56. package/dist/runner-core.d.ts.map +1 -1
  57. package/dist/runner-core.js +10 -0
  58. package/dist/runner-core.js.map +1 -1
  59. package/dist/runtime/phases/parallel.d.ts +3 -0
  60. package/dist/runtime/phases/parallel.d.ts.map +1 -1
  61. package/dist/runtime/phases/parallel.js.map +1 -1
  62. package/dist/runtime/phases/reduce.d.ts +47 -0
  63. package/dist/runtime/phases/reduce.d.ts.map +1 -0
  64. package/dist/runtime/phases/reduce.js +195 -0
  65. package/dist/runtime/phases/reduce.js.map +1 -0
  66. package/dist/runtime.d.ts +28 -1
  67. package/dist/runtime.d.ts.map +1 -1
  68. package/dist/runtime.js +412 -92
  69. package/dist/runtime.js.map +1 -1
  70. package/dist/schema.d.ts +67 -0
  71. package/dist/schema.d.ts.map +1 -1
  72. package/dist/schema.js +177 -1
  73. package/dist/schema.js.map +1 -1
  74. package/dist/store.d.ts +90 -2
  75. package/dist/store.d.ts.map +1 -1
  76. package/dist/store.js +494 -181
  77. package/dist/store.js.map +1 -1
  78. package/package.json +2 -2
package/README.md CHANGED
@@ -131,7 +131,7 @@ Save it as `.pi/taskflows/audit-api.json`, then run:
131
131
  /tf:audit-api dir=src/api
132
132
  ```
133
133
 
134
- On Codex, Claude Code, OpenCode, and Grok Build, run the same saved definition by name through `taskflow_run`.
134
+ On Codex, Claude Code, OpenCode, and Grok Build, run the same saved definition by name through `taskflow_run`. For long DAGs, use `mode: "background"`, then manage the durable run with `taskflow_runs` (`list` / `status` / `wait` / `cancel`); list output reports active concurrency and can filter `running` or `terminal` runs.
135
135
 
136
136
  [Follow the full quickstart →](https://heggria.github.io/taskflow/en/docs/getting-started)
137
137
 
@@ -200,7 +200,7 @@ FlowIR canonicalizes the graph and gives it a content hash. That compiled identi
200
200
  |---|---|---:|
201
201
  | `verify` / `compile` | Is the graph structurally safe to run? | **0** |
202
202
  | `ir` | What is the canonical graph and content hash? | **0** |
203
- | `resume` | What unfinished work remains? | Only unfinished phases |
203
+ | `resume` | What unfinished work remains? (forks a new run; original untouched) | Only unfinished phases |
204
204
  | `trace` | What calls and runtime decisions actually happened? | **0** to inspect |
205
205
  | `replay` | What if thresholds or budgets had been different? | **0** |
206
206
  | `why-stale` | What changed, and what depends on it? | **0** |
@@ -315,7 +315,7 @@ claude plugin install claude-taskflow@taskflow
315
315
 
316
316
  ```bash
317
317
  opencode mcp add taskflow -- \
318
- npx -y -p opencode-taskflow@0.2.1 opencode-taskflow-mcp
318
+ npx -y -p opencode-taskflow@0.2.3 opencode-taskflow-mcp
319
319
  ```
320
320
 
321
321
  [OpenCode guide →](https://heggria.github.io/taskflow/en/docs/guides/opencode)
@@ -324,7 +324,7 @@ opencode mcp add taskflow -- \
324
324
 
325
325
  ```bash
326
326
  grok mcp add taskflow -- \
327
- npx -y -p grok-taskflow@0.2.1 grok-taskflow-mcp
327
+ npx -y -p grok-taskflow@0.2.3 grok-taskflow-mcp
328
328
  ```
329
329
 
330
330
  Grok Build support is new in 0.2. Its CLI stream does not report token/cost usage, so budget-declaring flows are rejected rather than silently running without enforcement.
@@ -365,6 +365,7 @@ The test suite covers orchestration semantics, persistence and file-lock races,
365
365
  | [Host Guides](https://heggria.github.io/taskflow/en/docs/guides/) | Pi, Codex, Claude Code, OpenCode, and Grok setup |
366
366
  | [Reference](https://heggria.github.io/taskflow/en/docs/reference/) | Commands, shorthand, and exact tool surfaces |
367
367
  | [Showcase](https://heggria.github.io/taskflow/en/docs/showcase/) | Real flows and case studies |
368
+ | [0.2.0 Frontier Assessment](https://github.com/heggria/taskflow/blob/main/docs/taskflow-0.2.0-frontier-assessment.zh-CN.md) | Independent, evidence-based technical assessment (Chinese) |
368
369
 
369
370
  Also see [`examples/`](https://github.com/heggria/taskflow/blob/main/examples), the [changelog](https://github.com/heggria/taskflow/blob/main/CHANGELOG.md), and the [release guide](https://github.com/heggria/taskflow/blob/main/RELEASE.md).
370
371
 
package/dist/agents.d.ts CHANGED
@@ -18,9 +18,9 @@ export interface TaskflowSettings {
18
18
  builtInAgents: boolean;
19
19
  /** Whether package-local built-ins are copied into the current project's .pi/agents/. */
20
20
  syncBuiltinAgentsToProject: boolean;
21
- /** Maximum completed/failed runs to keep. 0 disables cleanup. */
21
+ /** Maximum inactive runs to keep. Running runs are never pruned. 0 disables cleanup. */
22
22
  maxKeptRuns: number;
23
- /** Maximum age (days) for completed/failed runs. 0 disables age cleanup. */
23
+ /** Maximum age (days) for inactive runs. Running runs are never pruned. 0 disables age cleanup. */
24
24
  maxRunAgeDays: number;
25
25
  /** Library (reusable-flow asset layer) settings. RFC: docs/rfc-library-reuse.md */
26
26
  library: LibrarySettings;
@@ -1 +1 @@
1
- {"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../src/agents.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../src/agents.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,CAAC;AAErD,MAAM,MAAM,sBAAsB,GAAG,UAAU,GAAG,WAAW,GAAG,SAAS,CAAC;AAE1E;iFACiF;AACjF,MAAM,WAAW,eAAe;IAC/B,eAAe,EAAE,sBAAsB,CAAC;IACxC,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;CACxB;AAED,eAAO,MAAM,yBAAyB,EAAE,eAIvC,CAAC;AAEF,MAAM,WAAW,gBAAgB;IAChC,+EAA+E;IAC/E,aAAa,EAAE,OAAO,CAAC;IACvB,yFAAyF;IACzF,0BAA0B,EAAE,OAAO,CAAC;IACpC,wFAAwF;IACxF,WAAW,EAAE,MAAM,CAAC;IACpB,mGAAmG;IACnG,aAAa,EAAE,MAAM,CAAC;IACtB,mFAAmF;IACnF,OAAO,EAAE,eAAe,CAAC;IACzB,yGAAyG;IACzG,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,sDAAsD;IACtD,OAAO,EAAE,eAAe,CAAC;CACzB;AAGD,OAAO,EAA4B,KAAK,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAEpF,eAAO,MAAM,yBAAyB,EAAE,gBAOvC,CAAC;AAEF,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,OAAO,GAAG,eAAe,CAkBtE;AAED,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,OAAO,GAAG,gBAAgB,CAiCxE;AAED;0DAC0D;AAC1D,MAAM,MAAM,cAAc,GACvB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,GAClF;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAE9D,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,OAAO,GAAG,eAAe,CAiBtE;AAED,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,OAAO,GAAG,cAAc,GAAG,SAAS,CAmBhF;AAED,wBAAgB,uBAAuB,CAAC,QAAQ,GAAE,gBAA4C,GAAG,OAAO,CAEvG;AAED,wBAAgB,gCAAgC,CAAC,QAAQ,GAAE,gBAA4C,GAAG,OAAO,CAEhH;AAED,MAAM,WAAW,WAAW;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,UAAU,CAAC;IACxC,QAAQ,EAAE,MAAM,CAAC;CACjB;AAED,gBAAgB;AAChB,MAAM,WAAW,oBAAoB;IACpC,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAyFD,wBAAgB,cAAc,CAC7B,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,UAAU,EACjB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACnC,gBAAgB,GAAE,gBAA4C,GAC5D,oBAAoB,CAwCtB;AAED,MAAM,WAAW,gBAAgB;IAChC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,QAAQ,EAAE,gBAAgB,CAAC;CAC3B;AAoBD,mGAAmG;AACnG,wBAAgB,oBAAoB,IAAI,gBAAgB,CAavD;AAED;;;;;;;;;GASG;AACH,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAmC5D"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Build identity — 0.2.0 dogfood issue 4.
3
+ *
4
+ * Exports the host-neutral build-info API: `packageVersion`, `gitCommit`, and
5
+ * the current run-state `schemaVersion`. Package version is sourced from
6
+ * package metadata (read at runtime — never runs git). The git commit is
7
+ * stamped at BUILD time into a generated `build-info.json` shipped under
8
+ * `dist/`; in a source/dev checkout (no build) it falls back to the
9
+ * `PI_TASKFLOW_BUILD_COMMIT` env var, then to the deterministic string
10
+ * `"unknown"`. **`git` is never invoked at runtime** (no `git rev-parse`, no
11
+ * `.git` read) — the stamp is purely a build-time artifact.
12
+ *
13
+ * The build stamp lives under `dist/` (gitignored) so a normal build never
14
+ * dirties the source tree. See `scripts/stamp-build-info.mjs`.
15
+ */
16
+ /** The current run-state schema version. Bumped when the persisted `RunState`
17
+ * shape changes in a way a loader should be aware of. Optional metadata
18
+ * fields (packageVersion/gitCommit/host/parentRunId) were added in this
19
+ * version; absent fields on old runs are tolerated (backward compatible). */
20
+ export declare const CURRENT_RUN_STATE_SCHEMA_VERSION = 1;
21
+ /** The deterministic fallback when no build stamp is available (source/dev
22
+ * checkout, or a build that could not determine the commit). */
23
+ export declare const UNKNOWN_BUILD_COMMIT = "unknown";
24
+ export interface BuildInfo {
25
+ /** Package version, sourced from the nearest package.json (runtime read). */
26
+ packageVersion: string;
27
+ /** Git commit the published dist was built from, stamped at build time.
28
+ * `"unknown"` in a source/dev checkout (no `git` is ever run at runtime). */
29
+ gitCommit: string;
30
+ /** The current run-state schema version (see CURRENT_RUN_STATE_SCHEMA_VERSION). */
31
+ schemaVersion: number;
32
+ /** When the build stamp was generated (ms epoch), if known. */
33
+ buildTime?: number;
34
+ }
35
+ /** Resolve the package version from the nearest package.json. Tries the
36
+ * taskflow-core package.json first, then walks up. Never throws — returns
37
+ * `"0.0.0"` if no version can be read. */
38
+ export declare function packageVersion(): string;
39
+ /** Resolve the git commit the dist was built from. NEVER runs `git` at runtime.
40
+ * Precedence: build stamp (dist/build-info.json) → PI_TASKFLOW_BUILD_COMMIT
41
+ * env → "unknown". */
42
+ export declare function gitCommit(): string;
43
+ /** The build timestamp (ms epoch) the dist was stamped at, if known. */
44
+ export declare function buildTime(): number | undefined;
45
+ /** The full build-info record. Host adapters stamp RunState + report this to
46
+ * `action=version` / `taskflow_version`. */
47
+ export declare function getBuildInfo(): BuildInfo;
48
+ //# sourceMappingURL=build-info.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-info.d.ts","sourceRoot":"","sources":["../src/build-info.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAMH;;;8EAG8E;AAC9E,eAAO,MAAM,gCAAgC,IAAI,CAAC;AAElD;iEACiE;AACjE,eAAO,MAAM,oBAAoB,YAAY,CAAC;AAE9C,MAAM,WAAW,SAAS;IACzB,6EAA6E;IAC7E,cAAc,EAAE,MAAM,CAAC;IACvB;kFAC8E;IAC9E,SAAS,EAAE,MAAM,CAAC;IAClB,mFAAmF;IACnF,aAAa,EAAE,MAAM,CAAC;IACtB,+DAA+D;IAC/D,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAKD;;2CAE2C;AAC3C,wBAAgB,cAAc,IAAI,MAAM,CAsBvC;AA6BD;;uBAEuB;AACvB,wBAAgB,SAAS,IAAI,MAAM,CAMlC;AAED,wEAAwE;AACxE,wBAAgB,SAAS,IAAI,MAAM,GAAG,SAAS,CAE9C;AAED;6CAC6C;AAC7C,wBAAgB,YAAY,IAAI,SAAS,CAQxC"}
@@ -0,0 +1,112 @@
1
+ /**
2
+ * Build identity — 0.2.0 dogfood issue 4.
3
+ *
4
+ * Exports the host-neutral build-info API: `packageVersion`, `gitCommit`, and
5
+ * the current run-state `schemaVersion`. Package version is sourced from
6
+ * package metadata (read at runtime — never runs git). The git commit is
7
+ * stamped at BUILD time into a generated `build-info.json` shipped under
8
+ * `dist/`; in a source/dev checkout (no build) it falls back to the
9
+ * `PI_TASKFLOW_BUILD_COMMIT` env var, then to the deterministic string
10
+ * `"unknown"`. **`git` is never invoked at runtime** (no `git rev-parse`, no
11
+ * `.git` read) — the stamp is purely a build-time artifact.
12
+ *
13
+ * The build stamp lives under `dist/` (gitignored) so a normal build never
14
+ * dirties the source tree. See `scripts/stamp-build-info.mjs`.
15
+ */
16
+ import { readFileSync } from "node:fs";
17
+ import { dirname, join } from "node:path";
18
+ import { fileURLToPath } from "node:url";
19
+ /** The current run-state schema version. Bumped when the persisted `RunState`
20
+ * shape changes in a way a loader should be aware of. Optional metadata
21
+ * fields (packageVersion/gitCommit/host/parentRunId) were added in this
22
+ * version; absent fields on old runs are tolerated (backward compatible). */
23
+ export const CURRENT_RUN_STATE_SCHEMA_VERSION = 1;
24
+ /** The deterministic fallback when no build stamp is available (source/dev
25
+ * checkout, or a build that could not determine the commit). */
26
+ export const UNKNOWN_BUILD_COMMIT = "unknown";
27
+ let cachedPackageVersion;
28
+ let cachedStamp;
29
+ /** Resolve the package version from the nearest package.json. Tries the
30
+ * taskflow-core package.json first, then walks up. Never throws — returns
31
+ * `"0.0.0"` if no version can be read. */
32
+ export function packageVersion() {
33
+ if (cachedPackageVersion !== undefined)
34
+ return cachedPackageVersion;
35
+ const here = dirname(fileURLToPath(import.meta.url));
36
+ // src/build-info.ts → ../package.json (taskflow-core). In dist, build-info.js
37
+ // is at dist/build-info.js → ../package.json is still taskflow-core's.
38
+ const candidates = [join(here, "..", "package.json"), join(here, "..", "..", "package.json")];
39
+ for (const p of candidates) {
40
+ try {
41
+ const pkg = JSON.parse(readFileSync(p, "utf8"));
42
+ if (pkg && typeof pkg === "object" && "version" in pkg) {
43
+ const v = pkg.version;
44
+ if (typeof v === "string" && v) {
45
+ cachedPackageVersion = v;
46
+ return v;
47
+ }
48
+ }
49
+ }
50
+ catch {
51
+ /* try next candidate */
52
+ }
53
+ }
54
+ cachedPackageVersion = "0.0.0";
55
+ return cachedPackageVersion;
56
+ }
57
+ /** Read the build-time stamp (generated by scripts/stamp-build-info.mjs into
58
+ * dist/build-info.json). Returns `{}` when absent (source/dev checkout). */
59
+ function readBuildStamp() {
60
+ if (cachedStamp !== undefined)
61
+ return cachedStamp;
62
+ const here = dirname(fileURLToPath(import.meta.url));
63
+ // In dist: build-info.js → ./build-info.json (sibling). In src: the stamp
64
+ // is not generated (dev checkout) → readFileSync throws → {}.
65
+ const stampPath = join(here, "build-info.json");
66
+ try {
67
+ const raw = JSON.parse(readFileSync(stampPath, "utf8"));
68
+ const stamp = {};
69
+ if (raw && typeof raw === "object") {
70
+ if (typeof raw.gitCommit === "string") {
71
+ stamp.gitCommit = raw.gitCommit;
72
+ }
73
+ if (typeof raw.buildTime === "number") {
74
+ stamp.buildTime = raw.buildTime;
75
+ }
76
+ }
77
+ cachedStamp = stamp;
78
+ return stamp;
79
+ }
80
+ catch {
81
+ cachedStamp = {};
82
+ return cachedStamp;
83
+ }
84
+ }
85
+ /** Resolve the git commit the dist was built from. NEVER runs `git` at runtime.
86
+ * Precedence: build stamp (dist/build-info.json) → PI_TASKFLOW_BUILD_COMMIT
87
+ * env → "unknown". */
88
+ export function gitCommit() {
89
+ const stamp = readBuildStamp();
90
+ if (stamp.gitCommit)
91
+ return stamp.gitCommit;
92
+ const env = process.env.PI_TASKFLOW_BUILD_COMMIT;
93
+ if (typeof env === "string" && env.trim())
94
+ return env.trim();
95
+ return UNKNOWN_BUILD_COMMIT;
96
+ }
97
+ /** The build timestamp (ms epoch) the dist was stamped at, if known. */
98
+ export function buildTime() {
99
+ return readBuildStamp().buildTime;
100
+ }
101
+ /** The full build-info record. Host adapters stamp RunState + report this to
102
+ * `action=version` / `taskflow_version`. */
103
+ export function getBuildInfo() {
104
+ const stampedBuildTime = buildTime();
105
+ return {
106
+ packageVersion: packageVersion(),
107
+ gitCommit: gitCommit(),
108
+ schemaVersion: CURRENT_RUN_STATE_SCHEMA_VERSION,
109
+ ...(stampedBuildTime !== undefined ? { buildTime: stampedBuildTime } : {}),
110
+ };
111
+ }
112
+ //# sourceMappingURL=build-info.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-info.js","sourceRoot":"","sources":["../src/build-info.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ {
2
+ "gitCommit": "b0a3c22058941f05d7ae3a4072e3721de9e24d5c",
3
+ "buildTime": 1784369228000
4
+ }
@@ -0,0 +1,52 @@
1
+ /**
2
+ * File-backed control plane for detached Taskflow runs.
3
+ *
4
+ * A detached runner cannot rely on an IPC channel surviving its parent MCP
5
+ * process. Cancellation is therefore requested through a small durable marker
6
+ * in a user-private control directory keyed by the canonical invocation root.
7
+ * The child polls that marker and aborts the normal RuntimeDeps signal,
8
+ * preserving the runtime's existing paused semantics and process-tree cleanup.
9
+ */
10
+ export interface DetachedCancelRequest {
11
+ requestedAt: number;
12
+ reason?: string;
13
+ }
14
+ export declare const DETACHED_CONTROL_VERSION = 1;
15
+ export declare const DETACHED_CONTROL_CWD_ENV = "TASKFLOW_DETACHED_CONTROL_CWD";
16
+ export declare const DETACHED_CONTROL_RUN_ID_ENV = "TASKFLOW_DETACHED_CONTROL_RUN_ID";
17
+ export declare const DETACHED_CONTROL_INSTANCE_ENV = "TASKFLOW_DETACHED_CONTROL_INSTANCE";
18
+ export declare const DETACHED_CONTROL_OWNER_PID_ENV = "TASKFLOW_DETACHED_CONTROL_OWNER_PID";
19
+ export declare const DETACHED_CONTROL_SIGNAL_READY_ENV = "TASKFLOW_DETACHED_CONTROL_SIGNAL_READY";
20
+ export interface DetachedProcessRegistry {
21
+ version: number;
22
+ instanceId: string;
23
+ ownerPid: number;
24
+ heartbeatAt: number;
25
+ pids: number[];
26
+ }
27
+ /** Resolve the cancel marker for a run without accepting caller-selected paths. */
28
+ export declare function detachedCancelRequestPath(cwd: string, runId: string): string;
29
+ /** Persist an idempotent cancellation request for a detached runner. */
30
+ export declare function requestDetachedCancel(cwd: string, runId: string, reason?: string): DetachedCancelRequest;
31
+ /** Read a cancellation request. Corrupt markers still mean "cancel" fail-safe. */
32
+ export declare function readDetachedCancelRequest(cwd: string, runId: string): DetachedCancelRequest | null;
33
+ export declare function clearDetachedCancelRequest(cwd: string, runId: string): void;
34
+ export declare function detachedProcessRegistryPath(cwd: string, runId: string): string;
35
+ export declare function readDetachedProcessRegistry(cwd: string, runId: string): DetachedProcessRegistry | null;
36
+ export declare function heartbeatDetachedProcessRegistry(cwd: string, runId: string, instanceId: string, ownerPid?: number): void;
37
+ /** True only after this exact detached owner installed its persistence-aware signal bridge. */
38
+ export declare function isDetachedSignalOwnerReady(): boolean;
39
+ /** Best-effort hook used by runner-core whenever a Host CLI process group starts. */
40
+ export declare function registerDetachedProcessTreeFromEnv(pid: number): void;
41
+ /** Best-effort hook used by runner-core after a Host CLI process group is reaped. */
42
+ export declare function unregisterDetachedProcessTreeFromEnv(pid: number): void;
43
+ /** Reap every Host CLI process group owned by exactly this worker instance. */
44
+ export declare function terminateDetachedProcessTrees(cwd: string, runId: string, instanceId: string): number[];
45
+ export declare function clearDetachedProcessRegistry(cwd: string, runId: string, instanceId?: string): void;
46
+ /**
47
+ * Poll a detached cancellation marker and bridge it into an AbortController.
48
+ * Returns a cleanup callback. The timer is unref'd so it never keeps a
49
+ * completed detached runner alive by itself.
50
+ */
51
+ export declare function watchDetachedCancel(cwd: string, runId: string, controller: AbortController, pollMs?: number, onRequest?: (request: DetachedCancelRequest) => void): () => void;
52
+ //# sourceMappingURL=detached-control.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detached-control.d.ts","sourceRoot":"","sources":["../src/detached-control.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAOH,MAAM,WAAW,qBAAqB;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAKD,eAAO,MAAM,wBAAwB,IAAkB,CAAC;AACxD,eAAO,MAAM,wBAAwB,kCAAkC,CAAC;AACxE,eAAO,MAAM,2BAA2B,qCAAqC,CAAC;AAC9E,eAAO,MAAM,6BAA6B,uCAAuC,CAAC;AAClF,eAAO,MAAM,8BAA8B,wCAAwC,CAAC;AACpF,eAAO,MAAM,iCAAiC,2CAA2C,CAAC;AAE1F,MAAM,WAAW,uBAAuB;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,EAAE,CAAC;CACf;AAkBD,mFAAmF;AACnF,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAE5E;AAED,wEAAwE;AACxE,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,qBAAqB,CAUxG;AAED,kFAAkF;AAClF,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,qBAAqB,GAAG,IAAI,CAiBlG;AAED,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAO3E;AAED,wBAAgB,2BAA2B,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAE9E;AAED,wBAAgB,2BAA2B,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,uBAAuB,GAAG,IAAI,CAuBtG;AAOD,wBAAgB,gCAAgC,CAC/C,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,MAAM,EAClB,QAAQ,SAAc,GACpB,IAAI,CAUN;AAcD,+FAA+F;AAC/F,wBAAgB,0BAA0B,IAAI,OAAO,CAGpD;AAED,qFAAqF;AACrF,wBAAgB,kCAAkC,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAcpE;AAED,qFAAqF;AACrF,wBAAgB,oCAAoC,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAYtE;AAmBD,+EAA+E;AAC/E,wBAAgB,6BAA6B,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAKtG;AAED,wBAAgB,4BAA4B,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAOlG;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAClC,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,eAAe,EAC3B,MAAM,SAAkB,EACxB,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,qBAAqB,KAAK,IAAI,GAClD,MAAM,IAAI,CAaZ"}
@@ -0,0 +1,251 @@
1
+ /**
2
+ * File-backed control plane for detached Taskflow runs.
3
+ *
4
+ * A detached runner cannot rely on an IPC channel surviving its parent MCP
5
+ * process. Cancellation is therefore requested through a small durable marker
6
+ * in a user-private control directory keyed by the canonical invocation root.
7
+ * The child polls that marker and aborts the normal RuntimeDeps signal,
8
+ * preserving the runtime's existing paused semantics and process-tree cleanup.
9
+ */
10
+ import * as fs from "node:fs";
11
+ import * as path from "node:path";
12
+ import { spawnSync } from "node:child_process";
13
+ import { detachedControlDir, validateRunId, writeFileAtomic } from "./store.js";
14
+ const DEFAULT_POLL_MS = 250;
15
+ const CONTROL_VERSION = 1;
16
+ export const DETACHED_CONTROL_VERSION = CONTROL_VERSION;
17
+ export const DETACHED_CONTROL_CWD_ENV = "TASKFLOW_DETACHED_CONTROL_CWD";
18
+ export const DETACHED_CONTROL_RUN_ID_ENV = "TASKFLOW_DETACHED_CONTROL_RUN_ID";
19
+ export const DETACHED_CONTROL_INSTANCE_ENV = "TASKFLOW_DETACHED_CONTROL_INSTANCE";
20
+ export const DETACHED_CONTROL_OWNER_PID_ENV = "TASKFLOW_DETACHED_CONTROL_OWNER_PID";
21
+ export const DETACHED_CONTROL_SIGNAL_READY_ENV = "TASKFLOW_DETACHED_CONTROL_SIGNAL_READY";
22
+ function ensureControlDir(cwd) {
23
+ const dir = detachedControlDir(cwd);
24
+ fs.mkdirSync(dir, { recursive: true, mode: 0o700 });
25
+ const stat = fs.lstatSync(dir);
26
+ if (!stat.isDirectory() || stat.isSymbolicLink()) {
27
+ throw new Error("Detached control root must be a private physical directory");
28
+ }
29
+ try {
30
+ fs.chmodSync(dir, 0o700);
31
+ }
32
+ catch { /* Windows / restrictive filesystem */ }
33
+ return dir;
34
+ }
35
+ function controlPath(cwd, runId, suffix) {
36
+ if (!validateRunId(runId))
37
+ throw new Error("Invalid runId for detached control");
38
+ return path.join(detachedControlDir(cwd), `${runId}.${suffix}.json`);
39
+ }
40
+ /** Resolve the cancel marker for a run without accepting caller-selected paths. */
41
+ export function detachedCancelRequestPath(cwd, runId) {
42
+ return controlPath(cwd, runId, "cancel");
43
+ }
44
+ /** Persist an idempotent cancellation request for a detached runner. */
45
+ export function requestDetachedCancel(cwd, runId, reason) {
46
+ ensureControlDir(cwd);
47
+ const request = {
48
+ requestedAt: Date.now(),
49
+ ...(typeof reason === "string" && reason.trim()
50
+ ? { reason: reason.trim().slice(0, 500) }
51
+ : {}),
52
+ };
53
+ writeFileAtomic(detachedCancelRequestPath(cwd, runId), `${JSON.stringify(request)}\n`);
54
+ return request;
55
+ }
56
+ /** Read a cancellation request. Corrupt markers still mean "cancel" fail-safe. */
57
+ export function readDetachedCancelRequest(cwd, runId) {
58
+ const filePath = detachedCancelRequestPath(cwd, runId);
59
+ if (!fs.existsSync(filePath))
60
+ return null;
61
+ try {
62
+ const parsed = JSON.parse(fs.readFileSync(filePath, "utf8"));
63
+ if (typeof parsed === "object" && parsed !== null) {
64
+ const record = parsed;
65
+ return {
66
+ requestedAt: typeof record.requestedAt === "number" ? record.requestedAt : Date.now(),
67
+ ...(typeof record.reason === "string" ? { reason: record.reason } : {}),
68
+ };
69
+ }
70
+ }
71
+ catch {
72
+ // The marker exists, so fail safe and cancel even if its optional metadata
73
+ // was truncated or externally corrupted.
74
+ }
75
+ return { requestedAt: Date.now(), reason: "Cancellation marker was unreadable" };
76
+ }
77
+ export function clearDetachedCancelRequest(cwd, runId) {
78
+ try {
79
+ fs.unlinkSync(detachedCancelRequestPath(cwd, runId));
80
+ }
81
+ catch {
82
+ /* missing/already consumed */
83
+ }
84
+ try {
85
+ fs.rmdirSync(detachedControlDir(cwd));
86
+ }
87
+ catch { /* other markers / missing */ }
88
+ }
89
+ export function detachedProcessRegistryPath(cwd, runId) {
90
+ return controlPath(cwd, runId, "processes");
91
+ }
92
+ export function readDetachedProcessRegistry(cwd, runId) {
93
+ const filePath = detachedProcessRegistryPath(cwd, runId);
94
+ try {
95
+ const parsed = JSON.parse(fs.readFileSync(filePath, "utf8"));
96
+ if (typeof parsed !== "object" || parsed === null)
97
+ return null;
98
+ const value = parsed;
99
+ if (value.version !== CONTROL_VERSION ||
100
+ typeof value.instanceId !== "string" ||
101
+ !Number.isSafeInteger(value.ownerPid) ||
102
+ typeof value.heartbeatAt !== "number" ||
103
+ !Array.isArray(value.pids))
104
+ return null;
105
+ return {
106
+ version: CONTROL_VERSION,
107
+ instanceId: value.instanceId,
108
+ ownerPid: value.ownerPid,
109
+ heartbeatAt: value.heartbeatAt,
110
+ pids: value.pids.filter((pid) => Number.isSafeInteger(pid) && Number(pid) > 0),
111
+ };
112
+ }
113
+ catch {
114
+ return null;
115
+ }
116
+ }
117
+ function writeDetachedProcessRegistry(cwd, runId, registry) {
118
+ ensureControlDir(cwd);
119
+ writeFileAtomic(detachedProcessRegistryPath(cwd, runId), `${JSON.stringify(registry)}\n`);
120
+ }
121
+ export function heartbeatDetachedProcessRegistry(cwd, runId, instanceId, ownerPid = process.pid) {
122
+ const existing = readDetachedProcessRegistry(cwd, runId);
123
+ const pids = existing?.instanceId === instanceId ? existing.pids : [];
124
+ writeDetachedProcessRegistry(cwd, runId, {
125
+ version: CONTROL_VERSION,
126
+ instanceId,
127
+ ownerPid,
128
+ heartbeatAt: Date.now(),
129
+ pids,
130
+ });
131
+ }
132
+ function processRegistryContextFromEnv() {
133
+ const cwd = process.env[DETACHED_CONTROL_CWD_ENV];
134
+ const runId = process.env[DETACHED_CONTROL_RUN_ID_ENV];
135
+ const instanceId = process.env[DETACHED_CONTROL_INSTANCE_ENV];
136
+ // Host CLIs inherit the detached worker's environment. Only the process that
137
+ // owns this exact PID token may mutate the outer worker's registry; nested
138
+ // Taskflow instances must not overwrite its heartbeat/owner identity.
139
+ if (process.env[DETACHED_CONTROL_OWNER_PID_ENV] !== String(process.pid))
140
+ return null;
141
+ if (!cwd || !runId || !instanceId || !validateRunId(runId))
142
+ return null;
143
+ return { cwd, runId, instanceId };
144
+ }
145
+ /** True only after this exact detached owner installed its persistence-aware signal bridge. */
146
+ export function isDetachedSignalOwnerReady() {
147
+ return process.env[DETACHED_CONTROL_OWNER_PID_ENV] === String(process.pid) &&
148
+ process.env[DETACHED_CONTROL_SIGNAL_READY_ENV] === "1";
149
+ }
150
+ /** Best-effort hook used by runner-core whenever a Host CLI process group starts. */
151
+ export function registerDetachedProcessTreeFromEnv(pid) {
152
+ const context = processRegistryContextFromEnv();
153
+ if (!context || !Number.isSafeInteger(pid) || pid <= 0)
154
+ return;
155
+ try {
156
+ const existing = readDetachedProcessRegistry(context.cwd, context.runId);
157
+ const pids = existing?.instanceId === context.instanceId ? existing.pids : [];
158
+ writeDetachedProcessRegistry(context.cwd, context.runId, {
159
+ version: CONTROL_VERSION,
160
+ instanceId: context.instanceId,
161
+ ownerPid: process.pid,
162
+ heartbeatAt: Date.now(),
163
+ pids: [...new Set([...pids, pid])],
164
+ });
165
+ }
166
+ catch { /* lifecycle diagnostics must never replace phase execution */ }
167
+ }
168
+ /** Best-effort hook used by runner-core after a Host CLI process group is reaped. */
169
+ export function unregisterDetachedProcessTreeFromEnv(pid) {
170
+ const context = processRegistryContextFromEnv();
171
+ if (!context)
172
+ return;
173
+ try {
174
+ const existing = readDetachedProcessRegistry(context.cwd, context.runId);
175
+ if (!existing || existing.instanceId !== context.instanceId)
176
+ return;
177
+ writeDetachedProcessRegistry(context.cwd, context.runId, {
178
+ ...existing,
179
+ heartbeatAt: Date.now(),
180
+ pids: existing.pids.filter((candidate) => candidate !== pid),
181
+ });
182
+ }
183
+ catch { /* lifecycle diagnostics must never replace phase execution */ }
184
+ }
185
+ function killRegisteredProcessTree(pid) {
186
+ if (!Number.isSafeInteger(pid) || pid <= 0 || pid === process.pid)
187
+ return;
188
+ if (process.platform === "win32") {
189
+ try {
190
+ spawnSync("taskkill", ["/PID", String(pid), "/T", "/F"], {
191
+ shell: false,
192
+ stdio: "ignore",
193
+ windowsHide: true,
194
+ });
195
+ }
196
+ catch { /* already gone / taskkill unavailable */ }
197
+ return;
198
+ }
199
+ try {
200
+ process.kill(-pid, "SIGKILL");
201
+ }
202
+ catch {
203
+ try {
204
+ process.kill(pid, "SIGKILL");
205
+ }
206
+ catch { /* already gone */ }
207
+ }
208
+ }
209
+ /** Reap every Host CLI process group owned by exactly this worker instance. */
210
+ export function terminateDetachedProcessTrees(cwd, runId, instanceId) {
211
+ const registry = readDetachedProcessRegistry(cwd, runId);
212
+ if (!registry || registry.instanceId !== instanceId)
213
+ return [];
214
+ for (const pid of registry.pids)
215
+ killRegisteredProcessTree(pid);
216
+ return registry.pids;
217
+ }
218
+ export function clearDetachedProcessRegistry(cwd, runId, instanceId) {
219
+ try {
220
+ const existing = readDetachedProcessRegistry(cwd, runId);
221
+ if (instanceId && existing && existing.instanceId !== instanceId)
222
+ return;
223
+ fs.unlinkSync(detachedProcessRegistryPath(cwd, runId));
224
+ }
225
+ catch { /* missing/already cleared */ }
226
+ try {
227
+ fs.rmdirSync(detachedControlDir(cwd));
228
+ }
229
+ catch { /* other markers / missing */ }
230
+ }
231
+ /**
232
+ * Poll a detached cancellation marker and bridge it into an AbortController.
233
+ * Returns a cleanup callback. The timer is unref'd so it never keeps a
234
+ * completed detached runner alive by itself.
235
+ */
236
+ export function watchDetachedCancel(cwd, runId, controller, pollMs = DEFAULT_POLL_MS, onRequest) {
237
+ const check = () => {
238
+ if (controller.signal.aborted)
239
+ return;
240
+ const request = readDetachedCancelRequest(cwd, runId);
241
+ if (request) {
242
+ onRequest?.(request);
243
+ controller.abort(request);
244
+ }
245
+ };
246
+ check();
247
+ const timer = setInterval(check, Math.max(50, pollMs));
248
+ timer.unref();
249
+ return () => clearInterval(timer);
250
+ }
251
+ //# sourceMappingURL=detached-control.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detached-control.js","sourceRoot":"","sources":["../src/detached-control.ts"],"names":[],"mappings":"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"}