@signalridge/pi-workflows 1.6.0 → 1.7.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/CHANGELOG.md CHANGED
@@ -1,5 +1,154 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.7.1
4
+ ### Patch Changes
5
+
6
+ - 1f586f8: Preserve resumable cancellation when a workflow pauses during successful timeout cleanup, and retain finalized subagent output alongside observer failures. Avoid retaining descendant-owned mouse gestures in bordered components. Track successful writes using final rewritten paths, and distinguish uncertain changes observed during failed calls from confirmed agent modifications while keeping both discoverable in file browsing. Preserve exact filesystem paths and lazy-directory scan state when discovering session-observed changes, including changes injected during an active scan.
7
+ - 1f586f8: - Bound workflow cancellation drains and durably fence unconfirmed cleanup, aborting sibling agents and releasing foreground callers.
8
+ - Await managed timeout cleanup before script continuation and terminal publication.
9
+ - Keep failed retry text and length responses discarded by overflow-compaction retry out of successful subagent fallbacks, while retaining valid pre-compaction and non-retried length output.
10
+ - Account for native prompts spanning reporter activation without dropping out-of-order wait debt.
11
+ - Reconcile settlement after observer-triggered manual compaction with run/session ownership.
12
+ - Preserve clipped overlay hit ranges and native container ancestry for editor autocomplete focus.
13
+ - Reconcile errored writes and edits against pre/post mutation evidence, retaining invocation cwd and releasing evidence when blocked or aborted preflight bypasses tool results.
14
+ - d9219d4: Correct shipped documentation that contradicted the code or the manifest.
15
+
16
+ - `pi-subagents`: the summary line still advertised protocol-v3 spawning while
17
+ the feature list and the managed-spawn section described v4.
18
+ - `pi-worktree`: the workspace-switching section named `/tree`; the registered
19
+ command is `/worktree`.
20
+ - `pi-workflows`: removed an orphaned sentence fragment left behind by an edit
21
+ to the saved-workflow paragraph.
22
+ - `pi-plan-mode`, `pi-goal`, `pi-usage-extension`: the stated Pi floor
23
+ (`0.80.6`, `0.42.4+`) contradicted the declared `^0.84.0` peer range, which
24
+ resolves to `0.84.x`. `pi-usage-extension` also carried a "Last updated"
25
+ stamp from a version that predates the workspace baseline.
26
+ - `pi-welcome`: the example card was a real session capture. It is now a
27
+ generic sample, and Install moved above the configuration sections instead of
28
+ sitting below them.
29
+ - 1f586f8: Preserve Codex opaque checkpoints across Pi's retry-only assistant-tail removal using optional, fingerprint-verified version-1 proof plus explicit lifecycle provenance. Preserve that provenance across same-runtime reload without confusing a new identical assistant response with the persisted tail; persisted rebuilds reset it and unknown provenance fails closed. Bound BTW context and tool-argument construction, including suffix-key storage for wide JSON-shaped objects (enumeration remains linear). Balance out-of-order native UI waiting notifications without affecting manual blocked ownership. Foreground workflow cancellation waits for exact-owner quiescence even when stop is unavailable or rejects after reconciliation already stopped the child, including cancelled spawn allocation recovery; unconfirmed cleanup becomes durably non-resumable with a diagnostic retaining any stop error. Background execution remains detached.
30
+
31
+ These are corrective changes: existing checkpoint fields, exports, and cross-extension protocols remain compatible, so no protocol or major-version bump is required.
32
+ - 1f586f8: Expand Pi peer support to `^0.84.0 || ^0.85.0`, retaining 0.84 compatibility while admitting 0.85 releases. The previous zero-major caret range excluded Pi 0.85.1. Update existing Pi development dependency pins to 0.85.1.
33
+ - 1f586f8: Keep goal iteration and continuation numbering correct when Pi compacts between tool results and the next response within one run. Preserve existing response limits and manual/post-run compaction handling.
34
+
35
+ Capture subagent invocation results from finalized assistant events with bounded message retention so compaction cannot hide a final error or mix in historical output. Recognize explicitly selected PowerShell when the host provides it, without requiring its export on older Pi versions or expanding default wildcard tools.
36
+
37
+ Use real session contexts for workflow replay and live TUI progress, release widget bindings on shutdown, and allow foreground checkpoint dialogs in RPC mode while retaining print-mode defaults. Cancel unanswered dialogs with their owning execution on tool abort, pause, stop, disposal, or fatal failure without journaling cancelled answers.
38
+
39
+ ## 1.7.0
40
+ ### Minor Changes
41
+
42
+ - f05185e: A workflow now runs at the width of the host's subagent pool rather than a
43
+ number it picked blind, and stops charging queue time against the agent waiting
44
+ in it.
45
+
46
+ Two facts were missing on the pi-workflows side, and they compounded. It had no
47
+ way to learn `maxConcurrent`, so its own width was a constant guess. And a
48
+ dispatched agent was treated as a running one, though a managed spawn takes a
49
+ background slot like any other and waits when the pool is full, so a batch
50
+ dispatched behind a busy pool could fail as timeouts with none of it having run.
51
+
52
+ - The ping reply can now carry the peer's live `maxConcurrent`, and pi-workflows
53
+ makes it both the default width and the ceiling: an unnamed `concurrency` takes
54
+ the pool size, and a named one is clamped to it, with the clamp recorded in the
55
+ run log so a caller who asked for a number learns why it got another. It is
56
+ read at each start and resume rather than frozen onto the run, because the pool
57
+ is a setting the user can change in between. One setting therefore governs the
58
+ whole fleet, which is what the ownership boundary already said and what the
59
+ code can now honour.
60
+ - **This narrows the common case, and that is the point.** The pool defaults to
61
+ 4 background slots, so a default pair now runs a fan-out four at a time where
62
+ it used to dispatch `hardwareConcurrency - 2`. Nothing runs slower for it —
63
+ dispatching twelve into four slots only ever queued eight, ahead of the host's
64
+ own spawns — but the width a run reports is now the width it actually has, and
65
+ `maxConcurrent` is the single place to raise it for workflows and every other
66
+ background agent at once. A host that had already raised it gets the wide
67
+ fan-outs its setting always implied.
68
+ - The field is **requested by name** (`include: ["maxConcurrent"]`) rather than
69
+ volunteered. A ping envelope is parsed with `rejectUnknownKeys`, so a peer that
70
+ simply added a field would make every already-published caller reject the
71
+ handshake and lose workflows entirely. Asking keeps both directions working: an
72
+ older peer answers without it and the caller falls back to 16, and a caller that
73
+ never asks gets the v4 envelope unchanged. No version bump, no capability, no
74
+ lockstep release. Both READMEs document the mechanism, since `include` is now
75
+ part of the public cross-extension contract.
76
+ - `agentTimeoutMs` now counts from the moment the host reports the agent left its
77
+ queue. The clock is still armed at dispatch and restarted on that report, not
78
+ armed only by it, so a report that never arrives degrades to the old behaviour
79
+ rather than to an agent that can hang forever. A report that arrives *after* the
80
+ agent settled is ignored, so a late or duplicate one cannot leave a live timer
81
+ behind to abort a finished agent.
82
+
83
+ The engine already subscribed to `subagents:started` and already filtered it by
84
+ workflow owner, so the start signal is the event it was discarding.
85
+
86
+ `getMaxConcurrent` is required on the RPC bridge rather than optional. The other
87
+ bridge members are capabilities, advertised in the ping and rejected outright
88
+ when missing, so forgetting one fails loudly; a missing pool size has no
89
+ capability bit and no failure — the caller would silently fall back to its own
90
+ guess and run at the wrong width. Required is what makes that omission a compile
91
+ error instead of a quiet wrong answer.
92
+ - f05185e: Stop the run's own limits from being the thing that keeps a fan-out small.
93
+
94
+ Every execution limit a caller can pass — `maxAgents`, `concurrency`,
95
+ `agentRetries`, `tokenBudget`, `agentTimeoutMs` — reached the model as a bare
96
+ number with no stated default, while the authoring skill asked it to "set finite
97
+ bounds that match the work" for three of them. The result was a caller that
98
+ priced the run before writing it: fan-outs of one to eight, `concurrency: 1`,
99
+ and per-agent wall clocks of two to five minutes. Each of those values ends a run
100
+ rather than shaping it — `AGENT_LIMIT_EXCEEDED` partway through, or a whole
101
+ batch failing as timeouts — so the precaution removed coverage and not cost.
102
+
103
+ Four changes, and the first two matter most:
104
+
105
+ - Every numeric tool input now states its default and says to omit it, and the
106
+ guidelines ask for a fan-out sized to the evidence the task has: one agent per
107
+ independent question, ten to thirty for an ordinary review or audit. The gain
108
+ named is coverage, not speed — one agent asked one question reads further into
109
+ it than one agent asked four — because how many of them run at once is the
110
+ host's pool and not the script's to decide. The authoring and review skills no
111
+ longer treat the invocation limits as the place to express a bound — that
112
+ belongs to the script's own task counts, loop rounds, and fan-out widths, which
113
+ is where the topology is decided. `lifecycle.md` also stops citing two settings
114
+ keys that never existed (`defaultAgentTimeoutMs`, `defaultTokenBudget`).
115
+ - `agentTimeoutMs` defaults to 30 minutes rather than 5. It exists to bound a
116
+ hang; an agent's real budget is the turn, tool and token ceiling pi-subagents
117
+ applies to it, which a deep call legitimately spends over many minutes. A
118
+ default an order of magnitude under that budget turned every wide fan-out of
119
+ real work into a batch of timeouts. `null` still removes the wall clock.
120
+ - Concurrency defaults to 16 and clamps at 64, up from a default of
121
+ `hardwareConcurrency - 2` clamped at 16. Core count was the wrong quantity: a
122
+ dispatched agent is a remote call this process waits on, so the old default
123
+ fanned a 14-core host out 12 ways and a 4-core host 2 ways for identical work.
124
+ pi-subagents' `maxConcurrent` remains the authoritative throttle — this is the
125
+ guard against a runaway script, and a host that wants a narrower fleet still
126
+ narrows it in one place for every agent it runs.
127
+ - `strength` gains a criterion instead of three bare words. `high` now means a
128
+ step whose error is expensive to reverse — an architecture decision, a
129
+ destructive migration, a security boundary — normally absent from a fan-out and
130
+ at most one closing step, and the authoring skill and review checklist both say
131
+ so. The ULTRA effort directive stops asking for it outright: it used to end
132
+ `give the deepest steps strength: "high"`, which priced every branch of a wide
133
+ run at the cost of the one that mattered, and now points the exhaustiveness at
134
+ width and reserves `high` for a step that has that property, if the run has one.
135
+ Nothing about the mechanism changed — there is still no default strength, and a
136
+ call naming none still dispatches with no tier.
137
+ - `/workflows run` plans up to 24 tasks instead of 8. The planner's JSON schema
138
+ was the only bound on the one path where the model decides the width itself,
139
+ and 8 was below what an ordinary audit decomposes into. The synthesis step
140
+ absorbs the extra tasks by shrinking its per-worker excerpt: measured against
141
+ the 78,000-character context budget, 8 tasks contribute about 6,000 characters
142
+ each and 24 contribute about 2,500 — three times the coverage at roughly 40%
143
+ of the depth per worker, and about a quarter more total evidence reaching the
144
+ synthesizer. Widening past that would need a larger budget, which the wire's
145
+ 100,000-character prompt cap does not leave room for.
146
+
147
+ ### Patch Changes
148
+
149
+ - Updated dependencies [f05185e]
150
+ - @signalridge/pi-subagents-protocol@1.5.0
151
+
3
152
  ## 1.6.0
