@signalridge/pi-workflows 1.3.2 → 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.
@@ -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: `1.0.0`<br>
5
- Contract content / skill / extension: `1.3.2`
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
- - `model`: string (optional); default: pi-subagents model resolver
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
@@ -28,8 +27,11 @@ Every exact fact below is projected from the installed extension's capability co
28
27
  - Constraint: recoverable failures return null after retries; nonrecoverable failures throw
29
28
  - Constraint: schema noncompliance after bounded repair attempts is nonrecoverable
30
29
  - Constraint: resume replays only the longest unchanged prefix; the first miss and every later call execute live
30
+ - Constraint: replayed calls do not consume the real-dispatch maxAgents or token/phase budgets
31
31
  - Constraint: spawnKeys rotate by generation on resume so pi-subagents never raises a fingerprint conflict
32
- - Constraint: explicit model is resolved and scope-checked by pi-subagents; unavailable selectors fail closed
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
33
35
  - Constraint: same-thread calls must be sequential and preserve a stable workflow thread name
34
36
  - Constraint: threads cannot be combined with worktree isolation
35
37
 
@@ -41,8 +43,9 @@ Every exact fact below is projected from the installed extension's capability co
41
43
  - Signature: `parallel(thunks) => Promise<Array<unknown \| null>>`
42
44
  - Constraint: requires functions rather than promises
43
45
  - Constraint: result order matches input order
44
- - Constraint: recoverable thunk failures become null; nonrecoverable failures throw
46
+ - Constraint: recoverable thunk failures become null; nonrecoverable failures throw after the batch barrier settles
45
47
  - Constraint: a breached agent cap cancels only its own batch
48
+ - Constraint: accepts at most 4096 thunks per call
46
49
 
47
50
  <a id="runtime-global-pipeline"></a>
48
51
  ## pipeline
@@ -53,6 +56,21 @@ Every exact fact below is projected from the installed extension's capability co
53
56
  - Constraint: items run concurrently while stages per item run sequentially
54
57
  - Constraint: each stage receives previousValue, originalItem, and zero-based index
55
58
  - Constraint: a null stage result is passed to the next stage
59
+ - Constraint: accepts at most 4096 items per call and awaits the whole batch before surfacing fatal errors
60
+
61
+ <a id="runtime-global-orchestrate"></a>
62
+ ## orchestrate
63
+
64
+ - Classification: `runtime-global`
65
+ - Support: `supported`
66
+ - Signature: `orchestrate(tasks, options?) => Promise<{ results, tasks }>`
67
+ - `onError`: "skip-dependents"\|"continue"\|"fail-fast" (optional); default: "skip-dependents"
68
+ - Constraint: task ids and dependencies are validated before any callback runs
69
+ - Constraint: ready tasks run in declaration-order layers with a barrier between layers
70
+ - Constraint: task context carries detached named results and statuses
71
+ - Constraint: ordinary task failures can retry up to three times; fatal workflow errors propagate
72
+ - Constraint: failed or skipped dependencies skip descendants by default; continue runs them with null values
73
+ - Constraint: the graph accepts at most 128 tasks and emits task start/retry/end/skip runtime events
56
74
 
57
75
  <a id="runtime-global-workflow"></a>
58
76
  ## workflow
@@ -60,9 +78,9 @@ Every exact fact below is projected from the installed extension's capability co
60
78
  - Classification: `runtime-global`
61
79
  - Support: `supported`
62
80
  - Signature: `workflow(savedName, childArgs?) => Promise<unknown>`
63
- - Constraint: one nested level
81
+ - Constraint: one nested level; concurrent sibling nested calls are allowed
64
82
  - Constraint: shares limiter, counters, token accounting, and store
65
- - Constraint: nested runs get unique runIds via nestedCallSeq
83
+ - Constraint: nested calls use call-index/generation namespaces and replay as one parent result
66
84
 
67
85
  <a id="runtime-global-verify"></a>
68
86
  ## verify
@@ -270,6 +288,7 @@ Every exact fact below is projected from the installed extension's capability co
270
288
  - Support: `supported`
271
289
  - Signature: `resumeFromRunId?: string`
272
290
  - Constraint: resumes a prior incomplete run with an edited script
