hermes-taskflow 0.3.0-beta.1.1 → 1.0.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.
package/README.md
CHANGED
|
@@ -11,23 +11,23 @@
|
|
|
11
11
|
|
|
12
12
|
**English** · [简体中文](https://github.com/heggria/taskflow/blob/main/README.zh-CN.md)
|
|
13
13
|
|
|
14
|
-
[0
|
|
14
|
+
[1.0 overview](#taskflow-10-declarative-coding-agent-workflows) · [Quickstart](#quickstart) · [Docs](https://heggria.github.io/taskflow/en/docs) · [Examples](https://github.com/heggria/taskflow/blob/main/examples) · [Changelog](https://github.com/heggria/taskflow/blob/main/CHANGELOG.md)
|
|
15
15
|
|
|
16
16
|
</div>
|
|
17
17
|
|
|
18
18
|
---
|
|
19
19
|
|
|
20
|
-
# taskflow 0
|
|
20
|
+
# taskflow 1.0: declarative coding-agent workflows
|
|
21
21
|
|
|
22
|
-
**taskflow is a declarative runtime for coding-agent workflows.** It turns a graph into a verifiable execution contract, runs phases in isolation, and keeps intermediate work out of the host conversation. In
|
|
22
|
+
**taskflow is a declarative runtime for coding-agent workflows.** It turns a graph into a verifiable execution contract, runs phases in isolation, and keeps intermediate work out of the host conversation. In Taskflow 1.0, the contract also describes the effects a phase is allowed to propose.
|
|
23
23
|
|
|
24
|
-
> **
|
|
24
|
+
> **Taskflow 1.0.0** includes the DAG runtime, trusted filesystem effects and complete Control Plane (CLI/MCP/WebUI). [GitHub Releases](https://github.com/heggria/taskflow/releases) and npm establish publication; see the [acceptance scoreboard](https://github.com/heggria/taskflow/blob/main/docs/internal/1.0.0-ga-scoreboard.md) for verified scope and limits.
|
|
25
25
|
|
|
26
|
-
## The
|
|
26
|
+
## The declared-effect contract
|
|
27
27
|
|
|
28
28
|
An agent can propose content. It should not become the mutation authority merely because it can run a command.
|
|
29
29
|
|
|
30
|
-
For admitted, declared filesystem-write targets, taskflow 0
|
|
30
|
+
For admitted, declared filesystem-write targets, taskflow 1.0 makes the path explicit and routes the final mutation through the resources transaction:
|
|
31
31
|
|
|
32
32
|
```text
|
|
33
33
|
flow / .tf.ts
|
|
@@ -47,39 +47,40 @@ flow / .tf.ts
|
|
|
47
47
|
|
|
48
48
|
This is **not** an OS sandbox. Resolve-only hosts cannot prevent every write to an undeclared path. Secret and service references are typed and fail closed in this cut; they do not imply a vault or network backend.
|
|
49
49
|
|
|
50
|
-
##
|
|
50
|
+
## The 1.0 target and current implementation
|
|
51
51
|
|
|
52
|
-
| Layer | What it does |
|
|
52
|
+
| Layer | What it does | Support boundary |
|
|
53
53
|
|---|---|---|
|
|
54
|
-
| **Taskflow runtime** | Declarative DAGs, 12 phase types, budgets, retries, approvals, isolation, resume, replay, trace, and recompute |
|
|
55
|
-
| **Trusted Effects** | Closed `EffectIR`, `PathRef` / `SecretRef` / `ServiceRef`, confidentiality/integrity labels, effect validation, overlap checks, and ledger-backed `why-*` explainers |
|
|
56
|
-
| **Resource transaction** | Snapshot → lease → durable intent/permit → stage → commit, or restore and reject |
|
|
54
|
+
| **Taskflow runtime** | Declarative DAGs, 12 phase types, budgets, retries, approvals, isolation, resume, replay, trace, and recompute | Stable runtime contract |
|
|
55
|
+
| **Trusted Effects** | Closed `EffectIR`, `PathRef` / `SecretRef` / `ServiceRef`, confidentiality/integrity labels, effect validation, overlap checks, and ledger-backed `why-*` explainers | Declared-target contract |
|
|
56
|
+
| **Resource transaction** | Snapshot → lease → durable intent/permit → stage → commit, or restore and reject | Declared-target contract |
|
|
57
57
|
| **Host adapters** | Pi, Codex, Claude Code, OpenCode, Grok Build, and Hermes Agent use the same flow contract | Existing host surface; support remains host-specific |
|
|
58
|
-
| **Control Plane** |
|
|
59
|
-
| **WebUI** | Runs,
|
|
58
|
+
| **Control Plane** | Authenticated multi-project admission, global concurrency, durable replay, approvals/CAS, Receipts and operator CLI/MCP | Bundled in public `taskflow-mcp-core`; Unix UDS, Windows pipes non-GA |
|
|
59
|
+
| **WebUI** | Runs, approval edits, Receipts and evidence browsing | Local token login, live authorization and project isolation |
|
|
60
60
|
|
|
61
|
-
The
|
|
61
|
+
The [1.0 release plan](https://github.com/heggria/taskflow/blob/main/docs/internal/1.0.0-release-plan.md) defines the stable scope and acceptance gates. The filesystem-transaction details are in [`docs/internal/0.3.0-trusted-effects-mvp.md`](https://github.com/heggria/taskflow/blob/main/docs/internal/0.3.0-trusted-effects-mvp.md). The 0.3-C Control Plane plan is [`docs/internal/0.3-c-control-plane-plan.md`](https://github.com/heggria/taskflow/blob/main/docs/internal/0.3-c-control-plane-plan.md).
|
|
62
62
|
|
|
63
63
|
## Quickstart
|
|
64
64
|
|
|
65
|
-
|
|
65
|
+
Use Node.js **≥ 22.19.0**. To run from the 1.0 source checkout:
|
|
66
66
|
|
|
67
67
|
```bash
|
|
68
68
|
git clone https://github.com/heggria/taskflow.git
|
|
69
69
|
cd taskflow
|
|
70
|
-
git checkout
|
|
70
|
+
git checkout v1.0.0
|
|
71
71
|
pnpm install
|
|
72
72
|
pnpm run typecheck
|
|
73
73
|
pnpm test
|
|
74
74
|
```
|
|
75
75
|
|
|
76
|
-
|
|
76
|
+
Install the matching 1.0.0 package set after confirming the release is available:
|
|
77
|
+
|
|
77
78
|
```bash
|
|
78
|
-
npm install --global pi-taskflow@
|
|
79
|
-
npm install --global codex-taskflow@
|
|
79
|
+
npm install --global pi-taskflow@1.0.0
|
|
80
|
+
npm install --global codex-taskflow@1.0.0
|
|
80
81
|
```
|
|
81
82
|
|
|
82
|
-
The host-specific plugin and MCP commands remain in the [host guides](https://heggria.github.io/taskflow/en/docs/guides/).
|
|
83
|
+
The host-specific plugin and MCP commands remain in the [host guides](https://heggria.github.io/taskflow/en/docs/guides/).
|
|
83
84
|
|
|
84
85
|
Run the no-LLM Trusted Effects vertical-slice fixture:
|
|
85
86
|
|
|
@@ -88,7 +89,15 @@ pnpm exec node --conditions=development --experimental-strip-types --test \
|
|
|
88
89
|
packages/taskflow-core/test/effects-e2e-fixture.test.ts
|
|
89
90
|
```
|
|
90
91
|
|
|
91
|
-
This exercises the checked-in `examples/trusted-effects-write.json` path without a live LLM. For an interactive run, use the host guide for the adapter you already run. The
|
|
92
|
+
This exercises the checked-in `examples/trusted-effects-write.json` path without a live LLM. For an interactive run, use the host guide for the adapter you already run. The [release guide](https://github.com/heggria/taskflow/blob/main/RELEASE.md) covers packed-consumer validation and release gates.
|
|
93
|
+
|
|
94
|
+
### Local Control Console
|
|
95
|
+
|
|
96
|
+
In Pi, run `/tf web` to start the bundled local Control Console and open the default browser. If browser opening fails, the command shows a manual loopback URL. Use the one-use token in the reported private (0600) handoff file to log in; tokens are never included in the URL or command notifications.
|
|
97
|
+
|
|
98
|
+
The console shows Control Plane runs, approvals, Receipts and existing evidence. Legacy Pi run transcripts are outside this view. Repeating the command in the same project reuses its service; changing projects or leaving the Pi session stops only the console process started by that session. Unix local transport is required. If another host already owns the Control home, stop that owner explicitly before launching this console.
|
|
99
|
+
|
|
100
|
+
See [Pi compatibility](https://github.com/heggria/taskflow/blob/main/docs/pi-compatibility.md) for the tested SDK matrix and the distinction between real-process fixtures and live-provider acceptance.
|
|
92
101
|
|
|
93
102
|
## Declare an effect
|
|
94
103
|
|
|
@@ -191,7 +200,7 @@ Host support is not a blanket security guarantee. Read the [host support baselin
|
|
|
191
200
|
- Writes to undeclared paths remain host-policy dependent under resolve-only execution.
|
|
192
201
|
- `SecretRef` and `ServiceRef` are typed handles only; no vault or live service adapter ships in this cut.
|
|
193
202
|
- There is no FileBroker or full OS sandbox claim in 0.3 MVP.
|
|
194
|
-
- Control Plane
|
|
203
|
+
- Control Plane admission, authorized replay, durable approvals, Receipts, global coordination and WebUI are implemented. Public `taskflow-mcp-core` provides the control binaries; operator actions require an explicitly provisioned separate credential. Request audit fields never grant authority.
|
|
195
204
|
|
|
196
205
|
## Development
|
|
197
206
|
|
|
@@ -210,13 +219,13 @@ The monorepo contains the host-neutral `taskflow-core`, Trusted Effects and reso
|
|
|
210
219
|
|
|
211
220
|
| Start here | Use it for |
|
|
212
221
|
|---|---|
|
|
213
|
-
| [0
|
|
222
|
+
| [1.0 overview](https://heggria.github.io/taskflow/en/docs) | 1.0 scope, support, and the security boundary |
|
|
214
223
|
| [Getting Started](https://heggria.github.io/taskflow/en/docs/getting-started) | First flow and host setup |
|
|
215
224
|
| [Core Concepts](https://heggria.github.io/taskflow/en/docs/concepts/) | DAGs, isolation, verification, resume, and evidence |
|
|
216
225
|
| [Compiler & Runtime](https://heggria.github.io/taskflow/en/docs/compiler-runtime/) | JSON, TypeScript DSL, FlowIR, replay, and recompute |
|
|
217
226
|
| [Host Guides](https://heggria.github.io/taskflow/en/docs/guides/) | Pi, Codex, Claude Code, OpenCode, Grok, and Hermes |
|
|
218
227
|
| [Examples](https://github.com/heggria/taskflow/blob/main/examples) | Runnable flow definitions, including Trusted Effects |
|
|
219
|
-
| [Changelog](https://github.com/heggria/taskflow/blob/main/CHANGELOG.md) | Release history and
|
|
228
|
+
| [Changelog](https://github.com/heggria/taskflow/blob/main/CHANGELOG.md) | Release history and version notes |
|
|
220
229
|
|
|
221
230
|
## License
|
|
222
231
|
|
|
@@ -226,6 +235,6 @@ The monorepo contains the host-neutral `taskflow-core`, Trusted Effects and reso
|
|
|
226
235
|
|
|
227
236
|
**Declare the effect. Verify the path. Commit through one authority.**
|
|
228
237
|
|
|
229
|
-
[Read the docs](https://heggria.github.io/taskflow/en/docs) · [
|
|
238
|
+
[Read the docs](https://heggria.github.io/taskflow/en/docs) · [Install Taskflow 1.0](#quickstart) · [View releases](https://github.com/heggria/taskflow/releases)
|
|
230
239
|
|
|
231
240
|
</div>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hermes-taskflow",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "Run taskflow on Hermes Agent: a Hermes subagent runner plus an MCP server (and a config scaffold) that exposes the taskflow_* tools to Hermes users.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"hermes",
|
|
@@ -50,9 +50,9 @@
|
|
|
50
50
|
"access": "public"
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
|
-
"taskflow-core": "0.
|
|
54
|
-
"taskflow-hosts": "0.
|
|
55
|
-
"taskflow-mcp-core": "0.
|
|
53
|
+
"taskflow-core": "1.0.0",
|
|
54
|
+
"taskflow-hosts": "1.0.0",
|
|
55
|
+
"taskflow-mcp-core": "1.0.0"
|
|
56
56
|
},
|
|
57
57
|
"scripts": {
|
|
58
58
|
"build": "rm -rf dist && tsc -p tsconfig.build.json && node ../../scripts/copy-readme.mjs hermes-taskflow"
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
taskflow:
|
|
16
16
|
command: "npx"
|
|
17
|
-
args: ["-y", "-p", "hermes-taskflow@0.
|
|
17
|
+
args: ["-y", "-p", "hermes-taskflow@1.0.0", "hermes-taskflow-mcp"]
|
|
18
18
|
env:
|
|
19
19
|
# Uncomment for mutating agent phases (terminal / file write).
|
|
20
20
|
# Leave unset for verify/plan/script-only flows.
|
|
@@ -147,9 +147,9 @@ For a non-trivial flow you'll iterate on, **write the definition to a file**
|
|
|
147
147
|
(typically in the OS tmp dir) and point every call at it with `defineFile`:
|
|
148
148
|
|
|
149
149
|
```jsonc
|
|
150
|
-
// 1. write /tmp/audit.json with the `write` tool (a full {name, phases:[
|
|
150
|
+
// 1. write /tmp/audit.json with the `write` tool (a full {name, phases:[...]} object)
|
|
151
151
|
// 2. verify, iterate, run — all reference the SAME file by path:
|
|
152
|
-
{ "name": "taskflow_plan", "arguments": { "defineFile": "/tmp/audit.json", "args": {
|
|
152
|
+
{ "name": "taskflow_plan", "arguments": { "defineFile": "/tmp/audit.json", "args": { ... } } } // zero tokens: bind + plan + budget bound
|
|
153
153
|
{ "name": "taskflow_verify", "arguments": { "defineFile": "/tmp/audit.json" } } // zero tokens
|
|
154
154
|
{ "name": "taskflow_compile", "arguments": { "defineFile": "/tmp/audit.json" } } // diagram
|
|
155
155
|
{ "name": "taskflow_lint", "arguments": { "defineFile": "/tmp/audit.json" } } // script-lint + custom verifiers
|
|
@@ -163,6 +163,24 @@ large definition on every call and keeps a durable draft you can diff. Falls
|
|
|
163
163
|
back cleanly: precedence is `define` (inline) > `defineFile` (disk) > `name`
|
|
164
164
|
(saved flow).
|
|
165
165
|
|
|
166
|
+
### Long instructions: `taskFile` (load-time include, not `context`)
|
|
167
|
+
|
|
168
|
+
A phase or parallel branch may set `taskFile` **instead of** `task`. Trusted
|
|
169
|
+
loaders (`defineFile` / saved flow) resolve the **literal** path against the
|
|
170
|
+
definition directory — same class of source as `scriptCwd: "flow"` — inline the
|
|
171
|
+
UTF-8 body into `task`, and **delete** `taskFile` before validate / interpolate
|
|
172
|
+
/ cache / FlowIR. Runtime never sees `taskFile`.
|
|
173
|
+
|
|
174
|
+
- XOR with `task`. Path is a static import: **not interpolated**, no `..`, no
|
|
175
|
+
symlink leaf, must stay physically inside the flow directory. Cap 256 KiB.
|
|
176
|
+
- Inline leftover → `TF_TASKFILE_NO_PROVENANCE`. Generated sub-flows →
|
|
177
|
+
`TF_DYNAMIC_RESOURCE_FORBIDDEN`.
|
|
178
|
+
- Do **not** put durable instructions in `context`. `context` is cwd-relative,
|
|
179
|
+
default-truncated at 8k, wrapped as `## File:`, marked unreplayable, and
|
|
180
|
+
forbidden in dynamic sub-flows.
|
|
181
|
+
- TS DSL: `agent({ taskFile: "prompts/x.md" })`. `taskflow-dsl check` / erase
|
|
182
|
+
emit the field and do **not** read the file.
|
|
183
|
+
|
|
166
184
|
### DSL shape
|
|
167
185
|
|
|
168
186
|
```jsonc
|
|
@@ -554,7 +572,7 @@ Each effect:
|
|
|
554
572
|
**Phase output is the payload.** With one declared `fs.write`, the phase's
|
|
555
573
|
output becomes the staged file content (see the example: `process.stdout.write`
|
|
556
574
|
= the report). With several `fs.write` effects, the phase must emit JSON
|
|
557
|
-
mapping each effect id to its content (`{ "report": "
|
|
575
|
+
mapping each effect id to its content (`{ "report": "...", "backup": "..." }`).
|
|
558
576
|
Commit promotes each file atomically; a later failure restores every admitted
|
|
559
577
|
file to its durable pre-state, and a direct write by the agent/script to a
|
|
560
578
|
**declared final path** is detected and restored — only the resource
|
|
@@ -606,8 +624,8 @@ more than comparing every approach.
|
|
|
606
624
|
{
|
|
607
625
|
"id": "quick", "type": "race",
|
|
608
626
|
"branches": [
|
|
609
|
-
{ "task": "Answer with a short heuristic
|
|
610
|
-
{ "task": "Answer with a thorough search
|
|
627
|
+
{ "task": "Answer with a short heuristic...", "agent": "executor" },
|
|
628
|
+
{ "task": "Answer with a thorough search...", "agent": "researcher" }
|
|
611
629
|
],
|
|
612
630
|
"final": true
|
|
613
631
|
}
|
|
@@ -47,9 +47,9 @@ Top-level keys of the taskflow definition object.
|
|
|
47
47
|
| `concurrency` | number | `8` | Default fan-out / same-layer parallelism cap. See §4. |
|
|
48
48
|
| `idleTimeout` | number | host default (`300000`) | Flow-level idle watchdog in ms (≥ 1000, or `0` to disable) for all agent-running phases that don't set their own. `0` disables the watchdog but then **every** agent-running phase MUST declare a finite wall `timeout` (≥ 1000) so the flow can never hang. A per-phase `idleTimeout` overrides this. |
|
|
49
49
|
| `agentScope` | `user`\|`project`\|`both` | `user` | Which agent dirs to load. See §6. |
|
|
50
|
-
| `scriptCwd` | `invocation`\|`flow` | `invocation` | Default cwd policy for `script` phases. `flow` requires trusted saved-flow/`defineFile` provenance; explicit phase `cwd` wins, and inherited cwd-bridge boundaries still constrain the resolved source directory. |
|
|
50
|
+
| `scriptCwd` | `invocation`\|`flow` | `invocation` | Default cwd policy for `script` phases. `flow` requires trusted saved-flow/`defineFile` provenance; explicit phase `cwd` wins, and inherited cwd-bridge boundaries still constrain the resolved source directory. `taskFile` is the same class of load-time trusted source (see §2). |
|
|
51
51
|
| `args` | record | `{}` | Declared invocation arguments. See §3. |
|
|
52
|
-
| `hooks` | object | — | **0.2.7.** Terminal fire-and-forget notifications: `onComplete` / `onFail` / `onBlocked` arrays of `{type:"webhook"\|"file"\|"command",
|
|
52
|
+
| `hooks` | object | — | **0.2.7.** Terminal fire-and-forget notifications: `onComplete` / `onFail` / `onBlocked` arrays of `{type:"webhook"\|"file"\|"command", ...}`. Payload is summary-only (`taskflow.hook.v1`) — never transcripts. Hook failure never changes run status. `https` or `http://127.0.0.1\|localhost` for webhooks; `command.run` is argv-only (no shell string). |
|
|
53
53
|
| `phases` | array | — | **Required.** The phase DAG. See §2. |
|
|
54
54
|
| `version` | number | `1` | Informational metadata in 0.2.x; it does not select runtime semantics or migrate a flow. |
|
|
55
55
|
|
|
@@ -66,11 +66,11 @@ Keys of each object in `phases[]`. Some only apply to specific `type`s.
|
|
|
66
66
|
"id": "audit", // required, unique — referenced via {steps.audit.output}
|
|
67
67
|
"type": "map", // agent | parallel | map | gate | reduce | approval | flow | loop | tournament | script | race | expand (default: agent)
|
|
68
68
|
"agent": "analyst", // agent name to run this phase
|
|
69
|
-
"task": "Audit {item.route}
|
|
69
|
+
"task": "Audit {item.route}...",
|
|
70
70
|
"dependsOn": ["discover"],// DAG edges
|
|
71
71
|
"over": "{steps.discover.json}", // [map] array to fan out over
|
|
72
72
|
"as": "item", // [map] loop var name (default: item)
|
|
73
|
-
"branches": [ /*
|
|
73
|
+
"branches": [ /* ... */ ], // [parallel|race] static task list
|
|
74
74
|
"from": ["audit"], // [reduce] phase ids to aggregate
|
|
75
75
|
"def": "{steps.plan.json}", // [expand|flow] inline fragment / dynamic sub-flow
|
|
76
76
|
"expandMode": "nested", // [expand] nested | graft
|
|
@@ -86,13 +86,14 @@ Keys of each object in `phases[]`. Some only apply to specific `type`s.
|
|
|
86
86
|
|
|
87
87
|
| Key | Applies to | Default | Notes |
|
|
88
88
|
|-----|-----------|---------|-------|
|
|
89
|
-
| `id` | all | — | **Required, unique.** Used in `{steps.<id
|
|
89
|
+
| `id` | all | — | **Required, unique.** Used in `{steps.<id>...}`. |
|
|
90
90
|
| `type` | all | `agent` | One of the **12** phase types (agent, parallel, map, gate, reduce, approval, flow, loop, tournament, script, **race**, **expand**). |
|
|
91
91
|
| `agent` | all | first available | Agent name; resolved from the scoped pool. |
|
|
92
|
-
| `task` | agent, gate, map, reduce | — | Prompt; supports interpolation. Required for these types. |
|
|
92
|
+
| `task` | agent, gate, map, reduce | — | Prompt; supports interpolation. Required for these types unless `taskFile` is set. |
|
|
93
|
+
| `taskFile` | agent, gate, map, reduce, parallel/race branch | — | Load-time include. Literal path relative to the flow definition directory. Trusted loaders inline UTF-8 into `task` and delete the field. XOR with `task`. Path is **not** interpolated. Cap 256 KiB. Not `context`. |
|
|
93
94
|
| `over` | map | — | **Required for map.** Must resolve to an array. |
|
|
94
95
|
| `as` | map | `item` | Loop variable bound per item. |
|
|
95
|
-
| `branches` | parallel, race | — | **Required** (≥1 for parallel; ≥2 for race). `[{task, agent?}]`. |
|
|
96
|
+
| `branches` | parallel, race | — | **Required** (≥1 for parallel; ≥2 for race). `[{task, agent?}]` or `{taskFile, agent?}`. |
|
|
96
97
|
| `cancelLosers` | race | `true` | Abort in-flight losers after first **success** (best-effort AbortSignal). |
|
|
97
98
|
| `from` | reduce | — | **Required for reduce.** Phase ids whose outputs are aggregated. `{previous.output}` resolves to **all completed `from[]` outputs** in from-array order (one → raw; many → `### <id>\n\n<output>` sections joined by `\n\n---\n\n`). |
|
|
98
99
|
| `reduceStrategy` | reduce | `one-shot` | `one-shot` = a single reducer call over all aggregated inputs. `tree` = batched intermediate reducer rounds (see `batchSize`); useful when aggregated input would exceed one prompt. `tree` forces the imperative runtime (event kernel falls back). |
|
|
@@ -267,8 +268,8 @@ There are **two independent concurrency limits**:
|
|
|
267
268
|
"concurrency": 6, // ≤6 sibling phases run at once
|
|
268
269
|
"phases": [
|
|
269
270
|
{ "id": "scan", "type": "map", "over": "{steps.list.json}",
|
|
270
|
-
"concurrency": 3, //
|
|
271
|
-
"task": "
|
|
271
|
+
"concurrency": 3, // ...but this map only fans out 3 at a time
|
|
272
|
+
"task": "...", "dependsOn": ["list"] }
|
|
272
273
|
]
|
|
273
274
|
}
|
|
274
275
|
```
|
|
@@ -434,7 +435,7 @@ fingerprint folds **“did the world change?”** signals into that key, so an
|
|
|
434
435
|
external change becomes a cache **miss** even when the task text is identical.
|
|
435
436
|
Each entry is one of:
|
|
436
437
|
|
|
437
|
-
| Entry | Becomes a miss when
|
|
438
|
+
| Entry | Becomes a miss when... | Resolves to |
|
|
438
439
|
|-------|----------------------|-------------|
|
|
439
440
|
| `git:HEAD` / `git:<ref>` | the commit moves | the resolved SHA (30s timeout → `<timeout>`; no git → `<no-git>`) |
|
|
440
441
|
| `glob:<pattern>` | the **set of matching paths** or their metadata changes | sorted path list with size + mtime (content-hashed globs use `glob!:` instead, which is mtime-independent) |
|
|
@@ -496,7 +497,7 @@ Each entry is one of:
|
|
|
496
497
|
```jsonc
|
|
497
498
|
{ "id": "review", "type": "gate", "agent": "reviewer",
|
|
498
499
|
"model": "claude-opus-4", "thinking": "high",
|
|
499
|
-
"task": "
|
|
500
|
+
"task": "...\nVERDICT:", "dependsOn": ["audit"] }
|
|
500
501
|
```
|
|
501
502
|
|
|
502
503
|
**Sandbox a phase to read-only in a subdirectory:**
|
|
@@ -515,7 +516,7 @@ Each entry is one of:
|
|
|
515
516
|
|
|
516
517
|
**Project-only agents:**
|
|
517
518
|
```jsonc
|
|
518
|
-
{ "name": "ci-audit", "agentScope": "project", "phases": [ /*
|
|
519
|
+
{ "name": "ci-audit", "agentScope": "project", "phases": [ /* ... */ ] }
|
|
519
520
|
```
|
|
520
521
|
|
|
521
522
|
---
|
|
@@ -554,22 +555,22 @@ symlinks, and commit atomically; `--emit both` preflights both destinations.
|
|
|
554
555
|
|
|
555
556
|
**Authoring notes (kinds ↔ runes)**
|
|
556
557
|
|
|
557
|
-
Import: `import { flow, agent, map,
|
|
558
|
+
Import: `import { flow, agent, map, ... } from "taskflow-dsl"`. Runes erase to Taskflow
|
|
558
559
|
JSON kinds (single source: `PHASE_TYPES` in core + `erase/kinds/*` registry).
|
|
559
560
|
|
|
560
561
|
| JSON `type` | DSL rune(s) | Notes |
|
|
561
562
|
|-------------|-------------|--------|
|
|
562
563
|
| `agent` | `agent(task, opts?)` | templates → `{steps.*}` / `{item.*}` |
|
|
563
|
-
| `parallel` | `parallel([agent
|
|
564
|
-
| `map` | `map(source, item => agent
|
|
564
|
+
| `parallel` | `parallel([agent...])` | waits for all branches |
|
|
565
|
+
| `map` | `map(source, item => agent...)` | `over` + `as` |
|
|
565
566
|
| `gate` | `gate(up, opts?, task?)` · `gate.automated` · `gate.scored` | sugar → `eval` / `score` |
|
|
566
|
-
| `reduce` | `reduce([
|
|
567
|
+
| `reduce` | `reduce([...], () => agent...)` | `from` |
|
|
567
568
|
| `approval` | `approval({ request })` | |
|
|
568
569
|
| `flow` | `subflow("name")` · `subflow.def(plan)` | use vs def |
|
|
569
|
-
| `loop` | `loop({ task, until?,
|
|
570
|
-
| `tournament` | `tournament({ branches/variants, judge,
|
|
570
|
+
| `loop` | `loop({ task, until?, ... })` | |
|
|
571
|
+
| `tournament` | `tournament({ branches/variants, judge, ... })` | |
|
|
571
572
|
| `script` | `script(run, opts?)` | string or argv array |
|
|
572
|
-
| `race` | `race([agent
|
|
573
|
+
| `race` | `race([agent...], { cancelLosers? })` | first **success** wins; cooperative loser usage is counted |
|
|
573
574
|
| `expand` | `expand` / `expand.nested` / `expand.graft` | `def` + `expandMode` |
|
|
574
575
|
|
|
575
576
|
- `const [a,b] = parallel([agent(...), agent(...)])` desugars to **two real agent phases** (`a`, `b`) that run concurrently (no `dependsOn` between them). Prefer this when you need `{steps.a.output}`.
|