4
153
  ### Minor Changes
5
154
 
package/README.md CHANGED
@@ -145,8 +145,31 @@ workflow, and the review skill before accepting a topology or recovery change.
145
145
  ## Tools and commands
146
146
 
147
147
  - `workflow`: run a script (`script`) or a saved/built-in workflow (`name`),
148
- with `args`, `background` (default true), `maxAgents`, `concurrency`,
149
- `agentRetries`, `tokenBudget`, `agentTimeoutMs`, and `resumeFromRunId`.
148
+ with `args`, `background` (default true), `maxAgents` (default 1000),
149
+ `concurrency` (defaults to the host's pool size), `agentRetries` (default 0),
150
+ `tokenBudget` (default unlimited), `agentTimeoutMs` (default 1800000, `null`
151
+ disables), and `resumeFromRunId`. The execution limits are tuned defaults: a
152
+ caller that names one narrower than the script needs stops the run rather
153
+ than shaping it.
154
+
155
+ Concurrency is not configured here at all. A workflow agent occupies one of
156
+ pi-subagents' `maxConcurrent` background slots like any other background
157
+ agent, so that setting is both the width a run defaults to and the ceiling it
158
+ is clamped to — read live from the peer at each start and resume, so one
159
+ setting governs the whole fleet and a run neither guesses it nor exceeds it.
160
+ The peer publishes it only to a caller that requests it by name, so an older
161
+ pair still handshakes; a run that learns no pool size falls back to 16. A
162
+ request above the pool is clamped and the run log says so.
163
+
164
+ In practice that pool is usually the *narrower* number, not the wider one: it
165
+ defaults to 4 background slots, so a default pair runs a fan-out four at a
166
+ time. That is the honest width rather than a new restriction — dispatching
167
+ twelve into four slots only ever queued eight — but it does mean a wide
168
+ fan-out finishes in waves, and `maxConcurrent` is the one place to change
169
+ that, for workflows and for every other background agent at once.
170
+
171
+ `agentTimeoutMs` counts from the moment the host reports the agent left its
172
+ queue, so waiting for a slot is never charged against the work.
150
173
  - `workflow_control`: `list`, `get`, `pause`, `resume`, `stop`, or `rm` a run; `rm` writes a durable removal tombstone.
151
174
  - `pi.events` emits `pi-workflows:runtime` snapshots (`{ runId, event }`) for phase, task, quality, retry, and nested-workflow progress; observer failures are contained.
152
175
  - `/workflows`: TUI navigator plus `run`, `status`, `watch`, `stop`, `pause`,
@@ -185,7 +208,6 @@ sentence-ending dot is not a filename dot: "please run a workflow." arms, and
185
208
  turn it off entirely with `/workflows-trigger off`.
186
209
 
187
210
  Saved workflows use project scope first and a user scope fallback; writes are atomic and names are path-safe.
188
- written atomically with a backup.
189
211
 
190
212
  ## Model routing
191
213
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@signalridge/pi-workflows",
3
- "version": "1.6.0",
3
+ "version": "1.7.1",
4
4
  "description": "Deterministic JavaScript orchestration workflows backed by pi-subagents managed spawning.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -15,12 +15,12 @@
15
15
  "lifecycle": "stable"
16
16
  },