291
+ - Constraint: original args and execution limits are reused on resume
273
292
  - Constraint: unchanged positional calls replay from cache until the first changed call
274
293
  - Constraint: always runs in the background
275
294
 
@@ -281,6 +300,7 @@ Every exact fact below is projected from the installed extension's capability co
281
300
  - Signature: `export const meta = { name, description, phases? }`
282
301
  - Constraint: must be the first statement
283
302
  - Constraint: name and description must be nonblank literals
303
+ - Constraint: workflow meta and phase metadata cannot contain model or thinking fields
284
304
  - Constraint: spread, computed keys, methods, template interpolation, and __proto__/constructor/prototype are rejected
285
305
 
286
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 | A higher-priority selector overrides the expected route | [registry ownership](registry-ownership.md#priority) |
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,6 +4,7 @@ Read only the recipe matching the concern. Change task prompts, schemas, bounds,
4
4
 
5
5
  | Concern | Preserve when adapting | Tested recipe |
6
6
  | --- | --- | --- |
7
+ | Named dependencies | Validate stable task IDs before dispatch; use the default skip policy unless dependents can consume `statuses` and null results. | [Named task graph](../examples/named-task-graph.js) |
7
8
  | Phased budgets | Phase and run budgets are soft pre-call gates; active work can overshoot. Report shared spend and bound calls independently. | [Phased budgets](../examples/phased-budgets.js) |
8
9
  | Saved workflows | Use a context-supplied name, await jobs sequentially, nest one level, and treat shared limits, counters, tokens, limiter, and store as parent capacity. | [Saved nested workflows](../examples/saved-nested-workflows.js) |
9
10
  | Semantic retry | Separate it from recoverable runtime retries. Use a new unique label per bounded attempt and return the attempt ledger plus exhausted outcome. | [Bounded semantic retry](../examples/bounded-semantic-retry.js) |
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## Bounds and budget
4
4
 
5
- Set finite bounds that match the work for `maxAgents`, `concurrency`, and `agentRetries`; bound loops and semantic retries inside the script. 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
+ 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.
6
6
 
7
7
  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
8
 
@@ -22,9 +22,9 @@ Always retain `{ id, status, result }` or an equivalent ledger for each intended
22
22
 
23
23
  ## Resume
24
24
 
25
- Resume replays only the longest unchanged prefix of journaled calls. Once one call is new, changed, or unusable, that call and all later calls execute live. Stable lexical call ordering, prompts, labels, routing options, and inputs therefore matter. Retry chains can cascade after an upstream miss. Nested workflows do not reuse the parent's resume journal.
25
+ Resume replays only the longest unchanged prefix of journaled calls. Once one call is new, changed, or unusable, that call and all later calls execute live. Stable lexical call ordering, prompts, labels, routing options, and inputs therefore matter. Retry chains can cascade after an upstream miss. A nested workflow is cached as one parent call; an unchanged child replays its complete result, while a changed or interrupted child runs live in a generation-scoped namespace.
26
26
 
27
- Only a call that finishes with a real result is journaled. A call whose every attempt was recoverable (including one that only ever produced `AGENT_EMPTY_OUTPUT`) contributes no journal entry, so resuming that run reruns exactly that call and everything lexically after it live; the earlier, already-succeeded prefix still replays from cache.
27
+ Only a call that finishes with a real result is journaled. A call whose every attempt was recoverable (including one that only ever produced `AGENT_EMPTY_OUTPUT`) contributes no journal entry, so resuming that run reruns exactly that call and everything lexically after it live; the earlier, already-succeeded prefix still replays from cache. Schema repair retries include the concrete validation errors in the next prompt.
28
28
 
29
29
  The runtime blocks common accidental nondeterminism, but this is not a security boundary. Pass timestamps, randomness, and external decisions through `args`.
30
30
 
@@ -5,6 +5,7 @@ Choose from data dependencies, then read only the matching example. JavaScript o
5
5
  <a id="fan-out-and-synthesize"></a>
6
6
  | Dependency shape | Pattern | Preserve when adapting | Example |
7
7
  | --- | --- | --- | --- |
8
+ | Named steps have explicit dependencies | Named task graph | Give every task a stable ID; let `orchestrate()` validate cycles, run declaration-order layers, and pass named results/statuses to dependents | [Adapt](../examples/named-task-graph.js) |
8
9
  | Heterogeneous items need different handling | Classify and act | Finish all classification before routed action; ledger classification and action failures by item ID | [Adapt](../examples/classify-and-act.js) |
9
10
  | Independent work needs whole-set judgment | Fan out and synthesize | Pass thunks; await the full set; give synthesis every intended ID, including `null` | [Adapt](../examples/fan-out-and-synthesize.js) |
10
11
  | Claims need skeptical checks | Adversarial verification | Use separate producer and skeptic calls; start skepticism after production; ledger both failures | [Adapt](../examples/adversarial-verification.js) |
@@ -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
- The `pi-subagents` workflow-tier settings own route names. Standard routes are `small`, `medium`, and `large`; use another route only when its name and purpose are supplied in context. A route is selected with `tier`. An exact user-requested model is selected with `model` and is resolved/scope-checked by pi-subagents.
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, model, 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.
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
- Routing priority is explicit `model` > named `tier` > phase/run model > pi-subagents agent configuration > parent session. Higher priority means selection, not "try this then fall back to the next selector." Avoid specifying competing selectors unless deliberately overriding a lower-priority default.
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 for explicit `model` and named tiers: pi-subagents reports the selector and does not silently run a different model. An omitted selector may inherit the parent session according to the companion's current settings.
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,23 +6,25 @@ 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
 
12
13
  ## Topology and identity
13
14
 
14
- - Does topology match dependencies: thunks for independent parallel work, stages for per-item pipelines, barriers before whole-set synthesis?
15
- - Is cardinality bounded before fan-out?
15
+ - Does topology match dependencies: `orchestrate` for named graphs, thunks for independent parallel work, stages for per-item pipelines, barriers before whole-set synthesis?
16
+ - Is cardinality bounded before graph construction and fan-out?
16
17
  - Is every agent label short and unique?
17
- - Are stable work-unit IDs retained beside ordered results?
18
+ - Are stable graph/work-unit IDs retained beside ordered results?
18
19
  - Are failed/null identities recorded before any filtering?
19
20
 
20
21
  ## Data and routing
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
- - Are `model`, `tier`, and `agentType` used according to selector priority?
25
- - Did every nonstandard route or agent type come from context with a name and purpose?
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
 
@@ -30,12 +32,15 @@ Review author-visible behavior, not formatting preferences. When behavior depend
30
32
  - Are loops, agents, concurrency, timeout, and token spend bounded appropriately?
31
33
  - Are budget claims honest about soft gates and in-flight overshoot?
32
34
  - Are checkpoints limited to implemented confirmation/headless behavior?
33
- - Does nesting stay one level and account for shared limits/store?
34
- - Would lexical call order remain stable under resume?
35
+ - Does nesting stay one level, allow only safe sibling concurrency, and account for shared limits/store?
36
+ - Are helper attempts and graph retries finite and separately visible?
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?
35
39
 
36
40
  ## Compatibility and publication
37
41
 
38
42
  - Does new code use `log()` rather than compatibility-only `console`?
43
+ - Are runtime progress events and background result delivery described without promising durability the engine does not provide?
39
44
  - Is compatibility behavior clearly distinguished from supported authoring behavior and VM substrate?
40
45
  - Do package, skill, and generated contract versions match?
41
46
  - Do all relative links resolve within the publishable package?
@@ -4,19 +4,20 @@ 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?, model? }] }`. Values are nonblank literals; declare only used phases and call `phase()` before each phase's work. 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.
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
- The runtime supplies `agent`, `parallel`, `pipeline`, `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.
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
 
