@signalridge/pi-workflows 1.4.0 → 1.5.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/CHANGELOG.md +135 -0
- package/README.md +54 -12
- package/package.json +3 -3
- package/skills/workflow-authoring/SKILL.md +11 -6
- package/skills/workflow-authoring/references/capabilities.md +3 -3
- package/skills/workflow-authoring/references/capability-details.md +7 -5
- package/skills/workflow-authoring/references/debugging.md +2 -2
- package/skills/workflow-authoring/references/registry-ownership.md +6 -4
- package/skills/workflow-authoring/references/review.md +5 -2
- package/skills/workflow-authoring/references/runtime.md +3 -3
- package/skills/workflow-authoring/references/versions.md +1 -1
- package/skills/workflow-patterns/SKILL.md +1 -1
- package/skills/workflow-review/SKILL.md +1 -1
- package/src/builtins.ts +23 -23
- package/src/capabilities.ts +11 -4
- package/src/engine.ts +238 -58
- package/src/index.ts +292 -150
- package/src/journal.ts +292 -253
- package/src/rpc-client.ts +37 -48
- package/src/runtime.ts +176 -44
- package/src/ui.ts +29 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,140 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.5.0
|
|
4
|
+
### Minor Changes
|
|
5
|
+
|
|
6
|
+
- c1b1741: Protocol v4: workflows use the Agent-tier catalogue directly.
|
|
7
|
+
|
|
8
|
+
The wire contract changes, so the three packages move together: `pi-workflows`
|
|
9
|
+
now declares `"@signalridge/pi-subagents": ">=1.9.0"`, and a peer outside that
|
|
10
|
+
range fails the startup handshake with a diagnostic naming both packages rather
|
|
11
|
+
than failing mid-run.
|
|
12
|
+
|
|
13
|
+
The `small | medium | large` workflow-tier vocabulary and its mapping layer are
|
|
14
|
+
gone. A managed request names an Agent tier — a key in the host's own
|
|
15
|
+
`agentTiers` catalogue — and `resolveAgentTier()` is the single resolver for
|
|
16
|
+
every spawn path. Removed with it: the wire's mapped `agentTier` field, the
|
|
17
|
+
`workflow` settings key (retired with a warning naming it; `agentTiers.defaultTier`
|
|
18
|
+
replaces `workflow.defaultTier`), and the per-call `model`/`thinking` selectors,
|
|
19
|
+
which the validator now rejects rather than accepting and ignoring.
|
|
20
|
+
|
|
21
|
+
Every v4 capability is required and every ping carries the host's tier catalogue,
|
|
22
|
+
so an incomplete peer fails one check instead of five optional ones. Fresh
|
|
23
|
+
installs ship `low`/`medium`/`high` profiles, all inheriting their model, and a
|
|
24
|
+
managed call that names no tier falls back to `medium`, so a workflow runs on an
|
|
25
|
+
unconfigured machine without this package choosing a vendor. Because `medium`
|
|
26
|
+
inherits, that fallback lands on the parent session's model — it commits to an
|
|
27
|
+
effort level, not to a vendor, so it does change the thinking level a managed
|
|
28
|
+
call runs at when the parent session is set higher, and it does not move the
|
|
29
|
+
work anywhere cheaper. What it buys is a named policy with a durable snapshot
|
|
30
|
+
and a scope check; a workspace that wants cheaper managed work names a
|
|
31
|
+
`defaultTier` whose profile pins a model. The fallback is scoped to calls that
|
|
32
|
+
cannot inherit a parent model rather than being installed as
|
|
33
|
+
`agentTiers.defaultTier`: a shipped catalogue default would have applied to
|
|
34
|
+
every ordinary `Agent` spawn as well, silencing `defaultModel` and pinning a
|
|
35
|
+
thinking level on machines that configured neither. The catalogue no longer
|
|
36
|
+
ships a `fast` profile; it was the same (model, thinking) pair as `low`, and the
|
|
37
|
+
one agent that named it (Explore) now names `low`. A user agent file that still
|
|
38
|
+
says `agentTier: fast` is reported by the existing unknown-reference check when
|
|
39
|
+
settings and agents load, rather than failing at its first spawn.
|
|
40
|
+
|
|
41
|
+
`agentTiers.defaultTier` therefore has three states, and `/agents → Settings`
|
|
42
|
+
offers all three rather than rendering two of them as one word: a named tier,
|
|
43
|
+
`unset` (managed calls reach the shipped fallback), and `none` (recorded as
|
|
44
|
+
`noDefaultTier`, which withdraws the fallback so managed calls fail closed).
|
|
45
|
+
`setDefaultAgentTier` takes that choice as a tagged value, so a caller cannot
|
|
46
|
+
express "no default" without saying which of the two it means.
|
|
47
|
+
|
|
48
|
+
`resolveAgentTier` gained `requireTier` for that fallback, and the two things
|
|
49
|
+
pre-resolution callers need are both answered by the resolver rather than
|
|
50
|
+
restated beside it: `agentTierApplies()` for "will a tier own this spawn's
|
|
51
|
+
model?", and `selectAgentTier()` for the tier key itself, which the managed
|
|
52
|
+
path needs to label a tombstone and the lifecycle events before the runner has
|
|
53
|
+
resolved anything.
|
|
54
|
+
|
|
55
|
+
Because a tier now owns model resolution outright, the spawn paths stop
|
|
56
|
+
pre-resolving one — and with it they stopped producing the model name the agent
|
|
57
|
+
UI shows. The resolution callback carries that label back instead, so a tier
|
|
58
|
+
that pins a model still names it in the viewer and the agent list, and a profile
|
|
59
|
+
that inherits correctly shows none. The label rides beside the snapshot rather
|
|
60
|
+
than inside it: the snapshot is a durable policy record a managed tombstone
|
|
61
|
+
persists and revalidates, and a cosmetic string does not belong in it.
|
|
62
|
+
|
|
63
|
+
Workflow resume now keys each cached call on the policy for that call's own tier
|
|
64
|
+
rather than on a whole-catalogue fingerprint, so defining or editing an unrelated
|
|
65
|
+
tier no longer forces a full re-execution — but only for a call that names its
|
|
66
|
+
tier. A call that names none keeps the whole-catalogue key, because the host
|
|
67
|
+
resolves those as `call > agent frontmatter > defaultTier` and frontmatter is
|
|
68
|
+
not on this wire: an agent reaches a managed caller as a name. Keyed on
|
|
69
|
+
`defaultTier`, such a call would be wrong twice over — replaying stale work
|
|
70
|
+
after an edit to the tier its agent actually declares, and re-executing after an
|
|
71
|
+
edit to a default it never reached. `agentTierPolicyIdentity()` therefore
|
|
72
|
+
requires a tier rather than accepting `undefined` and folding the default in, so
|
|
73
|
+
the wrong call cannot be written. Journal schema v4 and managed tombstone schema
|
|
74
|
+
v2 are quarantined from older facts rather than migrated.
|
|
75
|
+
|
|
76
|
+
The tier catalogue belongs to the user, names included. The built-in workflows
|
|
77
|
+
and the ad-hoc script ship with this package, so a tier name they use that the
|
|
78
|
+
host does not define is dropped in favour of the host's default rather than
|
|
79
|
+
failing the run — they cannot assert which names exist on someone else's
|
|
80
|
+
machine. A script the user wrote still fails closed on an undefined tier, since
|
|
81
|
+
that is a typo in a catalogue they own. Shipped-ness travels with the script
|
|
82
|
+
rather than with the frame that called it, so a user script that reaches a
|
|
83
|
+
built-in through `workflow(name)` applies the built-in's rule to the built-in;
|
|
84
|
+
the authoring skill now says outright that `low`/`medium`/`high` are the shipped
|
|
85
|
+
profiles rather than names an authored script may assume.
|
|
86
|
+
|
|
87
|
+
The managed routing policy published on the wire reports the default a managed
|
|
88
|
+
call will actually get, fallback included, so a peer's replay identity cannot
|
|
89
|
+
disagree with the host's selection; its sorts are code-unit rather than
|
|
90
|
+
locale-dependent, so the same catalogue fingerprints identically everywhere. The
|
|
91
|
+
workflow peer re-pings per start and resume instead of pinning the catalogue it
|
|
92
|
+
saw at session start, and reports the host-selected tier back through an
|
|
93
|
+
`onTierResolved` callback rather than by mutating the dispatch options.
|
|
94
|
+
|
|
95
|
+
Fixes: a nested spawn no longer relabels an agent's frontmatter tier as
|
|
96
|
+
caller-requested, which had turned a `scopeModels` warning into a refusal and
|
|
97
|
+
misattributed the choice; the scheduler no longer freezes a frontmatter tier into
|
|
98
|
+
a job, so editing the agent file takes effect at fire time; retired managed spawn
|
|
99
|
+
keys are now bounded instead of growing for the life of a session; a
|
|
100
|
+
scope refusal for a tier whose profile inherits its model now names the model
|
|
101
|
+
that would have run instead of the literal `undefined`; and the retired
|
|
102
|
+
`workflow` key warns once per process rather than on every settings read and
|
|
103
|
+
every project write.
|
|
104
|
+
|
|
105
|
+
The tier-key predicate and its length bound now have a single definition, in
|
|
106
|
+
`pi-subagents-protocol`, which `pi-subagents` re-exports. The wire is the
|
|
107
|
+
narrower of the two gates — a key one accepted and the other rejected could
|
|
108
|
+
never reach a peer — so a second copy could only ever be a way for them to
|
|
109
|
+
disagree. That one definition now also governs `blockedProfiles`, which was
|
|
110
|
+
being validated by a helper that trims first: `" low"` became `"low"` there
|
|
111
|
+
while the same value in `profiles` or `defaultTier` was refused outright. All
|
|
112
|
+
three reject.
|
|
113
|
+
|
|
114
|
+
`/agents → Settings` no longer names the fallback tier in the `unset` row's
|
|
115
|
+
label. Which tier `unset` reaches depends on the catalogue, and a workspace that
|
|
116
|
+
edits or deletes the shipped `medium` profile leaves it reaching nothing — at
|
|
117
|
+
which point `unset` and `none` behave identically. The row's description asks
|
|
118
|
+
the resolver what `unset` would currently resolve to and says that, including
|
|
119
|
+
when the answer is "nothing".
|
|
120
|
+
|
|
121
|
+
`pi-workflows` also gained the session-lifecycle handling this routing work
|
|
122
|
+
needed to sit on. The engine has an explicit dispose lifecycle, so a protocol
|
|
123
|
+
probe or a start that is in flight when a session ends rejects with a disposed
|
|
124
|
+
error instead of resolving against an engine nobody owns. The tool, command and
|
|
125
|
+
widget surfaces register exactly once and resolve the *current* engine on each
|
|
126
|
+
use, rather than closing over the one that existed when they were registered —
|
|
127
|
+
a session replacement previously left them pointing at a disposed engine. Tool
|
|
128
|
+
and command handlers report failures as results rather than throwing out of the
|
|
129
|
+
host's dispatch, and the lifecycle handler accepts `subagents:created` and
|
|
130
|
+
`subagents:started` so a spawn's identity is recorded from the first event that
|
|
131
|
+
carries it rather than only at completion.
|
|
132
|
+
|
|
133
|
+
### Patch Changes
|
|
134
|
+
|
|
135
|
+
- Updated dependencies [c1b1741]
|
|
136
|
+
- @signalridge/pi-subagents-protocol@1.4.0
|
|
137
|
+
|
|
3
138
|
## 1.4.0
|
|
4
139
|
### Minor Changes
|
|
5
140
|
|
package/README.md
CHANGED
|
@@ -12,8 +12,8 @@ isolation, retry, and session policy.
|
|
|
12
12
|
|
|
13
13
|
## Install
|
|
14
14
|
|
|
15
|
-
`@signalridge/pi-workflows` requires `@signalridge/pi-subagents` `>=1.
|
|
16
|
-
with protocol
|
|
15
|
+
`@signalridge/pi-workflows` requires `@signalridge/pi-subagents` `>=1.9.0`
|
|
16
|
+
with protocol v4 managed-spawn, Agent-tier, and managed-policy support. They are separate Pi packages: the peer
|
|
17
17
|
dependency documents the requirement but intentionally does not auto-load or
|
|
18
18
|
duplicate the subagent extension.
|
|
19
19
|
|
|
@@ -54,9 +54,9 @@ export const meta = {
|
|
|
54
54
|
|
|
55
55
|
phase("scan");
|
|
56
56
|
const findings = await parallel([
|
|
57
|
-
() => agent("Check for cross-package imports", { label: "imports", tier: "
|
|
58
|
-
() => agent("Check for secrets", { label: "secrets", tier: "
|
|
59
|
-
() => agent("Check for dead code", { label: "dead-code", tier: "
|
|
57
|
+
() => agent("Check for cross-package imports", { label: "imports", tier: "low" }),
|
|
58
|
+
() => agent("Check for secrets", { label: "secrets", tier: "low" }),
|
|
59
|
+
() => agent("Check for dead code", { label: "dead-code", tier: "low" }),
|
|
60
60
|
]);
|
|
61
61
|
|
|
62
62
|
phase("synthesize");
|
|
@@ -77,15 +77,17 @@ user's own LLM and run on the user's own machine.
|
|
|
77
77
|
|
|
78
78
|
### Runtime globals
|
|
79
79
|
|
|
80
|
-
- `agent(prompt, { label, phase, schema,
|
|
80
|
+
- `agent(prompt, { label, phase, schema, tier, isolation, thread, agentType, toolset, excludeTools, timeoutMs, retries })`
|
|
81
81
|
— dispatch one subagent through the managed spawn protocol. Returns text, a
|
|
82
82
|
schema-validated value, or recoverable `null` after retries. Replayed journal
|
|
83
83
|
calls consume no real-dispatch cap or token/phase budget. `schema` is a
|
|
84
84
|
plain JSON Schema; the reply is parsed and validated client-side with bounded
|
|
85
85
|
repair across attempts, and exhaustion throws `SCHEMA_NONCOMPLIANCE`.
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
86
|
+
`tier` is the provider-neutral workflow route; `thread` chains sequential turns
|
|
87
|
+
within a named conversation thread. A legacy programmatic `model` option may
|
|
88
|
+
still be accepted by non-managed callers, but workflow meta/phase model or
|
|
89
|
+
thinking fields are rejected and are never a workflow policy source. Pre-schema-v4
|
|
90
|
+
journal runs are quarantined and cannot be resumed.
|
|
89
91
|
- `parallel(thunks)` — run thunks concurrently, preserve input order. Recoverable
|
|
90
92
|
thunk failures become `null`; non-recoverable failures (token budget, agent
|
|
91
93
|
limit) halt the run after the batch barrier settles. Fan-out that breaches
|
|
@@ -184,12 +186,52 @@ written atomically with a backup.
|
|
|
184
186
|
|
|
185
187
|
## Model routing
|
|
186
188
|
|
|
187
|
-
|
|
189
|
+
`tier` names a key in the host's own `agentTiers` catalogue — the same catalogue an
|
|
190
|
+
ordinary `Agent` call uses. There is no separate workflow-tier vocabulary and no
|
|
191
|
+
mapping layer: a workflow that wants cheap work asks for the tier the user defined
|
|
192
|
+
for cheap work.
|
|
193
|
+
|
|
194
|
+
```js
|
|
195
|
+
await agent("summarize this diff", { tier: "low" })
|
|
196
|
+
await agent("design the migration", { tier: "high" })
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
The host's catalogue arrives with the protocol handshake, so a tier this host does
|
|
200
|
+
not define is rejected before any dispatch, naming the ones it does. Resolution
|
|
201
|
+
itself is entirely pi-subagents' `resolveAgentTier()`: it owns the final model,
|
|
202
|
+
thinking level, clamping, availability checks, and the immutable resolution
|
|
203
|
+
snapshot.
|
|
204
|
+
|
|
205
|
+
The catalogue belongs to whoever runs the workflow — the names included. The
|
|
206
|
+
built-in workflows and the ad-hoc script ship with this package, so they cannot
|
|
207
|
+
assert that `low` exists on a machine whose tiers are called `cheap` and `deep`:
|
|
208
|
+
a name they use that the host does not define is dropped, with a log line, and
|
|
209
|
+
the host's own default applies. A script you wrote names tiers from your own
|
|
210
|
+
catalogue, so an undefined one there is a typo and fails closed instead.
|
|
211
|
+
|
|
212
|
+
There is no per-call `model` or `thinking`, and `meta`/phase metadata may not carry
|
|
213
|
+
them either — both are rejected explicitly rather than accepted and ignored. A tier
|
|
214
|
+
is the only model policy a workflow can express, which is what keeps a script from
|
|
215
|
+
pinning a vendor the host did not choose.
|
|
216
|
+
|
|
217
|
+
Omitting `tier` uses the agent's own tier, then `agentTiers.defaultTier`. Fresh
|
|
218
|
+
installs ship `low`/`medium`/`high` profiles, all inheriting their model, and a
|
|
219
|
+
managed call that still names no tier falls back to `medium` — so the built-ins run
|
|
220
|
+
on a new machine without any configuration. That fallback is scoped to managed
|
|
221
|
+
calls: it is not the catalogue's `defaultTier`, so an ordinary `Agent` spawn on the
|
|
222
|
+
same machine keeps falling through to `defaultModel` and the parent session. A host
|
|
223
|
+
whose default has been cleared (`noDefaultTier`) rejects an untiered managed call
|
|
224
|
+
rather than quietly inheriting the parent session's model.
|
|
225
|
+
|
|
226
|
+
The managed wire, invocation record, journal, tombstone, and resume state all carry
|
|
227
|
+
the one resolved tier — including one the host defaulted to, so a run's record says
|
|
228
|
+
what actually ran. Resume keys each cached call on the policy for *that call's*
|
|
229
|
+
tier: editing an unrelated tier does not invalidate work that never used it.
|
|
188
230
|
|
|
189
231
|
## Intentional adaptations from upstream
|
|
190
232
|
|
|
191
233
|
- **No host-side web tools.** Agents reach the web through configured pi-web-access/MCP tools or an agent type's tool policy.
|
|
192
|
-
- **Agent registry and tier catalogue ownership.** `agentType` and
|
|
234
|
+
- **Agent registry and tier catalogue ownership.** `agentType` and the tier catalogue resolve in pi-subagents; the workflow package supplies only a tier key, avoiding a second model/thinking policy.
|
|
193
235
|
- **Schema validation is client-side.** The managed request does not assume a structured-output tool; the runtime asks for JSON, parses, validates (including `additionalProperties`), and repairs across bounded attempts.
|
|
194
236
|
|
|
195
|
-
State is persisted as `pi.appendEntry("pi-workflows:journal", ...)` custom entries (schema
|
|
237
|
+
State is persisted as `pi.appendEntry("pi-workflows:journal", ...)` custom entries (schema v4), including frozen invocation args, resolved tier identity, terminal result previews, script revisions, named nested-workflow result boundaries, and durable removals. Interrupted/provider-limited runs replay from the journal; pre-schema-v4 journals are quarantined rather than replayed. Foreground `AbortSignal`s stop owned children through explicit owner-scoped stop/quiescence, and dispose/branch replacement reject stale waiters.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@signalridge/pi-workflows",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "Deterministic JavaScript orchestration workflows backed by pi-subagents managed spawning.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -17,10 +17,10 @@
|
|
|
17
17
|
"peerDependencies": {
|
|
18
18
|
"@earendil-works/pi-coding-agent": "^0.84.0",
|
|
19
19
|
"@earendil-works/pi-tui": "^0.84.0",
|
|
20
|
-
"@signalridge/pi-subagents": ">=1.
|
|
20
|
+
"@signalridge/pi-subagents": ">=1.9.0"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@signalridge/pi-subagents-protocol": "^1.
|
|
23
|
+
"@signalridge/pi-subagents-protocol": "^1.4.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.
|
|
5
|
+
version: "1.5.0"
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Workflow authoring
|
|
@@ -28,10 +28,13 @@ JavaScript.
|
|
|
28
28
|
- Bound graph tasks, fan-out items, loops, retries, agents, concurrency, and
|
|
29
29
|
evidence size. Invocation-level token and time caps are user constraints, not
|
|
30
30
|
substitutes for algorithmic bounds.
|
|
31
|
-
- Route an agent call with `tier: "
|
|
32
|
-
`tier`
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
- Route an agent call with `tier: "<key>"`, naming a tier the destination host
|
|
32
|
+
defines. Omitting `tier` uses the agent's own tier, then the host's configured
|
|
33
|
+
default; a host whose default has been cleared rejects the call rather than
|
|
34
|
+
inheriting the parent model. There is no per-call `model`/`thinking`, and
|
|
35
|
+
neither may appear in workflow meta or phase profiles. Never guess a tier or
|
|
36
|
+
agent-type name—use names supplied by the current environment and follow
|
|
37
|
+
[registry ownership](references/registry-ownership.md).
|
|
35
38
|
- Workflows have no imports, filesystem/network APIs, timers, or unrestricted
|
|
36
39
|
Node APIs. Pass timestamps, randomness, and external decisions through `args`.
|
|
37
40
|
|
|
@@ -173,6 +176,8 @@ Before shipping a workflow change:
|
|
|
173
176
|
- read [debugging](references/debugging.md) when reproducing a failure;
|
|
174
177
|
- read [the review checklist](references/review.md) before accepting topology;
|
|
175
178
|
- read [the generated capability index](references/capabilities.md) when a
|
|
176
|
-
signature, default, or support boundary is disputed;
|
|
179
|
+
signature, default, or support boundary is disputed; remember that a tier
|
|
180
|
+
names a key in the host catalogue while model/thinking resolution stays in
|
|
181
|
+
pi-subagents;
|
|
177
182
|
- ensure every package-relative example/reference link remains inside the
|
|
178
183
|
publishable package.
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<!-- GENERATED from WORKFLOW_CAPABILITY_CONTRACT; do not edit by hand. -->
|
|
2
2
|
# Workflow capability index
|
|
3
3
|
|
|
4
|
-
Contract format: `
|
|
5
|
-
Contract content / skill / extension: `1.
|
|
4
|
+
Contract format: `2.0.0`<br>
|
|
5
|
+
Contract content / skill / extension: `1.5.0`
|
|
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>`
|
|
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>`tier`: agent tier key (optional); default: 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 |
|
|
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" |
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<!-- GENERATED from WORKFLOW_CAPABILITY_CONTRACT; do not edit by hand. -->
|
|
2
2
|
# Exhaustive workflow capability facts
|
|
3
3
|
|
|
4
|
-
Contract format: `
|
|
5
|
-
Contract content / skill / extension: `1.
|
|
4
|
+
Contract format: `2.0.0`<br>
|
|
5
|
+
Contract content / skill / extension: `1.5.0`
|
|
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
|
|
|
@@ -16,8 +16,7 @@ Every exact fact below is projected from the installed extension's capability co
|
|
|
16
16
|
- `label`: string (optional); default: derived from phase and call count
|
|
17
17
|
- `phase`: string (optional); default: current phase
|
|
18
18
|
- `schema`: plain JSON Schema (optional)
|
|
19
|
-
- `
|
|
20
|
-
- `tier`: small\|medium\|large (optional); default: pi-subagents workflow tier
|
|
19
|
+
- `tier`: agent tier key (optional); default: the agent's own tier, else agentTiers.defaultTier
|
|
21
20
|
- `isolation`: "worktree" (optional); default: pi-subagents worktree policy
|
|
22
21
|
- `thread`: string (optional); default: fresh session per call
|
|
23
22
|
- `toolset`: string (optional); default: configured host/agent toolset hint
|
|
@@ -30,7 +29,9 @@ Every exact fact below is projected from the installed extension's capability co
|
|
|
30
29
|
- Constraint: resume replays only the longest unchanged prefix; the first miss and every later call execute live
|
|
31
30
|
- Constraint: replayed calls do not consume the real-dispatch maxAgents or token/phase budgets
|
|
32
31
|
- Constraint: spawnKeys rotate by generation on resume so pi-subagents never raises a fingerprint conflict
|
|
33
|
-
- Constraint:
|
|
32
|
+
- Constraint: tier names a key in the host's agentTiers catalogue; a key it does not define is rejected before dispatch
|
|
33
|
+
- Constraint: resolveAgentTier in pi-subagents owns model, thinking, clamping, availability, and the resolution snapshot
|
|
34
|
+
- Constraint: there is no per-call model or thinking: a tier is the only model policy a workflow can express
|
|
34
35
|
- Constraint: same-thread calls must be sequential and preserve a stable workflow thread name
|
|
35
36
|
- Constraint: threads cannot be combined with worktree isolation
|
|
36
37
|
|
|
@@ -299,6 +300,7 @@ Every exact fact below is projected from the installed extension's capability co
|
|
|
299
300
|
- Signature: `export const meta = { name, description, phases? }`
|
|
300
301
|
- Constraint: must be the first statement
|
|
301
302
|
- Constraint: name and description must be nonblank literals
|
|
303
|
+
- Constraint: workflow meta and phase metadata cannot contain model or thinking fields
|
|
302
304
|
- Constraint: spread, computed keys, methods, template interpolation, and __proto__/constructor/prototype are rejected
|
|
303
305
|
|
|
304
306
|
<a id="script-contract-determinism"></a>
|
|
@@ -8,7 +8,7 @@ Start from the symptom, then reproduce through the real workflow runtime with de
|
|
|
8
8
|
| `parallel()` rejects input | Promises were passed instead of thunks | [runtime](runtime.md#topology) |
|
|
9
9
|
| Synthesis starts early | Fan-out was not awaited as one complete result set | [pattern selection](pattern-selection.md#fan-out-and-synthesize) |
|
|
10
10
|
| Coverage silently disappears | `null` results were filtered before IDs were ledgered | [lifecycle](lifecycle.md#retry-and-recoverable-failure) |
|
|
11
|
-
| Wrong model is used |
|
|
11
|
+
| Wrong model or thinking is used | The call named no tier and fell to a default, or named one whose profile is not what you expected | [registry ownership](registry-ownership.md#priority) |
|
|
12
12
|
| Unknown `agentType` log | A live registry name was guessed or is unavailable | [registry ownership](registry-ownership.md#agent-types) |
|
|
13
13
|
| Budget exceeds the number shown | The budget is a soft pre-call gate and work was in flight | [lifecycle](lifecycle.md#bounds-and-budget) |
|
|
14
14
|
| Later calls rerun on resume | An earlier call missed or changed, ending the replayable prefix | [lifecycle](lifecycle.md#resume) |
|
|
@@ -23,7 +23,7 @@ Start from the symptom, then reproduce through the real workflow runtime with de
|
|
|
23
23
|
|
|
24
24
|
1. Reduce to the smallest script that preserves metadata, labels, work IDs, and the failing topology.
|
|
25
25
|
2. Replace provider calls with deterministic, schema-aware fake agents.
|
|
26
|
-
3. Record call order, labels, phases, prompts, results, and `null` entries.
|
|
26
|
+
3. Record call order, labels, phases, prompts, resolved tiers, results, and `null` entries.
|
|
27
27
|
4. When the failure turns on a disputed signature or default, compare it with the compact [capability index](capabilities.md); follow its exhaustive-facts pointer only when needed.
|
|
28
28
|
5. Separate runtime defects from unsupported authoring assumptions and compatibility-only behavior.
|
|
29
29
|
6. Fix only the demonstrated authoring issue; do not rely on known out-of-scope gaps in nested persistence, resume accounting, checkpoint forms/timeouts, metadata validation, or budget overshoot.
|
|
@@ -4,14 +4,16 @@ Model routes and agent types are dynamic references. Their shape and owner are d
|
|
|
4
4
|
|
|
5
5
|
## Model routes
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
pi-subagents owns the agent-tier catalogue; a workflow names a key from it and nothing else. Available tier names depend on active configuration and are intentionally absent from static skill files — read them from the destination context.
|
|
8
|
+
|
|
9
|
+
A name a script writes is not a claim that the name exists. Scripts that ship with this package name `low`/`medium`/`high` — the profiles a fresh install receives — and a host that does not define one of those drops it in favour of that host's default, with a log line. A script you write is held to the stricter rule: an undefined tier is a typo in a catalogue you own, so it is rejected before dispatch rather than rerouted. Write the tier you mean for the host you are targeting; do not copy `low`/`medium`/`high` in on the assumption that every machine has them.
|
|
8
10
|
|
|
9
11
|
## Agent types
|
|
10
12
|
|
|
11
|
-
The agent registry owns agent-type names and their bound instructions, tools,
|
|
13
|
+
The agent registry owns agent-type names and their bound instructions, tools, Agent-tier defaults, and isolation policy. Use `agentType` only when context supplies both its name and purpose. Do not infer an agent type from a role-like label.
|
|
12
14
|
|
|
13
15
|
## Priority
|
|
14
16
|
|
|
15
|
-
|
|
17
|
+
A call's `tier` takes precedence over an agent type's own tier default, which takes precedence over `agentTiers.defaultTier`. `resolveAgentTier()` in pi-subagents then resolves model, thinking, clamping, availability, and the immutable snapshot as one decision. Neither a call, nor workflow meta, nor a phase may carry model or thinking fields.
|
|
16
18
|
|
|
17
|
-
Unavailability is fail-closed
|
|
19
|
+
Unavailability is fail-closed: pi-subagents names the tier and does not silently run a different model. A managed call with no tier and no applicable default is rejected rather than inheriting the parent session.
|
|
@@ -6,6 +6,7 @@ Review author-visible behavior, not formatting preferences. When behavior depend
|
|
|
6
6
|
|
|
7
7
|
- Is literal `export const meta` the first statement, with a short unique name and useful description?
|
|
8
8
|
- Are only used phases declared, and does each named phase begin at the intended boundary?
|
|
9
|
+
- Are workflow meta and phase objects free of retired `model`/`thinking` fields?
|
|
9
10
|
- Does the script call at least one agent and explicitly return JSON-serializable data?
|
|
10
11
|
- Are imports and nondeterministic APIs absent?
|
|
11
12
|
|
|
@@ -21,8 +22,9 @@ Review author-visible behavior, not formatting preferences. When behavior depend
|
|
|
21
22
|
|
|
22
23
|
- Does JavaScript consume structured fields only after a small plain JSON Schema guarantees them?
|
|
23
24
|
- Does synthesis receive complete coverage and failure ledgers?
|
|
24
|
-
-
|
|
25
|
-
-
|
|
25
|
+
- Does every `tier` name a key the destination host actually defines, rather than a guessed one?
|
|
26
|
+
- Is the tier the only model/thinking policy source, via pi-subagents' `resolveAgentTier()`?
|
|
27
|
+
- Did every tier or agent-type name come from context with a name and purpose?
|
|
26
28
|
|
|
27
29
|
## Lifecycle
|
|
28
30
|
|
|
@@ -33,6 +35,7 @@ Review author-visible behavior, not formatting preferences. When behavior depend
|
|
|
33
35
|
- Does nesting stay one level, allow only safe sibling concurrency, and account for shared limits/store?
|
|
34
36
|
- Are helper attempts and graph retries finite and separately visible?
|
|
35
37
|
- Would lexical call order and generated graph order remain stable under resume?
|
|
38
|
+
- Does the journal/tombstone retain the resolved `tier`, including one the host defaulted to?
|
|
36
39
|
|
|
37
40
|
## Compatibility and publication
|
|
38
41
|
|
|
@@ -4,7 +4,7 @@ Use this page for routine scripts. Open the generated capability index only when
|
|
|
4
4
|
|
|
5
5
|
## Script envelope
|
|
6
6
|
|
|
7
|
-
Start with the only legal export: `export const meta = { name, description, phases?: [{ title, detail
|
|
7
|
+
Start with the only legal export: `export const meta = { name, description, phases?: [{ title, detail? }] }`. Values are nonblank literals; declare only used phases and call `phase()` before each phase's work. Workflow meta and phase objects must not contain `model` or `thinking`; those retired fields are rejected. The remaining body already runs inside an async function: write helpers as ordinary declarations; `export default` and other exports are invalid. Return the result explicitly.
|
|
8
8
|
|
|
9
9
|
The runtime supplies `agent`, `parallel`, `pipeline`, `orchestrate`, `workflow`, quality/control helpers, `phase`, `log`, `args`, `cwd`, restricted `process.cwd()`, and `budget`. Imports, `require()`, filesystem modules, `Date.now()`, `Math.random()`, and no-argument `new Date()` are unavailable. The Node VM realm is implementation substrate, not a security boundary or public API.
|
|
10
10
|
|
|
@@ -17,7 +17,7 @@ The runtime supplies `agent`, `parallel`, `pipeline`, `orchestrate`, `workflow`,
|
|
|
17
17
|
|
|
18
18
|
## Data and failure
|
|
19
19
|
|
|
20
|
-
Call `agent(prompt, { label, schema? })`; it returns text, a schema-validated value, or recoverable `null`. Nonrecoverable limit, validation, and
|
|
20
|
+
Call `agent(prompt, { label, schema?, tier? })`; it returns text, a schema-validated value, or recoverable `null`. `tier` names a key in the host's agent-tier catalogue. Nonrecoverable limit, validation, budget, unknown-tier, and unavailable-tier failures throw. Record each intended work ID before filtering. A `null` means missing coverage, never a negative finding.
|
|
21
21
|
|
|
22
22
|
Use `agent(prompt, { thread: "implementer" })` when the same managed subagent must receive a later follow-up with its complete conversation intact. Reuse a thread name sequentially; never put same-thread calls in one `parallel()` batch. Threads are scoped to one workflow run/session and cannot use worktree isolation. A pause or process restart may require a fresh thread session.
|
|
23
23
|
|
|
@@ -25,6 +25,6 @@ When JavaScript reads fields, pass a small plain JSON Schema. Schema noncomplian
|
|
|
25
25
|
|
|
26
26
|
## Routing and support
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
`tier` is a key in the host's agent-tier catalogue, not a model ID. The catalogue and its names belong to the user running the workflow; read the available keys from the destination context rather than assuming any particular name exists. A tier this host does not define is rejected before dispatch — only the scripts shipped with this package reroute to the host default instead, because they cannot know the catalogue they will land in. pi-subagents' `resolveAgentTier()` alone resolves the final model, thinking, clamping, availability, and snapshot. A tier the host does not define is rejected before dispatch. Omitting `tier` uses the agent's own tier, then `agentTiers.defaultTier`; a host whose default has been cleared rejects the call instead of inheriting the parent model. There is no per-call model or thinking, and workflow meta and phases may not carry them either. Worktree isolation remains owned by pi-subagents. See [registry ownership](registry-ownership.md).
|
|
29
29
|
|
|
30
30
|
Generated entries marked `supported` are authoring API. `console` and whole-script Markdown fences are compatibility-only. VM realm facilities are internal. Active model routes and agent types are dynamic. Use `log()` in new scripts.
|
|
@@ -9,5 +9,5 @@ When copying a workflow between installations:
|
|
|
9
9
|
1. Check the destination's generated version and exact capability facts.
|
|
10
10
|
2. Re-check every supported global, option, and constraint used by the script.
|
|
11
11
|
3. Treat compatibility entries as preservation aids, not portable recommendations.
|
|
12
|
-
4. Re-resolve
|
|
12
|
+
4. Re-resolve tier keys and agent types from destination context; both come from the destination host's configuration, and static docs intentionally contain no live catalogue entries.
|
|
13
13
|
5. Prefer runtime behavior when prose and execution disagree, and report the documentation mismatch rather than changing behavior during an authoring fix.
|
|
@@ -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.
|
|
5
|
+
version: "1.5.0"
|
|
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.
|
|
5
|
+
version: "1.5.0"
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Workflow review
|