17
17
  "peerDependencies": {
18
- "@earendil-works/pi-coding-agent": "^0.84.0",
19
- "@earendil-works/pi-tui": "^0.84.0",
18
+ "@earendil-works/pi-coding-agent": "^0.84.0 || ^0.85.0",
19
+ "@earendil-works/pi-tui": "^0.84.0 || ^0.85.0",
20
20
  "@signalridge/pi-subagents": ">=1.9.0"
21
21
  },
22
22
  "dependencies": {
23
- "@signalridge/pi-subagents-protocol": "^1.4.0",
23
+ "@signalridge/pi-subagents-protocol": "^1.5.0",
24
24
  "@sinclair/typebox": "^0.34.50",
25
25
  "acorn": "^8.16.0"
26
26
  },
@@ -2,7 +2,7 @@
2
2
  name: workflow-authoring
3
3
  description: Design, write, review, and debug Pi JavaScript workflows that coordinate multiple subagents. Use when a request needs named dependencies, bounded fan-out, per-item pipelines, quality gates, saved or nested workflows, pause/resume, or workflow progress; do not use it merely to run an existing named workflow.
4
4
  metadata:
5
- version: "1.6.0"
5
+ version: "1.7.1"
6
6
  ---
7
7
 
8
8
  # Workflow authoring