11
11
  ## Topology
12
12
 
13
13
  - `parallel()` takes thunks, runs independent work, and preserves input order. Await the whole array before whole-set synthesis.
14
14
  - `pipeline()` runs stages sequentially per item while items proceed concurrently. Each stage receives `(previousValue, originalItem, index)` and forwards `null` to the next stage, so guard missing coverage first.
15
- - `workflow(name, childArgs?)` runs a context-supplied saved workflow. Nesting is one level and shares limits, counters, tokens, and store.
15
+ - `orchestrate()` is the preferred topology for named dependencies. Give each task a unique `id`, optional `dependsOn`, and a `run({ id, attempt, results, statuses })` callback. The runtime validates the graph, executes declaration-order ready layers behind barriers, and returns `{ results, tasks }`; use `onError: "continue"` only when a downstream task can handle failed dependencies.
16
+ - `workflow(name, childArgs?)` runs a context-supplied saved workflow. Nesting is one level, shares limits/counters/tokens/store, and journals the complete child result as one parent replay boundary.
16
17
 
17
18
  ## Data and failure
18
19
 
19
- Call `agent(prompt, { label, schema? })`; it returns text, a schema-validated value, or recoverable `null`. Nonrecoverable limit, validation, and budget failures throw. Record each intended work ID before filtering. A `null` means missing coverage, never a negative finding.
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.
20
21
 
