hermes-taskflow 0.2.9 → 0.3.0-beta.1

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
@@ -1,438 +1,222 @@
1
1
  <div align="center">
2
2
 
3
- <img src="https://raw.githubusercontent.com/heggria/taskflow/main/assets/hero.png" alt="taskflow: compile, verify, and run multi-agent DAGs across six coding-agent hosts" width="100%">
3
+ <img src="https://raw.githubusercontent.com/heggria/taskflow/main/assets/hero.png" alt="taskflow 0.3: trusted effects for coding-agent workflows" width="100%">
4
4
 
5
5
  <br />
6
6
 
7
- [![npm](https://img.shields.io/npm/v/pi-taskflow?style=flat-square&color=7775FF&label=npm)](https://www.npmjs.com/package/pi-taskflow)
8
7
  [![CI](https://img.shields.io/github/actions/workflow/status/heggria/taskflow/ci.yml?branch=main&style=flat-square&label=CI)](https://github.com/heggria/taskflow/actions/workflows/ci.yml)
9
8
  [![Node](https://img.shields.io/badge/node-%E2%89%A522.19-35C99A?style=flat-square)](https://nodejs.org)
10
9
  [![License](https://img.shields.io/badge/license-MIT-35C99A?style=flat-square)](https://github.com/heggria/taskflow/blob/main/LICENSE)
11
- [![Hosts](https://img.shields.io/badge/hosts-6-7775FF?style=flat-square)](#install-on-your-host)
12
- [![Tests](https://img.shields.io/badge/tests-1%2C500%2B-7775FF?style=flat-square)](#built-to-survive-real-work)
10
+ [![Hosts](https://img.shields.io/badge/hosts-6-7775FF?style=flat-square)](#host-adapters)
13
11
 
14
12
  **English** · [简体中文](https://github.com/heggria/taskflow/blob/main/README.zh-CN.md)
15
13
 
16
- [Install](#install-on-your-host) · [Quickstart](#60-second-start) · [What's new in 0.2.9](#029-hermes-agent--verify-parity) · [0.2 compiler turn](#02-is-the-compiler-turn) · [Docs](https://heggria.github.io/taskflow/en/docs) · [Examples](https://github.com/heggria/taskflow/blob/main/examples)
14
+ [0.3 overview](#taskflow-03-trusted-effects) · [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)
17
15
 
18
16
  </div>
19
17
 
20
18
  ---
21
19
 
22
- # Build multi-agent systems you can inspect before they run.
20
+ # taskflow 0.3: make agent side effects inspectable
23
21
 
24
- **taskflow turns agent plans into compiled task graphs**: declared once, verified before model spend, executed in isolated subagents, resumed across sessions, replayed without tokens, and recomputed from the smallest stale frontier.
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 the 0.3 candidate, the contract also describes the effects a phase is allowed to propose.
25
23
 
26
- It runs on the coding agent you already use:
24
+ > **Status: 0.3.0-beta.1 Trusted Effects beta — beta channel, not GA.** This release candidate is prepared for npm's `beta` channel; the beta ships the Trusted Effects MVP described below. The 0.3-C Control Plane remains a follow-on candidate track; it is not a shipped beta surface.
27
25
 
28
- **Pi · Codex · Claude Code · OpenCode · Grok Build · Hermes Agent**
26
+ ## The 0.3 idea
27
+
28
+ An agent can propose content. It should not become the mutation authority merely because it can run a command.
29
+
30
+ For admitted, declared filesystem-write targets, taskflow 0.3 makes the path explicit and routes the final mutation through the resources transaction:
29
31
 
30
32
  ```text
31
- JSON or .tf.ts
32
- │
33
- ▼
34
- validate ──► Taskflow JSON ──► FlowIR + content hash
33
+ flow / .tf.ts
34
+ │
35
+ ▼
36
+ validate + verify ──► EffectIR + FlowIR hash
37
+ │ │
38
+ │ ▼
39
+ │ admit declared targets
40
+ │ │
41
+ ▼ ▼
42
+ isolated phase ───────► stage → commit | restore + reject
35
43
  │
36
44
  ▼
37
- isolated DAG runtime
38
- │
39
- ┌────────────┼────────────┐
40
- ▼ ▼ ▼
41
- resume replay recompute
45
+ ledger-backed why-effect
42
46
  ```
43
47
 
44
- > Your host receives the final result. Intermediate transcripts stay inside the runtime unless you explicitly inspect them.
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.
45
49
 
46
- ## Why taskflow?
50
+ ## What is in the candidate
47
51
 
48
- Built-in subagent tools are excellent for one turn. The moment the work branches, retries, crosses sessions, or needs a quality gate, the plan becomes infrastructure.
49
-
50
- | | Ad-hoc agents / scripts | **taskflow** |
52
+ | Layer | What it does | Candidate status |
51
53
  |---|---|---|
52
- | **Plan** | Re-derived from prose or hidden in a script | **An explicit, versionable DAG** |
53
- | **Before execution** | Discover mistakes while spending | **Verify structure at zero model calls** |
54
- | **Intermediate output** | Floods the host context | **Stays isolated in the runtime** |
55
- | **Failure** | Start over or reconstruct state | **Resume from persisted phase state** |
56
- | **Changed input** | Re-run broadly | **Explain staleness and re-run the affected frontier** |
57
- | **Portability** | Coupled to one agent | **One JSON contract across six hosts** |
54
+ | **Taskflow runtime** | Declarative DAGs, 12 phase types, budgets, retries, approvals, isolation, resume, replay, trace, and recompute | Existing 0.2 foundation |
55
+ | **Trusted Effects** | Closed `EffectIR`, `PathRef` / `SecretRef` / `ServiceRef`, confidentiality/integrity labels, effect validation, overlap checks, and ledger-backed `why-*` explainers | 0.3 MVP implementation |
56
+ | **Resource transaction** | Snapshot → lease → durable intent/permit → stage → commit, or restore and reject | 0.3 MVP implementation |
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** | ControlHost scaffold, proposed wire contracts, singleton/fencing, and hello negotiation; future stores, approvals, receipts, and coordination | Active 0.3-C track; not shipped and not the 0.3 MVP GA claim |
59
+ | **WebUI** | Runs, approvals, receipts, and evidence browsing | Planned in the 0.3-C sequence; not shipped in this candidate |
58
60
 
59
- The trade is deliberate: less arbitrary orchestration code, more **verifiability, observability, recovery, and reuse**.
61
+ The normative MVP definition is [`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).
60
62
 
61
- ## 60-second start
63
+ ## Quickstart
62
64
 
63
- Install taskflow on [Pi](https://pi.dev):
65
+ The 0.3 beta can be installed from npm, or exercised from a clean source checkout. Use Node.js **≥ 22.19.0**:
64
66
 
65
67
  ```bash
66
- pi install npm:pi-taskflow
68
+ git clone https://github.com/heggria/taskflow.git
69
+ cd taskflow
70
+ git checkout rc/0.3.0-trusted-effects
71
+ pnpm install
72
+ pnpm run typecheck
73
+ pnpm test
67
74
  ```
68
75
 
69
- Then ask naturally:
76
+ The beta commands below become usable after the tag workflow completes; until then they are release-target examples, not proof of registry availability.
77
+ ```bash
78
+ npm install --global pi-taskflow@beta
79
+ npm install --global codex-taskflow@beta
80
+ ```
70
81
 
71
- > Use taskflow to audit `src/api` in parallel and return one prioritized report.
82
+ The host-specific plugin and MCP commands remain in the [host guides](https://heggria.github.io/taskflow/en/docs/guides/). Stable 0.2.x installs remain available through exact stable pins.
72
83
 
73
- The routing skill uses the same familiar `task` / `tasks` / `chain` shape:
84
+ Run the no-LLM Trusted Effects vertical-slice fixture:
74
85
 
75
- ```json
76
- {
77
- "chain": [
78
- { "agent": "scout", "task": "Map the public API under src/api." },
79
- {
80
- "agent": "security-reviewer",
81
- "task": "Audit this surface for missing auth and unsafe input boundaries:\n{previous.output}"
82
- },
83
- {
84
- "agent": "reviewer",
85
- "task": "Turn these findings into one prioritized report:\n{previous.output}"
86
- }
87
- ]
88
- }
86
+ ```bash
87
+ pnpm exec node --conditions=development --experimental-strip-types --test \
88
+ packages/taskflow-core/test/effects-e2e-fixture.test.ts
89
89
  ```
90
90
 
91
- That already gives you an isolated, tracked run. When the job needs real topology, declare the graph:
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 stable 0.2 installation path remains documented separately in the [host guides](https://heggria.github.io/taskflow/en/docs/guides/).
92
+
93
+ ## Declare an effect
94
+
95
+ Effects are part of the flow contract, not a free-form prompt promise:
92
96
 
93
97
  ```json
94
98
  {
95
- "name": "audit-api",
96
- "args": { "dir": { "default": "src/api" } },
97
- "concurrency": 4,
99
+ "name": "trusted-effects-write",
98
100
  "phases": [
99
101
  {
100
- "id": "discover",
101
- "type": "agent",
102
- "agent": "scout",
103
- "task": "List source files under {args.dir}. Output ONLY a JSON array of {\"path\":\"...\"} objects.",
104
- "output": "json"
105
- },
106
- {
107
- "id": "audit-each",
108
- "type": "map",
109
- "over": "{steps.discover.json}",
110
- "as": "file",
111
- "agent": "security-reviewer",
112
- "task": "Audit {file.path}. Cite evidence and assign severity.",
113
- "dependsOn": ["discover"]
114
- },
115
- {
116
- "id": "report",
117
- "type": "reduce",
118
- "from": ["audit-each"],
119
- "agent": "reviewer",
120
- "task": "Synthesize one prioritized report:\n{steps.audit-each.output}",
121
- "dependsOn": ["audit-each"],
102
+ "id": "write-report",
103
+ "type": "script",
104
+ "run": ["node", "scripts/render-report.mjs"],
105
+ "effects": [
106
+ {
107
+ "id": "report",
108
+ "kind": "fs.write",
109
+ "purpose": "write final report",
110
+ "target": {
111
+ "kind": "path",
112
+ "path": {
113
+ "workspace": "project",
114
+ "subpath": { "literalPath": "out/report.md" },
115
+ "intent": "create-file"
116
+ }
117
+ },
118
+ "confidentiality": "internal",
119
+ "integrity": "project"
120
+ }
121
+ ],
122
122
  "final": true
123
123
  }
124
124
  ]
125
125
  }
126
126
  ```
127
127
 
128
- Save it as `.pi/taskflows/audit-api.json`, then run:
129
-
130
- ```text
131
- /tf:audit-api dir=src/api
132
- ```
133
-
134
- On Codex, Claude Code, OpenCode, Grok Build, and Hermes Agent, 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.
128
+ The declaration is not authorization by itself. The runtime resolves the `PathRef`, checks labels and overlaps, records the resource intent, and only then permits the transaction to stage and finalize the declared target. `taskflow_why_effect` explains the resulting authorization and ledger state without model calls.
135
129
 
136
- [Follow the full quickstart →](https://heggria.github.io/taskflow/en/docs/getting-started)
130
+ ## The runtime contract
137
131
 
138
- ## See the graph run
139
-
140
- This is real output from a Pi run—not a mock dashboard:
132
+ The 0.2 runtime remains the foundation. A flow can be authored as portable JSON or compiled from TypeScript DSL to FlowIR:
141
133
 
142
134
  ```text
143
- ⊗ taskflow self-improve 6/7 · blocked · $0.095
144
- ✓ discover agent deepseek-v4-flash 10t ↑38k ↓6.7k $0.011
145
- ┌ ✓ write-runner-tests agent claude-sonnet-4-6 10t ↑13 ↓6.6k $0.020
146
- ├ ✓ write-store-tests agent claude-sonnet-4-6 10t ↑11 ↓10k $0.018
147
- ├ ✓ write-agents-tests agent claude-sonnet-4-6 10t ↑28 ↓13k $0.030
148
- └ ✓ fix-stability agent claude-sonnet-4-6 10t ↑13 ↓3.9k $0.012
149
- ✓ verify gate BLOCK 3 type errors in test files
150
- ⊘ report reduce skipped · Gate blocked ↳ fix-stability
151
- ```
152
-
153
- The layout **is** the DAG. Parallel rails expose concurrency; long edges expose dependencies; the gate explains why downstream work stopped. No separate control plane is required to understand the run.
154
-
155
- ## 0.2.9: Hermes Agent + verify parity
156
-
157
- Taskflow now ships on **Hermes Agent** as `hermes-taskflow`, bringing the same MCP control plane to a sixth host. Hermes children run with an ephemeral home, explicit toolsets, cwd-confined local reads, provider-only credential material, and an explicit opt-in for mutating `--yolo` phases.
158
-
159
- Pi's advertised `/tf verify <name>` command now matches the tool surface, including saved flow names containing spaces. Project discovery also stops at canonical home/temp boundaries, so ambient `/tmp/.pi` state cannot become a project by accident. [Full 0.2.9 notes →](https://github.com/heggria/taskflow/blob/main/CHANGELOG.md#029--2026-08-11)
160
-
161
- ## 0.2.8: review, then confirm
162
-
163
- Pi approvals now separate **selection** from **commit**. Choose Reject, Edit guidance, or Approve with `R` / `E` / `A`, arrows, or Tab; press Enter to confirm. The safe default is Reject, and Escape or Ctrl-C still rejects immediately.
164
-
165
- Long proposals start collapsed. Press `V` to open an inline scrollable preview while the decision footer stays visible; short proposals remain open by default. Full notes: [CHANGELOG 0.2.8](https://github.com/heggria/taskflow/blob/main/CHANGELOG.md#028--2026-08-10).
166
-
167
- ## 0.2.7: plan before spend · close the loop
168
-
169
- The 0.2 line made graphs **compiled and inspectable**. **0.2.7** makes the day-to-day loop feel finished: you can see the plan *before* any model call, and you can hear about the run *after* it finishes — without stuffing transcripts into the host.
170
-
171
- | Before spend | After spend |
172
- |---|---|
173
- | **`taskflow_plan` / `/tf plan`** — bind typed args, project phase order, mark dynamic refs, worst-case agent-call bound | **`hooks.onComplete` / `onFail` / `onBlocked`** — webhook, file, or argv-only command; summary payload only (`taskflow.hook.v1`) |
174
- | **`verify` / `lint`** still free | **`approval.timeoutMs` + `onExpire`** — HITL no longer waits forever |
175
- | **`recompute` savings line** — `reused N · rerun M · cutoff K · saved ~P%` | **`taskflow_analytics`** — last-N status, duration, fail/cache rates (read-only) |
176
-
177
- ```bash
178
- # Zero tokens: see what would run and how expensive the worst case looks
179
- # MCP: taskflow_plan · Pi: /tf plan my-flow '{"dir":"src"}'
180
- ```
181
-
182
- ```jsonc
183
- // Optional: fire-and-forget when a background run finishes
184
- {
185
- "hooks": {
186
- "onComplete": [{ "type": "file", "path": ".taskflow/hooks/last-complete.json" }]
187
- }
188
- }
189
- ```
190
-
191
- MCP hosts now expose **19 tools** (added `taskflow_plan` and `taskflow_analytics`). Starter templates: [`examples/templates/`](https://github.com/heggria/taskflow/blob/main/examples/templates/). Full notes: [CHANGELOG 0.2.7](https://github.com/heggria/taskflow/blob/main/CHANGELOG.md#027--2026-08-06).
192
-
193
- ## 0.2 is the compiler turn
194
-
195
- Before 0.2, taskflow executed declarative graphs. Now the graph also has a compile-time frontend, a canonical intermediate representation, an append-only decision trace, offline replay, and incremental recompute.
196
-
197
- ### Author in JSON or TypeScript
198
-
199
- JSON remains the portable runtime contract. For larger flows, `taskflow-dsl` adds a compile-time TypeScript authoring layer:
200
-
201
- ```ts
202
- import { agent, flow, json, map, reduce } from "taskflow-dsl";
203
-
204
- export default flow("audit", (ctx) => {
205
- ctx.budget({ maxUSD: 2 });
206
-
207
- const files = agent("List files under {args.dir}", {
208
- agent: "scout",
209
- output: json<{ path: string }[]>(),
210
- });
211
-
212
- const audits = map(files, (file) =>
213
- agent(`Audit ${file.path}`, { agent: "security-reviewer" }),
214
- );
215
-
216
- return reduce(
217
- [audits],
218
- (parts) => agent(`Write one report:\n${parts.audits.output}`),
219
- { final: true },
220
- );
221
- });
222
- ```
223
-
224
- ```bash
225
- pnpm add -D taskflow-dsl
226
- taskflow-dsl check audit.tf.ts
227
- taskflow-dsl build audit.tf.ts --emit both
228
- # → audit.taskflow.json + audit.flowir.json
135
+ JSON / .tf.ts
136
+ │
137
+ ▼
138
+ validate → Taskflow JSON → FlowIR + content hash
139
+ │
140
+ ▼
141
+ isolated DAG runtime
142
+ │
143
+ resume · replay · recompute · trace
144
+ │
145
+ ▼
146
+ finalOutput to the host
229
147
  ```
230
148
 
231
- `.tf.ts` is **compile-time only**. Hosts execute the emitted Taskflow JSON; they never interpret TypeScript.
232
-
233
- ### Compile to a contract you can reason about
234
-
235
- FlowIR canonicalizes the graph and gives it a content hash. That compiled identity makes provenance and stale analysis inspectable, while the runtime adds content-addressed caching and deterministic tools:
236
-
237
- | Operation | What it answers | Model calls |
238
- |---|---|---:|
239
- | **`plan`** | What will run, which args bind, worst-case agent calls? | **0** |
240
- | `verify` / `compile` / `lint` | Is the graph structurally safe / lint-clean? | **0** |
241
- | `ir` | What is the canonical graph and content hash? | **0** |
242
- | `resume` | What unfinished work remains? (forks a new run; original untouched) | Only unfinished phases |
243
- | `trace` | What calls and runtime decisions actually happened? | **0** to inspect |
244
- | `replay` | What if thresholds or budgets had been different? | **0** |
245
- | `why-stale` | What changed, and what depends on it? | **0** |
246
- | `recompute` | What is the smallest observable affected frontier? (+ savings line) | Only affected phases |
247
- | `analytics` | How have recent runs of this flow behaved? | **0** |
248
-
249
- [Explore the compiler and runtime →](https://heggria.github.io/taskflow/en/docs/compiler-runtime/)
250
-
251
149
  ## One runtime, 12 phase types
252
150
 
253
151
  | Family | Phases | Use them for |
254
152
  |---|---|---|
255
- | **Work** | `agent` · `parallel` · `map` · `reduce` · `script` | Single tasks, static fan-out, dynamic fan-out, aggregation, zero-token shell steps |
256
- | **Control** | `gate` · `approval` · `flow` · `loop` | Quality decisions, human checkpoints, composition, iterative refinement |
153
+ | **Work** | `agent` · `parallel` · `map` · `reduce` · `script` | Single tasks, static concurrency, dynamic fan-out, aggregation, and zero-token shell steps |
154
+ | **Control** | `gate` · `approval` · `flow` · `loop` | Quality decisions, human checkpoints, composition, and iterative refinement |
257
155
  | **Selection** | `tournament` · `race` | Best-of-N quality or first-success latency |
258
- | **Dynamic graph** | `expand` | Validate and execute a runtime-produced fragment, nested or grafted |
259
-
260
- Across those phase types, the DSL provides dependencies, conditions, retries, timeouts, output contracts, budgets, workspace isolation, and explicit final-output selection. Each kind accepts only the fields that are safe and meaningful for it; freshness-sensitive phases are excluded from cross-run caching.
261
-
262
- [Read the phase reference →](https://heggria.github.io/taskflow/en/docs/syntax/phase-types)
156
+ | **Dynamic graph** | `expand` | Validate and execute a runtime-produced nested or grafted fragment |
263
157
 
264
- ## Runtime guarantees, not prompt conventions
158
+ Across those phase types, the runtime provides shared behavior: dependencies, conditions, retries, timeouts, output contracts, budgets, workspace isolation, explicit final-output selection, and persistence for resume. Each phase kind accepts only the fields that are safe and meaningful for it.
265
159
 
266
- ### Verify before spend
160
+ Useful zero-token operations include:
267
161
 
268
- Cycles, dangling dependencies, invalid references, impossible joins, unsafe dynamic fragments, and configuration hazards are rejected or surfaced before the expensive work starts.
269
-
270
- ### Keep intermediate work out of the host context
271
-
272
- Agent-running phases execute in isolated subagent processes; control and script phases stay inside the runtime. Upstream outputs are wired into downstream inputs internally. Only `finalOutput` returns to the host unless you explicitly use `peek` or `trace`.
273
-
274
- ### Survive sessions and failures
275
-
276
- Phase state is persisted atomically. Resume skips unchanged completed work; detached Pi runs can outlive the initiating session; an idle watchdog terminates stalled subagents.
277
-
278
- ### Reuse work honestly
279
-
280
- Within-run resume is content-addressed. Cross-run caching is opt-in and can fingerprint Git commits, files, globs, environment variables, and TTLs. Change one declared input and only its dependents become stale.
281
-
282
- ### Bound the blast radius
283
-
284
- Budgets, concurrency caps, retries, timeouts, nesting limits, dynamic-graph breadth caps, path containment, non-idempotent phase classification, and fail-closed approval behavior are runtime semantics—not suggestions in a prompt.
285
-
286
- ### 0.2.1: safe dynamic cwd and Pi terminal reaping
287
-
288
- An invocation argument declared as `type: "relative-path"` may select a phase
289
- working directory with the exact form `cwd: "{args.package}"`. The bridge is
290
- default-off, requires host `resolve-only` authorization, and confines the
291
- canonical directory to the invocation root. Absolute paths, concatenation, and
292
- `{steps.*}` remain rejected; this compatibility bridge is not an OS sandbox.
293
- Resolve-only writer phases within one invocation are serialized before durable
294
- lease acquisition, so fan-out cannot self-timeout while separate processes
295
- remain protected by cross-process leases.
296
-
297
- Pi child agents no longer inherit ambient extensions by default. Trusted host
298
- settings can use an explicit extension allowlist or opt back into legacy
299
- inheritance. If a Pi child produces a validated final answer and terminal event
300
- but an extension keeps the process alive, Taskflow waits a bounded grace window,
301
- reaps the process group, and records `completionSource: "terminal-reap"` instead
302
- of reporting a false timeout.
303
-
304
- ```json
305
- {
306
- "taskflow": {
307
- "piChild": {
308
- "resourceProfile": "isolated",
309
- "extensions": [],
310
- "terminalGraceMs": 1500
311
- }
312
- }
313
- }
314
- ```
315
-
316
- `allowlist` accepts explicit trusted extension files; `inherit` restores ambient
317
- Pi extension discovery as a compatibility mode. Flows cannot widen this host
318
- authority.
319
-
320
- [Read the core concepts →](https://heggria.github.io/taskflow/en/docs/concepts/)
321
-
322
- ## Install on your host
323
-
324
- All packages require **Node.js ≥ 22.19.0**.
325
-
326
- ### Pi
327
-
328
- ```bash
329
- pi install npm:pi-taskflow
330
- ```
331
-
332
- Pi provides the richest local experience: the `taskflow` tool, `/tf` commands, live DAG rendering, interactive approvals, background runs, and model-role setup.
333
-
334
- [Pi guide →](https://heggria.github.io/taskflow/en/docs/guides/pi)
335
-
336
- ### OpenAI Codex
337
-
338
- ```bash
339
- codex plugin marketplace add heggria/taskflow
340
- codex plugin add taskflow@taskflow
341
- ```
342
-
343
- [Codex guide →](https://heggria.github.io/taskflow/en/docs/guides/codex)
344
-
345
- ### Claude Code
346
-
347
- ```bash
348
- claude plugin marketplace add heggria/taskflow
349
- claude plugin install claude-taskflow@taskflow
350
- ```
351
-
352
- [Claude Code guide →](https://heggria.github.io/taskflow/en/docs/guides/claude-code)
353
-
354
- ### OpenCode
355
-
356
- ```bash
357
- opencode mcp add taskflow -- \
358
- npx -y -p opencode-taskflow@0.2.9 opencode-taskflow-mcp
359
- ```
360
-
361
- [OpenCode guide →](https://heggria.github.io/taskflow/en/docs/guides/opencode)
362
-
363
- ### Grok Build
364
-
365
- ```bash
366
- grok mcp add taskflow -- \
367
- npx -y -p grok-taskflow@0.2.9 grok-taskflow-mcp
368
- ```
369
-
370
- 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.
371
-
372
- [Grok Build guide →](https://heggria.github.io/taskflow/en/docs/guides/grok-build)
373
-
374
- ### Hermes Agent
375
-
376
- ```bash
377
- hermes mcp add taskflow --command npx --args -y -p hermes-taskflow@0.2.9 hermes-taskflow-mcp
378
- # Prefer env in config.yaml (not CLI --env after args — can be stuffed into argv):
379
- # mcp_servers.taskflow.env.PI_TASKFLOW_HERMES_UNSAFE_YOLO: "1" # mutating only
380
- ```
162
+ | Operation | Question it answers |
163
+ |---|---|
164
+ | `taskflow_plan` | What will run, what arguments bind, and what is the worst-case agent-call bound? |
165
+ | `taskflow_verify` / `taskflow_compile` | Is the graph structurally valid and what is its canonical form? |
166
+ | `taskflow_trace` / `taskflow_replay` | What happened, or what would a zero-token what-if replay decide? |
167
+ | `taskflow_why_stale` / `taskflow_recompute` | What changed and what is the smallest affected frontier? |
168
+ | `taskflow_why_effect` | Why was a declared effect allowed, staged, committed, rejected, or left unknown? |
169
+ | `taskflow_analytics` | How have recent runs behaved? |
381
170
 
382
- Hermes quiet mode does not report token/cost usage, so budget-declaring flows are rejected rather than silently running without enforcement. Child agents use an ephemeral HERMES_HOME with only non-secret model/fallback routing, a routed-provider-only inference `auth.json`, and provider-allowlisted dotenv keys; parent MCP, skills, memory, sessions, and rules are not inherited. RO local-read → `taskflow_readonly_files`; else `taskflow_model_only` (never omit `-t`).
171
+ The MCP surface currently exposes **20 tools**. Intermediate transcripts remain inside the runtime unless you explicitly inspect them with `peek` or `trace`; the host normally receives only `finalOutput`.
383
172
 
384
- [Hermes guide →](https://github.com/heggria/taskflow/blob/main/docs/hermes-mcp.md)
173
+ ## Host adapters
385
174
 
175
+ The same flow contract can be delivered through six coding-agent hosts:
386
176
 
387
- ## Built to survive real work
177
+ - **Pi** — native extension, `/tf` commands, live run views, and interactive approvals.
178
+ - **Codex** — plugin and stdio MCP server.
179
+ - **Claude Code** — plugin and stdio MCP server.
180
+ - **OpenCode** — MCP configuration and generated skill.
181
+ - **Grok Build** — MCP configuration and generated skill.
182
+ - **Hermes Agent** — MCP delivery with explicit child toolsets and isolation policy.
388
183
 
389
- <div align="center">
184
+ Host support is not a blanket security guarantee. Read the [host support baseline](https://github.com/heggria/taskflow/blob/main/conformance/workspace/host-support-baseline.json) and the [Trusted Effects documentation](https://github.com/heggria/taskflow/blob/main/docs/internal/0.3.0-trusted-effects-mvp.md) before enabling mutating phases.
390
185
 
391
- **10 packages** · **6 hosts** · **12 phase types** · **18 built-in agents** · **1,500+ tests** · **MIT**
186
+ ## Security boundaries we state plainly
392
187
 
393
- </div>
188
+ - `effects[]` is a declaration and validation surface; it is not ambient authority.
189
+ - The resources layer is the only finalizer for admitted declared filesystem effects.
190
+ - Direct writes to declared targets are detected and restored by the MVP path.
191
+ - Writes to undeclared paths remain host-policy dependent under resolve-only execution.
192
+ - `SecretRef` and `ServiceRef` are typed handles only; no vault or live service adapter ships in this cut.
193
+ - There is no FileBroker or full OS sandbox claim in 0.3 MVP.
194
+ - Control Plane stores, approvals, receipts, and WebUI are future 0.3-C stages, not proof that 0.3 is released or GA.
394
195
 
395
- ```text
396
- taskflow-core
397
- ┌──────────────┼───────────────┐
398
- │ │ │
399
- taskflow-dsl pi-taskflow taskflow-mcp-core ─┐
400
- taskflow-hosts ─────┼─ codex-taskflow
401
- ├─ claude-taskflow
402
- ├─ opencode-taskflow
403
- └─ grok-taskflow / hermes-taskflow
404
- ```
405
-
406
- `taskflow-core` is host-neutral and imports no host SDK. `taskflow-mcp-core` implements stdio JSON-RPC without an MCP SDK dependency; `taskflow-hosts` owns the shared host process runners. The five MCP delivery packages bind both layers (and core), while Pi keeps its native adapter.
407
-
408
- The test suite covers orchestration semantics, persistence and file-lock races, cache freshness, path traversal, dynamic graph hardening, cancellation, budgets, all 12 phase kinds, FlowIR/replay/recompute, TypeScript DSL erasure, host argv contracts, MCP servers, and packed consumer imports.
409
-
410
- ## Documentation
411
-
412
- | Start here | When you need |
413
- |---|---|
414
- | [Getting Started](https://heggria.github.io/taskflow/en/docs/getting-started) | Your first successful run |
415
- | [Concepts](https://heggria.github.io/taskflow/en/docs/concepts/) | DAGs, isolation, verification, resume, shared context |
416
- | [Syntax](https://heggria.github.io/taskflow/en/docs/syntax/) | Phase fields, control flow, budgets, caching, scorers |
417
- | [Compiler & Runtime](https://heggria.github.io/taskflow/en/docs/compiler-runtime/) | TypeScript DSL, FlowIR, replay, recompute, background runs |
418
- | [Host Guides](https://heggria.github.io/taskflow/en/docs/guides/) | Pi, Codex, Claude Code, OpenCode, Grok, and Hermes setup |
419
- | [Reference](https://heggria.github.io/taskflow/en/docs/reference/) | Commands, shorthand, and exact tool surfaces |
420
- | [Showcase](https://heggria.github.io/taskflow/en/docs/showcase/) | Real flows and case studies |
421
- | [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) |
422
-
423
- 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).
424
-
425
- ## Contributing
196
+ ## Development
426
197
 
427
198
  ```bash
428
199
  pnpm install
429
200
  pnpm run typecheck
430
201
  pnpm test
431
202
  pnpm run build
203
+ pnpm run build:website
432
204
  pnpm run test:pack
433
205
  ```
434
206
 
435
- Contributions are welcome. Start with [`CONTRIBUTING.md`](https://github.com/heggria/taskflow/blob/main/CONTRIBUTING.md) for the workflow and [`AGENTS.md`](https://github.com/heggria/taskflow/blob/main/AGENTS.md) for architecture and coding conventions.
207
+ The monorepo contains the host-neutral `taskflow-core`, Trusted Effects and resources code, the `taskflow-control` 0.3-C contract package, the TypeScript DSL, MCP/host adapters, examples, and the website. See [`AGENTS.md`](https://github.com/heggria/taskflow/blob/main/AGENTS.md) for architecture and coding conventions.
208
+
209
+ ## Documentation
210
+
211
+ | Start here | Use it for |
212
+ |---|---|
213
+ | [0.3 overview](https://heggria.github.io/taskflow/en/docs) | Candidate scope, status, and the honest security boundary |
214
+ | [Getting Started](https://heggria.github.io/taskflow/en/docs/getting-started) | First flow and host setup |
215
+ | [Core Concepts](https://heggria.github.io/taskflow/en/docs/concepts/) | DAGs, isolation, verification, resume, and evidence |
216
+ | [Compiler & Runtime](https://heggria.github.io/taskflow/en/docs/compiler-runtime/) | JSON, TypeScript DSL, FlowIR, replay, and recompute |
217
+ | [Host Guides](https://heggria.github.io/taskflow/en/docs/guides/) | Pi, Codex, Claude Code, OpenCode, Grok, and Hermes |
218
+ | [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 candidate notes |
436
220
 
437
221
  ## License
438
222
 
@@ -440,8 +224,8 @@ Contributions are welcome. Start with [`CONTRIBUTING.md`](https://github.com/heg
440
224
 
441
225
  <div align="center">
442
226
 
443
- **Declare once. Verify first. Recompute only what changed.**
227
+ **Declare the effect. Verify the path. Commit through one authority.**
444
228
 
445
- [Read the docs](https://heggria.github.io/taskflow/en/docs) · [Try an example](https://github.com/heggria/taskflow/blob/main/examples) · [View releases](https://github.com/heggria/taskflow/releases)
229
+ [Read the docs](https://heggria.github.io/taskflow/en/docs) · [Try the candidate](#quickstart) · [View releases](https://github.com/heggria/taskflow/releases)
446
230
 
447
231
  </div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hermes-taskflow",
3
- "version": "0.2.9",
3
+ "version": "0.3.0-beta.1",
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.2.9",
54
- "taskflow-hosts": "0.2.9",
55
- "taskflow-mcp-core": "0.2.9"
53
+ "taskflow-core": "0.3.0-beta.1",
54
+ "taskflow-hosts": "0.3.0-beta.1",
55
+ "taskflow-mcp-core": "0.3.0-beta.1"
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.2.9", "hermes-taskflow-mcp"]
17
+ args: ["-y", "-p", "hermes-taskflow@0.3.0-beta.1", "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.
@@ -30,6 +30,7 @@ session.
30
30
  | `taskflow_trace` | Read a run's append-only event timeline. |
31
31
  | `taskflow_replay` | Replay recorded decisions offline with optional overrides — zero model calls. |
32
32
  | `taskflow_why_stale` | Explain why phases are stale from observed and declared dependencies — zero tokens. |
33
+ | `taskflow_why_effect` | Explain why a declared effect is authorized, from the durable resource-intent ledger (`runId` + `effectId`, optional `phaseId`; `json: true` for the full record). Declaration alone is not authorization — zero tokens, read-only. |
33
34
  | `taskflow_recompute` | Compute the stale frontier (**dry-run only** over MCP; never executes phases). |
34
35
  | `taskflow_reconcile_workspace` | After inspection/repair, accept a failed resolve-only workspace. Requires host `TASKFLOW_WORKSPACE_RECONCILE_MODE=explicit`; never restores files. |
35
36
  | `taskflow_save` | Save a reusable flow and optional library metadata. |
@@ -218,6 +219,7 @@ back cleanly: precedence is `define` (inline) > `defineFile` (disk) > `name`
218
219
  | `timeout` | max ms per subagent call (>= 1000). On expiry the subagent is aborted and the phase fails with a `timedOut` marker — deterministic, **never retried**. Caps EACH call, so a map/parallel/race/loop/tournament phase's wall time is per item/iteration/variant (a tournament's judge call gets its own cap too). Script phases keep their own child-process timeout (default 60s, max 300s). Not supported on approval/flow/expand. Pair with `optional: true` + a downstream fallback phase to degrade instead of failing the run. |
219
220
  | `expect` | output contract for `output: "json"` phases (agent/gate/reduce/loop): a JSON-Schema-like shape `{type, properties, required, items, enum}` validated the moment the subagent finishes. A violation fails the phase with per-path diagnostics (e.g. `$.score: required key is missing`) and is retryable under the phase's explicit `retry`. `verify`/`compile` also statically warn when a `{steps.X.json.field}` ref names a field absent from X's declared contract. |
220
221
  | `idempotent` | side-effect classification. Default `true` (safe to cache + auto-retry). Set `false` on phases with **irreversible side effects** (webhook POSTs, deploys, DB writes, file mutations): transient provider errors are **not** auto-retried (an explicit `retry{}` IS still honored — it's your declaration that repeats are acceptable) and the result is **never cached** in any scope (within-run resume, cross-run, `incremental` — the phase re-runs every time). The phase state records `sideEffect: true` (rendered as ⚡). |
222
+ | `effects` | **[0.3 Trusted Effects]** declared side-effect bag for this phase — typed `fs.read` / `fs.write` / `fs.delete` / `secret.read` / `service.call` declarations with PathRef/SecretRef/ServiceRef targets and optional confidentiality/integrity labels. See **Trusted Effects** below. |
221
223
  | `optional` | fail-soft — a failed/blocked phase won't abort the run; downstream sees empty output. Pair with a fallback phase guarded by `when`. |
222
224
  | `cache` | per-phase reuse policy (`run-only` default / `cross-run` / `off`). See `configuration.md` §8. |
223
225
 
@@ -487,6 +489,19 @@ output is exact.
487
489
  - A non-zero exit fails the phase (stderr captured); stdout capped at 1 MB.
488
490
  No `retry`, no `output: "json"`; **excluded from cross-run cache** (may have
489
491
  side effects). Not allowed inside LLM-generated dynamic sub-flows (RCE guard).
492
+ - Top-level `scriptCwd: "flow"` makes script phases run from the canonical saved
493
+ flow/`defineFile` directory. The default is `"invocation"`; explicit phase
494
+ `cwd` still wins. Inline definitions cannot claim file provenance and fail
495
+ closed in `"flow"` mode. The source directory identity is checked again just
496
+ before spawn, and any inherited cwd-bridge boundary still constrains it.
497
+ - Saved flows may live at legacy `.pi/taskflows/*.json` or recursively below
498
+ `.pi/taskflows/flows/**/*.json`. Legacy files win same-scope duplicate names;
499
+ nested candidates use deterministic Unicode-scalar path order. Discovery
500
+ rejects symlinks below trusted storage boundaries and fails closed above 1,000
501
+ flows, 10,000 entries, 512 directories, 8 MiB total definitions, 1 MiB per
502
+ definition, or 16 levels. A configured user agent-directory boundary may be a
503
+ symlink; project `.pi` remains no-follow. New-flow saves enforce the same
504
+ boundary policy and revalidate the target directory inside the write lock.
490
505
 
491
506
  ```jsonc
492
507
  { "id": "build", "type": "script", "run": "pnpm run build", "timeout": 120000 },
@@ -494,6 +509,82 @@ output is exact.
494
509
  "input": "{steps.analyze.output}", "dependsOn": ["analyze"], "final": true }
495
510
  ```
496
511
 
512
+ ### Trusted Effects (`effects[]` — declared side effects, 0.3)
513
+
514
+ > **One-line authority: the model proposes content; the resources runtime is
515
+ > the only commit authority.** A phase declares *what* it intends to touch;
516
+ > for admitted declared `fs.write` targets the runtime runs the
517
+ > resource-controlled **file transaction** — durable snapshot → persistent
518
+ > lease → journal intent/permit → stage → **Commit** or **Restore+Reject** —
519
+ > and no other code finalizes declared content.
520
+
521
+ Trusted Effects (0.3 MVP) adds an optional `effects[]` bag to **any** phase: a
522
+ closed vocabulary of typed side-effect declarations. `verify` / `compile`
523
+ statically check the bag (unknown kinds, malformed targets, and illegal
524
+ label flows surface as `[effects]` issues), and a run admits every declared
525
+ target through PathRef resolution — lease, durable intent, mutation permit —
526
+ **before** the phase body executes. Start from the runnable example
527
+ **`examples/trusted-effects-write.json`** (a `script` phase that declares one
528
+ `fs.write` and commits it via the resource transaction — no LLM involved).
529
+
530
+ Each effect:
531
+
532
+ | field | meaning |
533
+ |-------|---------|
534
+ | `id` | stable id within the flow — the handle the why-* audit explains |
535
+ | `kind` | `fs.read` · `fs.write` · `fs.delete` · `secret.read` · `service.call` |
536
+ | `target` | `{ kind: "path", path: <PathRef> }`, or the `secret` / `service` handle shapes |
537
+ | `confidentiality` | optional label `public` · `internal` · `secret` — a higher label must not flow to a lower sink |
538
+ | `integrity` | optional label `untrusted` · `project` · `verified` — lower integrity must not overwrite higher |
539
+ | `purpose` | free-text note surfaced by the why-* explainers (**not** authority) |
540
+
541
+ **PathRef shape** — the FS target, always relative to a workspace scope:
542
+
543
+ ```jsonc
544
+ "target": {
545
+ "kind": "path",
546
+ "path": {
547
+ "workspace": "project", // scope the path resolves in
548
+ "subpath": { "literalPath": "out/report.md" }, // or { "argPath": "out" } / { "segments": [ { "segment": "out" } ] }
549
+ "intent": "create-file" // create-file | create-directory | existing-file | existing-directory | executable
550
+ }
551
+ }
552
+ ```
553
+
554
+ **Phase output is the payload.** With one declared `fs.write`, the phase's
555
+ output becomes the staged file content (see the example: `process.stdout.write`
556
+ = the report). With several `fs.write` effects, the phase must emit JSON
557
+ mapping each effect id to its content (`{ "report": "…", "backup": "…" }`).
558
+ Commit promotes each file atomically; a later failure restores every admitted
559
+ file to its durable pre-state, and a direct write by the agent/script to a
560
+ **declared final path** is detected and restored — only the resource
561
+ transaction may finalize declared content.
562
+
563
+ **Only `fs.write` has a bound runtime backend in this cut.** The other kinds
564
+ are valid to declare and verify, but fail **closed** (no bound resource
565
+ backend): `fs.delete` is not supported by the file transaction, and
566
+ `secret.read` / `service.call` have no vault/network adapters in 0.3 — do not
567
+ author a flow expecting them to do anything yet.
568
+
569
+ **Audit with `taskflow_why_effect` (zero tokens, read-only).** Pass `runId` +
570
+ `effectId` (add `phaseId` to disambiguate a repeated id; `json: true` for the
571
+ full record) to explain a declared effect's authorization and lifecycle from
572
+ the durable resource-intent ledger — principal, capability binding, intent id,
573
+ journal status, and lifecycle (`declared` / `staged` / `committed` /
574
+ `rejected` / `unknown`). **Declaration alone is not authorization**: if no
575
+ durable intent admitted the effect for this run/phase, `authorized.allowed` is
576
+ `false` (fail-closed).
577
+
578
+ **What this is NOT (honesty baseline):**
579
+
580
+ - **No FileBroker sandbox.** Every host's PathRef support is *resolve-only*;
581
+ this is not an OS sandbox, and no host claims a FileBroker guarantee.
582
+ - **Undeclared paths are not protected.** Only writes to *declared* final
583
+ targets are detected and restored; writes outside the declared set remain
584
+ host-policy dependent.
585
+ - **`secret.read` / `service.call` are type-only fail-closed** (see above) —
586
+ valid declarations, no backend in the MVP.
587
+
497
588
  ### Race phases (first success wins)
498
589
 
499
590
  A `race` phase runs static `branches[]` concurrently and **returns the first
@@ -32,6 +32,7 @@ Top-level keys of the taskflow definition object.
32
32
  "description": "Audit API auth", // shown in /tf list and the command palette
33
33
  "concurrency": 8, // default max concurrent subagents (default: 8)
34
34
  "agentScope": "user", // user | project | both (default: user)
35
+ "scriptCwd": "invocation", // invocation | flow (default: invocation)
35
36
  "args": { /* see §3 */ },
36
37
  // 0.2.7: optional terminal hooks (summary payload only — never transcripts)
37
38
  // "hooks": { "onComplete": [{ "type": "file", "path": ".taskflow/hooks/last.json" }] },
@@ -46,11 +47,14 @@ Top-level keys of the taskflow definition object.
46
47
  | `concurrency` | number | `8` | Default fan-out / same-layer parallelism cap. See §4. |
47
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. |
48
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. |
49
51
  | `args` | record | `{}` | Declared invocation arguments. See §3. |
50
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). |
51
53
  | `phases` | array | — | **Required.** The phase DAG. See §2. |
52
54
  | `version` | number | `1` | Informational metadata in 0.2.x; it does not select runtime semantics or migrate a flow. |
53
55
 
56
+ Saved definitions remain compatible at `.pi/taskflows/*.json` and may also be organized recursively below `.pi/taskflows/flows/**/*.json`. Legacy top-level files win same-scope duplicate names; nested candidates use deterministic Unicode-scalar path order. Discovery has one shared user/project budget and fails closed above 1,000 flows, 10,000 entries, 512 directories, 8 MiB total definition bytes, 1 MiB per definition, or 16 nested levels. Symlinks below trusted storage boundaries are rejected; a configured user agent-directory boundary may itself be a symlink, while project `.pi` remains no-follow. New-flow saves enforce the same boundary policy and revalidate the physical target directory inside the write lock.
57
+
54
58
  ---
55
59
 
56
60
  ## 2. Phase-level options
@@ -305,7 +309,7 @@ Notes:
305
309
  phases fail closed unless `PI_TASKFLOW_HERMES_UNSAFE_YOLO=1`, which enables
306
310
  `--yolo`; their default surface is local `file,terminal`, while explicit web
307
311
  aliases may add `web`. Delegation, skills, memory, browser, cron, and other
308
- control-plane toolsets are denied in 0.2.9. Optional
312
+ control-plane toolsets are denied in 0.2.10. Optional
309
313
  `PI_TASKFLOW_HERMES_MAX_TURNS` caps child loops (default 64). Quiet mode
310
314
  does not stream token/cost accounting, so budgeted flows fail closed at the
311
315
  MCP adapter the same way other non-accounting hosts do when costs are