@@ -25,9 +25,19 @@ JavaScript.
25
25
  - Give every work unit a stable ID and every agent call a short unique label.
26
26
  Keep IDs beside results before filtering; `null` is missing coverage, not a
27
27
  successful finding.
28
- - Bound graph tasks, fan-out items, loops, retries, agents, concurrency, and
29
- evidence size. Invocation-level token and time caps are user constraints, not
30
- substitutes for algorithmic bounds.
28
+ - Bound the algorithm inside the script: graph tasks, fan-out items, loop
29
+ rounds, semantic retries, and evidence size. The invocation-level limits
30
+ (`maxAgents`, `concurrency`, `agentRetries`, `tokenBudget`, `agentTimeoutMs`)
31
+ are tuned defaults rather than the place to express a bound; each one stops or
32
+ fails a run that outgrows it, so a precautionary value cuts the coverage and
33
+ not the cost. Set one only when the user asked for that limit.
34
+ - Size the fan-out to the evidence the task actually has: one agent per
35
+ independent question, ten to thirty for an ordinary review or audit. The gain
36
+ is coverage — one agent asked one question reads further into it than one
37
+ agent asked four. Speed is a separate matter and not yours to decide: how many
38
+ of those agents run at once is the host's `maxConcurrent` pool, so a wide
39
+ fan-out on a narrow pool still finishes in waves. Split for what gets looked
40
+ at, not for wall-clock.
31
41
  - Route an agent call with `strength: "low" | "medium" | "high"` — this
32
42
  package's own word for how much effort a step deserves, and the only routing
33
43
  word a workflow has. It is **not** an agent-tier key: a `strengths` table
@@ -44,6 +54,15 @@ JavaScript.
44
54
  documented keys. Never guess an agent-type name—use
45
55
  names supplied by the current environment and follow
46
56
  [registry ownership](references/registry-ownership.md).
57
+ - Pick that word by what a wrong answer costs, not by how important the step
58
+ feels. `low` is retrieval, navigation, and read-heavy breadth. `medium` is the
59
+ ordinary working rung and where a labelled step belongs unless you can say why
60
+ not. `high` is for a step whose error is expensive to reverse — an architecture
61
+ decision, a destructive migration, a security boundary — and a fan-out normally
62
+ names it zero times, at most once on a closing step that actually decides
63
+ something. It is not a reward for the hardest-sounding task: routing a whole
64
+ fan-out to `high` prices every branch at the cost of the one that mattered, and
65
+ buys depth where the run needed coverage.
47
66
  - Workflows have no imports, filesystem/network APIs, timers, or unrestricted