21
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.
22
23
 
@@ -24,6 +25,6 @@ When JavaScript reads fields, pass a small plain JSON Schema. Schema noncomplian
24
25
 
25
26
  ## Routing and support
26
27
 
27
- Selector priority is explicit `model` > named `tier` > phase/run model > pi-subagents agent configuration > parent session. An unavailable explicit selector fails closed rather than silently choosing another model. Worktree isolation is also fail-closed and remains owned by pi-subagents. See [registry ownership](registry-ownership.md).
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).
28
29
 
29
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 dynamic model routes and agent types from destination context; static docs intentionally contain no live entries.
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.
@@ -1,51 +1,90 @@
1
1
  ---
2
2
  name: workflow-patterns
3
- description: Argument shapes for the 5 built-in workflow patterns — deep-research, adversarial-review, code-review, multi-perspective, codebase-audit — runnable via the `workflow` tool's `name` input, without slash-command syntax. Use for requests like "research X", "fact-check/adversarially review this", "review this diff/PR", "analyze from multiple perspectives", or "audit the codebase for Y". Not for authoring a new workflow script — see workflow-authoring.
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.2.1"
5
+ version: "1.5.0"
6
6
  ---
7
7
 
8
8
  # Built-in workflow patterns
9
9
 
10
- @signalridge/pi-workflows ships 5 curated, tested workflow patterns. Each is also a
11
- slash command (`/deep-research`, `/adversarial-review`, `/code-review`,
12
- `/multi-perspective`, `/codebase-audit`), but they are equally reachable from
13
- the `workflow` tool directly: call it with `name` set to the pattern name
14
- below and `args` matching its shape, instead of writing an equivalent script
15
- from scratch. Prefer this over authoring a new script whenever the request
16
- fits one of these shapes — the curated version is already reviewed and tested.
10
+ Use a built-in when its input shape matches the request. The built-ins are
11
+ reviewed scripts with bounded fan-out, structured intermediate results, and a
12
+ final aggregation step. Prefer them over writing a new script for a standard
13
+ research or review task.
17
14
 
18
- A project or user saved workflow of the same name always takes precedence
19
- over a built-in of that name — on the slash command, too.
15
+ ## Choose by task shape
20
16
 
21
- These 5 names are reachable only at the `workflow` tool's top-level `name`
22
- input, not via the in-script `await workflow(savedName, childArgs)` helper —
23
- that helper resolves saved workflows only. Calling `workflow('deep-research')`
24
- from inside a script fails as an unknown saved workflow; use the top-level
25
- `name` input instead.
17
+ | Request | Pattern | Input |
18
+ | --- | --- | --- |
19
+ | Investigate a question with cross-checked sources | `deep-research` | `{ question, angles?, minSupport? }` |
20
+ | Test a claim or task with skeptical reviewers | `adversarial-review` | `{ task, reviewers?, threshold? }` |
21
+ | Review a diff or change set from multiple angles | `code-review` | `{ diff, diffSource? }` |
22
+ | Compare a topic from independent viewpoints | `multi-perspective` | `{ topic, perspectives? }` |
23
+ | Assess codebase health, risk, and debt | `codebase-audit` | `{ scope?, root?, focus?, checks? }` |
26
24
 
27
- ## Patterns
25
+ Do not use a built-in for one direct question, one simple delegation, or a
26
+ custom dependency graph. Use the ordinary agent tool for small work and load
27
+ [workflow-authoring](../workflow-authoring/SKILL.md) for custom scripts.
28
28
 