48
67
  Node APIs. Pass timestamps, randomness, and external decisions through `args`.
49
68
 
@@ -31,7 +31,7 @@ function parseOrFlag(text, requiredKeys) {
31
31
  }
32
32
 
33
33
  // ADAPT: validate and bound work, then keep required fields as small as downstream JavaScript needs.
34
- const work = args && Array.isArray(args.work) ? args.work.slice(0, 8) : [{ id: "sample" }];
34
+ const work = args && Array.isArray(args.work) ? args.work.slice(0, 24) : [{ id: "sample" }];
35
35
  const requiredKeys = ["verdict", "reason"];
36
36
  const outputs = [];
37
37
  const missing = [];
@@ -5,7 +5,7 @@ export const meta = {
5
5
  };
6
6
 
7
7
  // ADAPT: validate the work and choose phase budgets, prompts, and schemas; add invocation-level tokenBudget only when the user explicitly requests a cap.
8
- const work = args && Array.isArray(args.work) ? args.work.slice(0, 8) : [{ id: "sample" }];
8
+ const work = args && Array.isArray(args.work) ? args.work.slice(0, 24) : [{ id: "sample" }];
9
9
  const phaseBudget =
10
10
  args && Number.isFinite(args.phaseBudget) ? Math.max(1, Math.min(args.phaseBudget, 100000)) : 2000;