29
- | `name` | When to reach for it | `args` |
30
- | --- | --- | --- |
31
- | `deep-research` | Research a question across the web with cross-checked sources | `{ question: string, angles?: number, minSupport?: number }` — `angles` (default 4) is the number of distinct search queries; `minSupport` (default 2) is the minimum distinct sources required for a claim to survive cross-checking |
32
- | `adversarial-review` | Investigate a task/claim, then cross-check each finding with skeptical reviewers | `{ task: string, reviewers?: number, threshold?: number }` |
33
- | `code-review` | Multi-angle review of a diff (correctness, reuse, simplification, efficiency, altitude) | `{ diff: string, diffSource?: string }` — get `diff` yourself first (e.g. `git diff`, `gh pr diff <n>`); this path does not fetch it for you |
34
- | `multi-perspective` | Analyze a topic from several independent perspectives in parallel, then synthesize | `{ topic: string, perspectives?: string[] }` — omit or give fewer than 2 to use the default set (technical, product, security, user experience, maintainability) |
35
- | `codebase-audit` | Audit a codebase for health, risk, and debt across dimensions | `{ scope?: string, root?: string, focus?: string, checks?: string[] }` — `scope`/`root` chooses the directory and `focus`/`checks` refines what the agents inspect |
29
+ ## Invocation contract
36
30
 
37
- ## Example
31
+ The model-facing call is a `workflow` tool call, not JavaScript:
38
32
 
39
33
  ```json
40
- { "name": "deep-research", "args": { "question": "What are the tradeoffs of X vs Y?" } }
34
+ {
35
+ "name": "deep-research",
36
+ "args": { "question": "What are the trade-offs between X and Y?" },
37
+ "background": true
38
+ }
41
39
  ```
42
40
 
43
- This is a `workflow` tool call, not a script — omit `script` entirely. The run
44
- starts in the background exactly like the slash-command form; `background`,
45
- `maxAgents`, `concurrency`, `agentRetries`, `agentTimeoutMs`, and `tokenBudget`
46
- all still apply.
41
+ `name` resolves a saved workflow before the built-in. A saved workflow with the
42
+ same name intentionally overrides the built-in. Do not send `script` together
43
+ with `name`; choose one form. `background` defaults to `true`; use
44
+ `background: false` only when the caller needs the result inline or a human
45
+ checkpoint must be shown.
46
+
47
+ ## Input rules
48
+
49
+ - `deep-research` requires a non-empty `question`; `angles` and `minSupport`
50
+ should be small positive bounds appropriate to the question.
51
+ - `adversarial-review` requires a non-empty `task`; use reviewer counts and
52
+ thresholds that fit the risk rather than maximizing votes.
53
+ - `code-review` requires the actual diff. Obtain it first with the host's safe
54
+ diff path; do not ask the workflow to guess which files changed.
55
+ - `multi-perspective` requires a non-empty `topic`; provide at least two
56
+ distinct perspectives when overriding the defaults.
57
+ - `codebase-audit` accepts a scope/root and optional focus/check list. Keep the
58
+ scope narrow enough that every worker can inspect it and cite concrete paths.
59
+
60
+ ## Result and recovery rules
61
+
62
+ Every built-in returns a bounded aggregate of successful intermediate results
63
+ and a final report. Failed worker calls can remain `null` or be omitted from that
64
+ aggregate, but stay visible in run details. A background call returns a run ID
65
+ immediately; inspect it with `workflow_control` (`get`, `pause`, `resume`, or
66
+ `stop`) rather than starting a duplicate run. If a provider limit pauses the run, resume the same
67
+ run after the configured retry window. A changed script or saved workflow
68
+ replays only its unchanged journal prefix, so preserve the original inputs when
69
+ resuming.
70
+
71
+ Inspect run details for missing or `null` worker results before treating the
72
+ aggregate as complete. State when sources, review angles, or audit dimensions
73
+ were unavailable; a settled workflow may still contain incomplete evidence.
74
+
75
+ ## Built-in topology summary
47
76
 