11
11
  const resultSchema = {
@@ -7,7 +7,7 @@ export const meta = {
7
7
  // ADAPT: accept only a saved workflow name supplied in context; never guess an installed name.
8
8
  const savedWorkflowName = args && typeof args.savedWorkflowName === "string" ? args.savedWorkflowName : null;
9
9
  if (!savedWorkflowName) throw new Error("args.savedWorkflowName must be supplied by context");
10
- const jobs = args && Array.isArray(args.jobs) ? args.jobs.slice(0, 8) : [{ id: "sample" }];
10
+ const jobs = args && Array.isArray(args.jobs) ? args.jobs.slice(0, 24) : [{ id: "sample" }];
11
11
  const preparationSchema = {
12
12
  type: "object",
13
13
  properties: { ready: { type: "boolean" } },
@@ -5,7 +5,7 @@ export const meta = {
5
5
  };
6
6
 
7
7
  // ADAPT: validate and bound work, then keep the schema as small as downstream JavaScript needs.
8
- const work = args && Array.isArray(args.work) ? args.work.slice(0, 8) : [{ id: "sample" }];
8
+ const work = args && Array.isArray(args.work) ? args.work.slice(0, 24) : [{ id: "sample" }];
9
9
  const outputSchema = {
10
10
  type: "object",
11
11
  properties: {
@@ -2,7 +2,7 @@
2
2
  # Workflow capability index
3
3
 
4
4
  Contract format: `2.0.0`<br>
5
- Contract content / skill / extension: `1.6.0`
5
+ Contract content / skill / extension: `1.7.1`
6
6
 
7
7
  This compact generated index covers supported runtime globals and workflow-tool inputs. For constraints, compatibility behavior, internal boundaries, and dynamic-reference ownership, follow the [exhaustive generated facts](capability-details.md).
8
8
 
@@ -11,7 +11,7 @@ This compact generated index covers supported runtime globals and workflow-tool
11
11
  <!-- BEGIN GENERATED SUPPORTED WORKFLOW CAPABILITIES -->
12
12
  | Name | Classification | Signature | Options and defaults |
13
13
  | --- | --- | --- | --- |
14
- | agent | runtime-global | `agent(prompt, options?) => Promise<string \| structured value \| null>` | `label`: string (optional); default: derived from phase and call count<br>`phase`: string (optional); default: current phase<br>`schema`: plain JSON Schema (optional)<br>`strength`: "low" \| "medium" \| "high" (optional); default: no tier is sent; the agent's own tier, else agentTiers.defaultTier<br>`isolation`: "worktree" (optional); default: pi-subagents worktree policy<br>`thread`: string (optional); default: fresh session per call<br>`toolset`: string (optional); default: configured host/agent toolset hint<br>`excludeTools`: string[] (optional)<br>`agentType`: string (optional); default: general-purpose<br>`timeoutMs`: number \| null (optional); default: 300000 (5min); null disables<br>`retries`: number (optional); default: run retry count |
14
+ | agent | runtime-global | `agent(prompt, options?) => Promise<string \| structured value \| null>` | `label`: string (optional); default: derived from phase and call count<br>`phase`: string (optional); default: current phase<br>`schema`: plain JSON Schema (optional)<br>`strength`: "low" \| "medium" \| "high" (optional); default: no tier is sent; the agent's own tier, else agentTiers.defaultTier<br>`isolation`: "worktree" (optional); default: pi-subagents worktree policy<br>`thread`: string (optional); default: fresh session per call<br>`toolset`: string (optional); default: configured host/agent toolset hint<br>`excludeTools`: string[] (optional)<br>`agentType`: string (optional); default: general-purpose<br>`timeoutMs`: number \| null (optional); default: 1800000 (30min); null disables<br>`retries`: number (optional); default: run retry count |
15
15
  | parallel | runtime-global | `parallel(thunks) => Promise<Array<unknown \| null>>` | — |
16
16
  | pipeline | runtime-global | `pipeline(items, ...stages) => Promise<Array<unknown \| null>>` | — |
17
17
  | orchestrate | runtime-global | `orchestrate(tasks, options?) => Promise<{ results, tasks }>` | `onError`: "skip-dependents"\|"continue"\|"fail-fast" (optional); default: "skip-dependents" |
@@ -35,9 +35,9 @@ This compact generated index covers supported runtime globals and workflow-tool
35
35
  | args | workflow-tool-input | `args?: unknown` | — |
36
36
  | background | workflow-tool-input | `background?: boolean = true` | — |
37
37
  | maxAgents | workflow-tool-input | `maxAgents?: number = 1000` | — |
38
- | concurrency | workflow-tool-input | `concurrency?: number` | — |
38
+ | concurrency | workflow-tool-input | `concurrency?: number = the host's pi-subagents maxConcurrent` | — |
39
39
  | agentRetries | workflow-tool-input | `agentRetries?: number = 0` | — |
40
- | agentTimeoutMs | workflow-tool-input | `agentTimeoutMs?: number = 300000` | — |
40
+ | agentTimeoutMs | workflow-tool-input | `agentTimeoutMs?: number = 1800000` | — |
41
41
  | tokenBudget | workflow-tool-input | `tokenBudget?: number` | — |
42
42
  | resumeFromRunId | workflow-tool-input | `resumeFromRunId?: string` | — |
43
43
  | export const meta | script-contract | `export const meta = { name, description, phases? }` | — |
@@ -2,7 +2,7 @@
2
2
  # Exhaustive workflow capability facts
3
3
 
4
4
  Contract format: `2.0.0`<br>
5
- Contract content / skill / extension: `1.6.0`
5
+ Contract content / skill / extension: `1.7.1`
6
6
 
7
7
  Every exact fact below is projected from the installed extension's capability contract. Explanatory judgment belongs in the hand-written references next to this file.
8
8
 
@@ -22,7 +22,7 @@ Every exact fact below is projected from the installed extension's capability co
22
22
  - `toolset`: string (optional); default: configured host/agent toolset hint
23
23
  - `excludeTools`: string[] (optional)
24
24
  - `agentType`: string (optional); default: general-purpose
25
- - `timeoutMs`: number \| null (optional); default: 300000 (5min); null disables
25
+ - `timeoutMs`: number \| null (optional); default: 1800000 (30min); null disables
26
26
  - `retries`: number (optional); default: run retry count
27
27
  - Constraint: recoverable failures return null after retries; nonrecoverable failures throw
28
28
  - Constraint: schema noncompliance after bounded repair attempts is nonrecoverable
@@ -262,8 +262,12 @@ Every exact fact below is projected from the installed extension's capability co
262
262
 
263
263
  - Classification: `workflow-tool-input`
264
264
  - Support: `supported`
265
- - Signature: `concurrency?: number`
266
- - Constraint: runtime clamps to 1..16
265
+ - Signature: `concurrency?: number = the host's pi-subagents maxConcurrent`
266
+ - Constraint: runtime clamps to 1..64
267
+ - Constraint: read live from the peer at each start and resume, and also the ceiling: a request above the pool is clamped to it, and the run log records the clamp
268
+ - Constraint: 16 is only the fallback for a peer that publishes no pool size
269
+ - Constraint: pi-subagents maxConcurrent stays the authoritative throttle; one setting governs the whole fleet
270
+ - Constraint: that pool is typically small (4 slots by default), so a wide fan-out runs in waves rather than all at once
267
271
 
268
272
  <a id="workflow-tool-input-agentretries"></a>
269
273
  ## agentRetries
@@ -278,8 +282,10 @@ Every exact fact below is projected from the installed extension's capability co
278
282
 
279
283
  - Classification: `workflow-tool-input`
280
284
  - Support: `supported`
281
- - Signature: `agentTimeoutMs?: number = 300000`
282
- - Constraint: null disables the hard timeout; default 300000ms (5min)
285
+ - Signature: `agentTimeoutMs?: number = 1800000`
286
+ - Constraint: null disables the hard timeout; default 1800000ms (30min)
287
+ - Constraint: it bounds a hang only; an agent's real budget is the host's turn, tool and token ceiling
288
+ - Constraint: the clock restarts when the host reports the agent left its queue, so waiting for a slot is not charged as work
283
289
 
284
290
  <a id="workflow-tool-input-tokenbudget"></a>
285
291
  ## tokenBudget
@@ -2,7 +2,11 @@
2
2
 
3
3
  ## Bounds and budget
4
4
 
5
- Set finite bounds that match the work for `maxAgents`, `concurrency`, and `agentRetries`; bound graph tasks, fan-out items, loops, and semantic retries inside the script. A journal replay is logical work and does not consume the real-dispatch `maxAgents` cap, but it still counts toward reported call totals. Treat invocation-level `agentTimeoutMs` and `tokenBudget` as opt-in user constraints, not precautionary defaults. Omit `tokenBudget` unless the user supplies a cap or explicitly asks you to choose one. If asked to choose, allow for every planned agent call, retry, synthesis, and verification pass, with headroom. A tight gate can terminate coverage; it does not reduce work already in flight. An omitted `agentTimeoutMs` uses the configured `defaultAgentTimeoutMs` and is otherwise unbounded. An omitted `tokenBudget` uses the configured `defaultTokenBudget` and is otherwise unlimited.
5
+ Bound the work where the work is decided: graph tasks, fan-out items, loop rounds, semantic retries, and evidence size, all inside the script. The invocation-level limits are not that place. `maxAgents` (1000), `concurrency` (the host's pool, and 16 only when it publishes none, clamped either way to 64), `agentRetries` (0) and `agentTimeoutMs` (1800000ms, `null` to disable) are tuned defaults, and `tokenBudget` is unlimited unless set; each one stops or fails a run that outgrows it, so a precautionary value removes coverage rather than cost. Pass one only when the user asked for that limit — a `maxAgents` under the script's own dispatch count ends the run with `AGENT_LIMIT_EXCEEDED` partway, and an `agentTimeoutMs` shorter than the host's turn/tool/token budget fails a whole fan-out as timeouts. A journal replay is logical work and does not consume the real-dispatch `maxAgents` cap, but it still counts toward reported call totals. If the user does ask for a token cap, allow for every planned agent call, retry, synthesis, and verification pass, with headroom: a tight gate terminates coverage and does not reduce work already in flight.
6
+
7
+ `concurrency` needs no value at all: it defaults to the host's pi-subagents `maxConcurrent`, read live at each start and resume, and a larger request is clamped to it (the run log records the clamp). Dispatching wider would not run wider — a workflow agent takes one of those background slots like any other, so the surplus would only wait in the host's queue, ahead of the host's own spawns. Name a number here only to run *narrower* than the host allows, and only when the user asked for that.
8
+
9
+ That pool is typically small — 4 slots unless the host was configured otherwise — so assume a wide fan-out runs in waves, not all at once. This does not change how wide to make it: the agents all run either way, and the reason to split work is coverage rather than wall-clock. It does mean a script should not promise the user a fast answer because it fanned out, and should not add a checkpoint or a progress phase that only makes sense if everything starts together.
6
10
 
7
11
  Enter a phase budget with `phase("Name", { budget: N })`; phase metadata does not carry budgets. `N` is a token allowance, not a call or round count: size it for the intended agent work instead of copying a small iteration limit. Token and phase budgets are soft pre-call gates. Spend lands after agents finish, so concurrent work can overshoot. A phase budget gates later calls in that phase; it neither reserves tokens nor cancels active calls. `budget.spent()` and `budget.remaining()` include nested work.
8
12
 
@@ -30,7 +30,10 @@ Review author-visible behavior, not formatting preferences. When behavior depend
30
30
  ## Lifecycle
31
31
 
32
32
  - Are runtime retries and semantic retries separately bounded?
33
- - Are loops, agents, concurrency, timeout, and token spend bounded appropriately?
33
+ - Are loops, graph tasks, fan-out items, and semantic retries bounded inside the script, where the topology is decided?
34
+ - Does the invocation leave `maxAgents`, `concurrency`, `agentRetries`, `tokenBudget` and `agentTimeoutMs` at their defaults unless the user asked for that limit? A precautionary value there removes coverage, not cost.
35
+ - Is the fan-out as wide as the evidence the task has, rather than narrowed by habit?
36
+ - Does `high` appear only on a step whose error is expensive to reverse — normally nowhere, at most once — rather than across a fan-out?
34
37
  - Are budget claims honest about soft gates and in-flight overshoot?
35
38
  - Are checkpoints limited to implemented confirmation/headless behavior?
36
39
  - Does nesting stay one level, allow only safe sibling concurrency, and account for shared limits/store?
@@ -2,7 +2,7 @@
2
2
  name: workflow-patterns
3
3
  description: Choose and run one of Pi's built-in multi-agent workflows for research, adversarial review, code review, multi-perspective analysis, or codebase auditing. Use when the request matches a named pattern; use workflow-authoring instead for a new script or custom topology.
4
4
  metadata:
5
- version: "1.6.0"
5
+ version: "1.7.1"
6
6
  ---
7
7
 
8
8
  # Built-in workflow patterns
@@ -2,7 +2,7 @@
2
2
  name: workflow-review
3
3
  description: Audit an existing Pi JavaScript workflow for topology, prompt/data flow, limits, failure handling, cancellation, resume safety, and publication compatibility. Use when reviewing or debugging a workflow script or saved run; do not use to run a standard named workflow.
4
4
  metadata:
5
- version: "1.6.0"
5
+ version: "1.7.1"
6
6
  ---
7
7
 
8
8
  # Workflow review
@@ -25,9 +25,11 @@ they are available.
25
25
  values and their bounds. Confirm that structured fields have a schema and
26
26
  that failed/null results remain visible in a ledger.
27
27
  4. **Check admission.** Verify finite bounds for task count, fan-out, loops,
28
- retries, concurrency, token budget, timeout, and evidence size. Check that
29
- a graph validates IDs, references, duplicate edges, and cycles before any
30
- callback runs.
28
+ retries, and evidence size inside the script, and that the invocation leaves
29
+ `maxAgents`, `concurrency`, `tokenBudget` and `agentTimeoutMs` at their
30
+ defaults unless the user asked for that limit — a precautionary value there
31
+ removes coverage rather than cost. Check that a graph validates IDs,
32
+ references, duplicate edges, and cycles before any callback runs.
31
33
  5. **Check failure policy.** Distinguish recoverable child `null` from fatal
32
34
  workflow errors. For graphs, verify whether the default
33
35
  `skip-dependents`, explicit `continue`, or `fail-fast` policy matches the
@@ -63,7 +63,7 @@ export const WORKFLOW_CAPABILITIES: readonly CapabilityEntry[] = [
63
63
  { name: "toolset", kind: "string", optional: true, default: "configured host/agent toolset hint" },
64
64
  { name: "excludeTools", kind: "string[]", optional: true, default: "none" },
65
65
  { name: "agentType", kind: "string", optional: true, default: "general-purpose" },
66
- { name: "timeoutMs", kind: "number | null", optional: true, default: "300000 (5min); null disables" },
66
+ { name: "timeoutMs", kind: "number | null", optional: true, default: "1800000 (30min); null disables" },
67
67
  { name: "retries", kind: "number", optional: true, default: "run retry count" },
68
68
  ],
69
69
  constraints: [
@@ -284,9 +284,15 @@ export const WORKFLOW_CAPABILITIES: readonly CapabilityEntry[] = [
284
284
  {
285
285
  name: "concurrency",
286
286
  classification: "workflow-tool-input",
287
- signature: "concurrency?: number",
287
+ signature: "concurrency?: number = the host's pi-subagents maxConcurrent",
288
288
  options: [],
289
- constraints: ["runtime clamps to 1..16"],
289
+ constraints: [
290
+ "runtime clamps to 1..64",
291
+ "read live from the peer at each start and resume, and also the ceiling: a request above the pool is clamped to it, and the run log records the clamp",
292
+ "16 is only the fallback for a peer that publishes no pool size",
293
+ "pi-subagents maxConcurrent stays the authoritative throttle; one setting governs the whole fleet",
294
+ "that pool is typically small (4 slots by default), so a wide fan-out runs in waves rather than all at once",
295
+ ],
290
296
  },
291
297
  {
292
298
  name: "agentRetries",
@@ -298,9 +304,13 @@ export const WORKFLOW_CAPABILITIES: readonly CapabilityEntry[] = [
298
304
  {
299
305
  name: "agentTimeoutMs",
300
306
  classification: "workflow-tool-input",
301
- signature: "agentTimeoutMs?: number = 300000",
307
+ signature: "agentTimeoutMs?: number = 1800000",
302
308
  options: [],
303
- constraints: ["null disables the hard timeout; default 300000ms (5min)"],
309
+ constraints: [
310
+ "null disables the hard timeout; default 1800000ms (30min)",
311
+ "it bounds a hang only; an agent's real budget is the host's turn, tool and token ceiling",
312
+ "the clock restarts when the host reports the agent left its queue, so waiting for a slot is not charged as work",
313
+ ],
304
314
  },
305
315
  {
306
316
  name: "tokenBudget",