48
- ## Writing a new workflow instead
77
+ - Research plans queries, gathers them concurrently, cross-checks claims, then
78
+ writes a cited report.
79
+ - Adversarial review separates finding generation from skeptical verification
80
+ before consensus.
81
+ - Code review fans out correctness, reuse, simplification, efficiency,
82
+ architecture, security, and testability lenses, then verifies candidates
83
+ before ranking them.
84
+ - Multi-perspective analysis runs independent views behind a barrier before
85
+ synthesis.
86
+ - Codebase audit maps structure first, then runs bounded dimension audits before
87
+ its roadmap.
49
88
 
50
- If the request doesn't fit one of these 5 shapes, author a script with
51
- `script` as usual — see the workflow-authoring skill.
89
+ When a built-in needs a dependency beyond these shapes, author a custom
90
+ `orchestrate()` graph instead of adding hidden assumptions to a built-in.
@@ -0,0 +1,70 @@
1
+ ---
2
+ name: workflow-review
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
+ metadata:
5
+ version: "1.5.0"
6
+ ---
7
+
8
+ # Workflow review
9
+
10
+ Review the workflow as an executable orchestration program, not as prose. The
11
+ review is read-only unless the user explicitly asks for a fix. Report concrete
12
+ failure scenarios and evidence; do not recommend extra agents merely because
13
+ they are available.
14
+
15
+ ## Review procedure
16
+
17
+ 1. **Identify the boundary.** Read the complete script, its invocation `args`,
18
+ saved-workflow source if applicable, and the relevant package version. Do not
19
+ infer behavior from a truncated run notification.
20
+ 2. **Map the topology.** List every work unit and its stable ID. Mark each as a
21
+ direct call, `orchestrate` task, `parallel` item, `pipeline` stage, loop
22
+ round, quality helper, checkpoint, or nested workflow. Draw the dependency
23
+ edges and barriers in declaration order.
24
+ 3. **Trace data flow.** For every downstream prompt, identify the exact input
25
+ values and their bounds. Confirm that structured fields have a schema and
26
+ that failed/null results remain visible in a ledger.
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.
31
+ 5. **Check failure policy.** Distinguish recoverable child `null` from fatal
32
+ workflow errors. For graphs, verify whether the default
33
+ `skip-dependents`, explicit `continue`, or `fail-fast` policy matches the
34
+ task. Ensure ordinary task retries do not silently duplicate side effects.
35
+ 6. **Check lifecycle.** Verify every batch is awaited, cancellation stops
36
+ owned work, checkpoints have a headless behavior, and nested workflows stay
37
+ within one level and shared capacity.
38
+ 7. **Check resume.** Keep call order, labels, prompts, routing options, and
39
+ inputs stable. Confirm that edited or missing calls invalidate downstream
40
+ replay and that nested results use a generation-scoped boundary. Treat
41
+ effectful worktree/file changes as non-replayable unless its effects are
42
+ explicitly restored.
43
+ 8. **Check publication.** Confirm the literal meta envelope, no imports or
44
+ nondeterministic APIs, safe relative links, current capability facts, and
45
+ an appropriate changeset when shipped package files changed.
46
+
47
+ ## Output format
48
+
49
+ Rank findings by severity and include:
50
+
51
+ - `file:line` or the task ID;
52
+ - the concrete input or lifecycle sequence that triggers it;
53
+ - the incorrect or risky behavior;
54
+ - the smallest safe fix;
55
+ - whether it blocks correctness, loses coverage, wastes tokens, or is only a
56
+ documentation concern.
57
+
58
+ End with a short topology summary and a list of verified strengths. If no
59
+ finding is reproducible, say so and state which paths were checked.
60
+
61
+ ## References
62
+
63
+ - Use [the review checklist](../workflow-authoring/references/review.md) for
64
+ the compact acceptance gate.
65
+ - Use [lifecycle](../workflow-authoring/references/lifecycle.md) for pause,
66
+ stop, budget, retry, and resume semantics.
67
+ - Use [debugging](../workflow-authoring/references/debugging.md) to reduce a
68
+ failure to a deterministic fake-agent reproduction.
69
+ - Use [the generated capability index](../workflow-authoring/references/capabilities.md)
70
+ only when a signature or support boundary is disputed.