pi-subagents 0.73.0 → 0.74.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 +65 -0
- package/README.md +1 -1
- package/docs/agents.md +18 -12
- package/docs/configuration.md +66 -9
- package/docs/extension-api.md +5 -4
- package/docs/missions.md +13 -13
- package/docs/models.md +2 -2
- package/docs/observability.md +2 -2
- package/docs/tool-reference.md +63 -86
- package/docs/workflows.md +165 -171
- package/package.json +2 -2
- package/prompts/review-loop.md +1 -1
- package/skills/council-mode/SKILL.md +1 -1
- package/skills/pi-subagents/SKILL.md +12 -5
- package/skills/pi-subagents/references/constraints-and-recipes.md +3 -3
- package/skills/pi-subagents/references/execution-controls.md +68 -67
- package/skills/pi-subagents/references/management-authoring-rpc.md +2 -2
- package/skills/pi-subagents/references/multi-lane-orchestration.md +1 -1
- package/skills/pi-subagents/references/prompting-and-roles.md +45 -48
- package/src/agents/advertised-agent-prompt.d.ts +6 -4
- package/src/agents/advertised-agent-prompt.d.ts.map +1 -1
- package/src/agents/advertised-agent-prompt.js +16 -30
- package/src/agents/advertised-agent-prompt.js.map +1 -1
- package/src/agents/agent-management.js +2 -2
- package/src/agents/agent-management.js.map +1 -1
- package/src/agents/agents.d.ts +1 -0
- package/src/agents/agents.d.ts.map +1 -1
- package/src/agents/agents.js +8 -0
- package/src/agents/agents.js.map +1 -1
- package/src/api/preflight.d.ts +5 -1
- package/src/api/preflight.d.ts.map +1 -1
- package/src/api/preflight.js +2 -1
- package/src/api/preflight.js.map +1 -1
- package/src/extension/config.d.ts.map +1 -1
- package/src/extension/config.js +12 -4
- package/src/extension/config.js.map +1 -1
- package/src/extension/control-notices.d.ts +2 -0
- package/src/extension/control-notices.d.ts.map +1 -1
- package/src/extension/control-notices.js +2 -0
- package/src/extension/control-notices.js.map +1 -1
- package/src/extension/doctor.d.ts.map +1 -1
- package/src/extension/doctor.js +1 -0
- package/src/extension/doctor.js.map +1 -1
- package/src/extension/fanout-child.d.ts.map +1 -1
- package/src/extension/fanout-child.js +13 -3
- package/src/extension/fanout-child.js.map +1 -1
- package/src/extension/herdr-pi-bridge.d.ts.map +1 -1
- package/src/extension/herdr-pi-bridge.js +2 -0
- package/src/extension/herdr-pi-bridge.js.map +1 -1
- package/src/extension/index.d.ts +1 -1
- package/src/extension/index.d.ts.map +1 -1
- package/src/extension/index.js +71 -169
- package/src/extension/index.js.map +1 -1
- package/src/extension/public-execution.d.ts +10 -1
- package/src/extension/public-execution.d.ts.map +1 -1
- package/src/extension/public-execution.js +69 -35
- package/src/extension/public-execution.js.map +1 -1
- package/src/extension/reply-workflow-script.d.ts +12 -0
- package/src/extension/reply-workflow-script.d.ts.map +1 -0
- package/src/extension/reply-workflow-script.js +61 -0
- package/src/extension/reply-workflow-script.js.map +1 -0
- package/src/extension/rpc.d.ts +2 -0
- package/src/extension/rpc.d.ts.map +1 -1
- package/src/extension/rpc.js +33 -10
- package/src/extension/rpc.js.map +1 -1
- package/src/extension/schemas.d.ts +3 -117
- package/src/extension/schemas.d.ts.map +1 -1
- package/src/extension/schemas.js +38 -125
- package/src/extension/schemas.js.map +1 -1
- package/src/extension/tool-activation.d.ts +2 -4
- package/src/extension/tool-activation.d.ts.map +1 -1
- package/src/extension/tool-activation.js +54 -104
- package/src/extension/tool-activation.js.map +1 -1
- package/src/extension/tool-description.d.ts +8 -5
- package/src/extension/tool-description.d.ts.map +1 -1
- package/src/extension/tool-description.js +51 -27
- package/src/extension/tool-description.js.map +1 -1
- package/src/extension/upgrade-notice.d.ts +7 -0
- package/src/extension/upgrade-notice.d.ts.map +1 -0
- package/src/extension/upgrade-notice.js +37 -0
- package/src/extension/upgrade-notice.js.map +1 -0
- package/src/integrations/herdr-status.d.ts +3 -0
- package/src/integrations/herdr-status.d.ts.map +1 -1
- package/src/integrations/herdr-status.js +17 -3
- package/src/integrations/herdr-status.js.map +1 -1
- package/src/intercom/native-supervisor-channel.d.ts.map +1 -1
- package/src/intercom/native-supervisor-channel.js +4 -1
- package/src/intercom/native-supervisor-channel.js.map +1 -1
- package/src/runs/background/async-execution.d.ts +3 -0
- package/src/runs/background/async-execution.d.ts.map +1 -1
- package/src/runs/background/async-execution.js +6 -2
- package/src/runs/background/async-execution.js.map +1 -1
- package/src/runs/background/async-job-tracker.d.ts.map +1 -1
- package/src/runs/background/async-job-tracker.js +65 -22
- package/src/runs/background/async-job-tracker.js.map +1 -1
- package/src/runs/background/async-retention.d.ts +1 -1
- package/src/runs/background/async-retention.d.ts.map +1 -1
- package/src/runs/background/async-retention.js +47 -15
- package/src/runs/background/async-retention.js.map +1 -1
- package/src/runs/background/await-async-run.d.ts +23 -0
- package/src/runs/background/await-async-run.d.ts.map +1 -0
- package/src/runs/background/await-async-run.js +80 -0
- package/src/runs/background/await-async-run.js.map +1 -0
- package/src/runs/background/chain-root-attachment.d.ts +1 -0
- package/src/runs/background/chain-root-attachment.d.ts.map +1 -1
- package/src/runs/background/chain-root-attachment.js +3 -3
- package/src/runs/background/chain-root-attachment.js.map +1 -1
- package/src/runs/background/control-channel.d.ts +4 -0
- package/src/runs/background/control-channel.d.ts.map +1 -1
- package/src/runs/background/control-channel.js +16 -1
- package/src/runs/background/control-channel.js.map +1 -1
- package/src/runs/background/notify.d.ts +3 -0
- package/src/runs/background/notify.d.ts.map +1 -1
- package/src/runs/background/notify.js +3 -0
- package/src/runs/background/notify.js.map +1 -1
- package/src/runs/background/run-child-session.d.ts.map +1 -1
- package/src/runs/background/run-child-session.js +4 -1
- package/src/runs/background/run-child-session.js.map +1 -1
- package/src/runs/background/run-status.d.ts.map +1 -1
- package/src/runs/background/run-status.js +6 -0
- package/src/runs/background/run-status.js.map +1 -1
- package/src/runs/background/runner-child-launch.d.ts +1 -0
- package/src/runs/background/runner-child-launch.d.ts.map +1 -1
- package/src/runs/background/runner-child-launch.js +2 -0
- package/src/runs/background/runner-child-launch.js.map +1 -1
- package/src/runs/background/scheduled-runs.js +5 -5
- package/src/runs/background/scheduled-runs.js.map +1 -1
- package/src/runs/background/subagent-runner.d.ts +3 -0
- package/src/runs/background/subagent-runner.d.ts.map +1 -1
- package/src/runs/background/subagent-runner.js +13 -1
- package/src/runs/background/subagent-runner.js.map +1 -1
- package/src/runs/foreground/async-stop-action.d.ts.map +1 -1
- package/src/runs/foreground/async-stop-action.js +19 -3
- package/src/runs/foreground/async-stop-action.js.map +1 -1
- package/src/runs/foreground/execution.d.ts.map +1 -1
- package/src/runs/foreground/execution.js +8 -1
- package/src/runs/foreground/execution.js.map +1 -1
- package/src/runs/foreground/subagent-executor.d.ts +6 -5
- package/src/runs/foreground/subagent-executor.d.ts.map +1 -1
- package/src/runs/foreground/subagent-executor.js +293 -182
- package/src/runs/foreground/subagent-executor.js.map +1 -1
- package/src/runs/shared/child-launch.d.ts +5 -1
- package/src/runs/shared/child-launch.d.ts.map +1 -1
- package/src/runs/shared/child-launch.js +15 -1
- package/src/runs/shared/child-launch.js.map +1 -1
- package/src/runs/shared/child-session.d.ts +9 -0
- package/src/runs/shared/child-session.d.ts.map +1 -1
- package/src/runs/shared/child-session.js +90 -4
- package/src/runs/shared/child-session.js.map +1 -1
- package/src/runs/shared/child-tool-plan.d.ts +4 -0
- package/src/runs/shared/child-tool-plan.d.ts.map +1 -1
- package/src/runs/shared/child-tool-plan.js +11 -4
- package/src/runs/shared/child-tool-plan.js.map +1 -1
- package/src/runs/shared/dynamic-fanout.js +1 -1
- package/src/runs/shared/dynamic-fanout.js.map +1 -1
- package/src/runs/shared/mcp-config-sources.d.ts +1 -0
- package/src/runs/shared/mcp-config-sources.d.ts.map +1 -1
- package/src/runs/shared/mcp-config-sources.js +1 -1
- package/src/runs/shared/mcp-config-sources.js.map +1 -1
- package/src/runs/shared/mcp-direct-tool-allowlist.d.ts +28 -0
- package/src/runs/shared/mcp-direct-tool-allowlist.d.ts.map +1 -1
- package/src/runs/shared/mcp-direct-tool-allowlist.js +78 -2
- package/src/runs/shared/mcp-direct-tool-allowlist.js.map +1 -1
- package/src/runs/shared/model-resolution.d.ts +10 -0
- package/src/runs/shared/model-resolution.d.ts.map +1 -1
- package/src/runs/shared/model-resolution.js +30 -9
- package/src/runs/shared/model-resolution.js.map +1 -1
- package/src/runs/shared/model-scope.d.ts +2 -1
- package/src/runs/shared/model-scope.d.ts.map +1 -1
- package/src/runs/shared/model-scope.js +26 -10
- package/src/runs/shared/model-scope.js.map +1 -1
- package/src/runs/shared/parallel-utils.d.ts +2 -0
- package/src/runs/shared/parallel-utils.d.ts.map +1 -1
- package/src/runs/shared/parallel-utils.js.map +1 -1
- package/src/runs/shared/pi-spawn.d.ts +1 -10
- package/src/runs/shared/pi-spawn.d.ts.map +1 -1
- package/src/runs/shared/pi-spawn.js +7 -86
- package/src/runs/shared/pi-spawn.js.map +1 -1
- package/src/runs/shared/subagent-prompt-runtime.d.ts.map +1 -1
- package/src/runs/shared/subagent-prompt-runtime.js +2 -0
- package/src/runs/shared/subagent-prompt-runtime.js.map +1 -1
- package/src/runs/shared/worktree.d.ts +1 -1
- package/src/runs/shared/worktree.d.ts.map +1 -1
- package/src/runs/shared/worktree.js +1 -1
- package/src/runs/shared/worktree.js.map +1 -1
- package/src/shared/disabled-features.d.ts +92 -0
- package/src/shared/disabled-features.d.ts.map +1 -0
- package/src/shared/disabled-features.js +113 -0
- package/src/shared/disabled-features.js.map +1 -0
- package/src/shared/extension-context.d.ts +9 -0
- package/src/shared/extension-context.d.ts.map +1 -1
- package/src/shared/extension-context.js +7 -0
- package/src/shared/extension-context.js.map +1 -1
- package/src/shared/settings.d.ts +1 -1
- package/src/shared/types.d.ts +20 -0
- package/src/shared/types.d.ts.map +1 -1
- package/src/shared/types.js.map +1 -1
- package/src/slash/prompt-template-bridge.js +2 -2
- package/src/slash/prompt-template-bridge.js.map +1 -1
- package/src/slash/slash-commands.d.ts +2 -0
- package/src/slash/slash-commands.d.ts.map +1 -1
- package/src/slash/slash-commands.js +2 -2
- package/src/slash/slash-commands.js.map +1 -1
- package/src/tui/render.d.ts.map +1 -1
- package/src/tui/render.js +55 -17
- package/src/tui/render.js.map +1 -1
- package/src/watchdog/diff-tool.d.ts +3 -1
- package/src/watchdog/diff-tool.d.ts.map +1 -1
- package/src/watchdog/diff-tool.js +20 -11
- package/src/watchdog/diff-tool.js.map +1 -1
- package/src/watchdog/register-child.js +2 -2
- package/src/watchdog/register-child.js.map +1 -1
- package/src/watchdog/register-main.js +2 -2
- package/src/watchdog/register-main.js.map +1 -1
- package/src/watchdog/review.d.ts +1 -1
- package/src/watchdog/review.d.ts.map +1 -1
- package/src/watchdog/review.js +1 -1
- package/src/watchdog/review.js.map +1 -1
- package/src/watchdog/turn-delta.js +1 -1
- package/src/watchdog/turn-delta.js.map +1 -1
- package/src/workflows/chat-progress.js +2 -2
- package/src/workflows/chat-progress.js.map +1 -1
- package/src/workflows/scripted-workflow.d.ts +8 -0
- package/src/workflows/scripted-workflow.d.ts.map +1 -1
- package/src/workflows/scripted-workflow.js +10 -2
- package/src/workflows/scripted-workflow.js.map +1 -1
- package/src/workflows/structured-workflow-scripts.d.ts +10 -0
- package/src/workflows/structured-workflow-scripts.d.ts.map +1 -0
- package/src/workflows/structured-workflow-scripts.js +166 -0
- package/src/workflows/structured-workflow-scripts.js.map +1 -0
- package/src/workflows/workflow-receipt.d.ts.map +1 -1
- package/src/workflows/workflow-receipt.js +8 -2
- package/src/workflows/workflow-receipt.js.map +1 -1
- package/src/workflows/workflow-resources.d.ts +9 -0
- package/src/workflows/workflow-resources.d.ts.map +1 -1
- package/src/workflows/workflow-resources.js +39 -12
- package/src/workflows/workflow-resources.js.map +1 -1
- package/src/workflows/workflow-reuse.d.ts +51 -0
- package/src/workflows/workflow-reuse.d.ts.map +1 -0
- package/src/workflows/workflow-reuse.js +103 -0
- package/src/workflows/workflow-reuse.js.map +1 -0
- package/src/workflows/workflow-revival.d.ts +32 -0
- package/src/workflows/workflow-revival.d.ts.map +1 -0
- package/src/workflows/workflow-revival.js +111 -0
- package/src/workflows/workflow-revival.js.map +1 -0
package/docs/workflows.md
CHANGED
|
@@ -27,6 +27,8 @@ Stop and report the exact failure, run/status, and repository/cwd/worktree/branc
|
|
|
27
27
|
|
|
28
28
|
Failed workflow details and async `status.json` include `workflow.failureKind` as `validation`, `script`, `child`, `return-serialization`, `timeout`, `detached-child`, or `runtime`. `validation` means the host rejected the script before it ran (syntax or portability) or at completion (unawaited calls); errors thrown into a running script, including rejected `runs.run` parameters and runtime `SyntaxError`s, are `script` because the script could catch them, and failed children are `child`. `runtime` covers host setup and infrastructure failures, such as an unavailable cwd or a crashed worker. A workflow that is stopped or reloaded is not a failure and has no `failureKind`.
|
|
29
29
|
|
|
30
|
+
When `/reload`, a session resume, or a pi-web project switch replaces the extension runtime, a running async workflow stops with `workflow.stopCause: "runtime-replaced"` in `status.json`, and its awaited async children keep running. When the same workflow script is launched again with the same `args` in that session, a `runs.run` with the same key and params returns a child that already finished successfully without launching it, and waits for a child that is still running instead of starting another. Those results carry `reused: true`, their step and trace entry are marked `reused`, and the new run records `workflow.reusedFrom`. Failed and stopped children, and children that ran in-process, launch again. Reuse applies only when the newest run of that script and args in the session was stopped this way; a user stop or a completed run ends it.
|
|
31
|
+
|
|
30
32
|
Pi core may print a generic `pi -ne` extension-load hint; that out-of-repo hint is not protocol-approved fallback. A verified compaction abort may continue the retained child once on its already resolved model; it does not authorize an execution-mode or model switch.
|
|
31
33
|
|
|
32
34
|
## Prompt shortcuts
|
|
@@ -43,9 +45,17 @@ The package includes reusable prompt templates for common workflows. You do not
|
|
|
43
45
|
|
|
44
46
|
Add `autofix` to `/parallel-review` or `/parallel-cleanup` to apply only the synthesized fixes worth doing now after reviewers return.
|
|
45
47
|
|
|
46
|
-
## Scripted workflows
|
|
48
|
+
## Scripted workflows
|
|
49
|
+
|
|
50
|
+
Use direct `{ agent, task }` for one bounded child. Use a workflow script when the parent needs a stable keyed child, sequence, fanout, steering, retry, or aggregation. For ordinary parallel fanout, use `await runs.all([{ key, agent, task }, ...])`. It resolves to an ordered array, not a key map, so use indexes, destructuring, or `.map(...)`, not `results.<key>`. Do not read `.output` from unawaited `runs.run` launches. Store a `runs.run` promise only when the script later observes it with `await`, `Promise.race`, or `Promise.all`, such as steering a live child before awaiting its result. Scripts are ordinary JavaScript statement bodies. Use an explicit `return` for a useful result.
|
|
51
|
+
|
|
52
|
+
The `workflow` field selects the script source:
|
|
47
53
|
|
|
48
|
-
|
|
54
|
+
- `workflow: true` runs the one ```` ```js workflow ```` fenced block written in the same assistant reply as the `subagent` call. The script is plain text in the reply, so it needs no JSON string escaping. A reply can carry exactly one such block and one `workflow: true` call; zero or several blocks fail. A line containing only ```` ``` ```` (three or more backticks, optionally followed by spaces or tabs) ends the block, so keep Markdown fences inside quoted strings.
|
|
55
|
+
- A string containing `/` (or `\` in a Windows path), such as `workflow: "./workflows/review.js"`, is a script file.
|
|
56
|
+
- Any other string, such as `workflow: "review"`, is a [named workflow resource](#named-workflow-resources-for-permission-extensions).
|
|
57
|
+
|
|
58
|
+
`workflow: true` works only from a model tool call. Slash commands, RPC, and schedules pass scripts through their own inputs. Examples below that show only a ```` ```js workflow ```` block run with `subagent({ workflow: true })` in the same reply.
|
|
49
59
|
|
|
50
60
|
For multi-step or parallel work, make exactly one top-level `subagent` workflow call with `async:true` and launch children only inside it. Read this guide for recipes rather than constructing a second top-level orchestration. Available sandbox helpers include `runs.run`, `runs.all`, `runs.lanes`, `runs.steer`, `runs.status`, `runs.ref`/`runs.refs`, `emit`, `console`, standard JavaScript, and mission `state` when enabled. No filesystem, shell, arbitrary Pi tools, or host globals are available; named resources alone may grant `runs.host` authority.
|
|
51
61
|
|
|
@@ -59,26 +69,28 @@ A workflow can finish dispatch while these children remain running. Its summary
|
|
|
59
69
|
|
|
60
70
|
Validate a script without launching children:
|
|
61
71
|
|
|
72
|
+
```js workflow
|
|
73
|
+
const results = await runs.all([{ key: "scan", agent: "scout", task: "Scan" }]);
|
|
74
|
+
return results[0].output;
|
|
75
|
+
```
|
|
76
|
+
|
|
62
77
|
```js
|
|
63
|
-
subagent({ action: "validate",
|
|
64
|
-
const results = await runs.all([{ key: "scan", agent: "scout", task: "Scan" }]);
|
|
65
|
-
return results[0].output;
|
|
66
|
-
` });
|
|
78
|
+
subagent({ action: "validate", workflow: true });
|
|
67
79
|
```
|
|
68
80
|
|
|
69
|
-
For a script stored in a file,
|
|
81
|
+
For a script stored in a file, pass its path:
|
|
70
82
|
|
|
71
83
|
```js
|
|
72
|
-
subagent({
|
|
73
|
-
subagent({ action: "validate",
|
|
84
|
+
subagent({ workflow: "./workflows/review.js", cwd: "/path/to/project" });
|
|
85
|
+
subagent({ action: "validate", workflow: "./workflows/review.js" });
|
|
74
86
|
```
|
|
75
87
|
|
|
76
|
-
|
|
88
|
+
Relative paths resolve against the request `cwd`; absolute paths pass through. The host reads the file before validation, schedule creation, or workflow sandbox execution. The sandbox still has no filesystem access. Missing, unreadable, and empty files return file input errors instead of script syntax errors.
|
|
77
89
|
|
|
78
|
-
|
|
90
|
+
Reply-block and file-backed scripts accept bounded plain-JSON `args`:
|
|
79
91
|
|
|
80
92
|
```js
|
|
81
|
-
subagent({
|
|
93
|
+
subagent({ workflow: "./workflows/review.js", args: { target: "src/workflows" } });
|
|
82
94
|
// workflows/review.js
|
|
83
95
|
return runs.run("review", { agent: "reviewer", task: `Review ${args.target}` });
|
|
84
96
|
```
|
|
@@ -94,18 +106,20 @@ subagent({ workflow: "review", args: { task: "Review the change" } });
|
|
|
94
106
|
subagent({ workflow: "run-ci", args: { command: "npm test" } });
|
|
95
107
|
```
|
|
96
108
|
|
|
97
|
-
The host resolves the name and validates bounded plain-JSON `args` before starting the workflow. Resource provenance is recorded in workflow details and receipts for downstream permission/policy checks. Resource authority is not caller-supplied: `runs.host` is available only when the resolved resource explicitly grants the requested host key and command.
|
|
109
|
+
The host resolves the name and validates bounded plain-JSON `args` before starting the workflow. Resource provenance is recorded in workflow details and receipts for downstream permission/policy checks. Resource authority is not caller-supplied: `runs.host` is available only when the resolved resource explicitly grants the requested host key and command. Reply-block (`workflow: true`) and file-path scripts remain raw, unknown-provenance inputs, so their `runs.host` calls are unavailable through the public execution boundary. Named resources cannot be combined with `agent` or `task`; this first slice ships only the package-owned `review` and `run-ci` resources, not a user/project resource registry.
|
|
98
110
|
|
|
99
111
|
### Opt-in bounded workflows
|
|
100
112
|
|
|
101
113
|
Composite workflows have no default parent deadline. Add bounds only when the workflow contract calls for them:
|
|
102
114
|
|
|
115
|
+
```js workflow
|
|
116
|
+
const scan = await runs.run("scan", { agent: "scout", task: "Inspect the named files." });
|
|
117
|
+
return runs.run("review", { agent: "reviewer", task: "Review:\n" + scan.output });
|
|
118
|
+
```
|
|
119
|
+
|
|
103
120
|
```js
|
|
104
121
|
subagent({
|
|
105
|
-
|
|
106
|
-
const scan = await runs.run("scan", { agent: "scout", task: "Inspect the named files." });
|
|
107
|
-
return runs.run("review", { agent: "reviewer", task: "Review:\n" + scan.output });
|
|
108
|
-
`,
|
|
122
|
+
workflow: true,
|
|
109
123
|
timeoutMs: 900000,
|
|
110
124
|
toolBudget: { soft: 40, hard: 60 },
|
|
111
125
|
usageBudget: { tokens: { soft: 100000, hard: 150000 } }
|
|
@@ -120,80 +134,76 @@ subagent({
|
|
|
120
134
|
|
|
121
135
|
These controls are opt-in. Avoid tight hard budgets for mutation-capable workers unless the workflow has an explicit checkpoint and handoff path.
|
|
122
136
|
|
|
123
|
-
The optional `preflight` lane hints apply only to raw `
|
|
137
|
+
The optional `preflight` lane hints apply only to raw scripts (`workflow: true` or a script path), not named workflows or direct child calls. They are display-only: mismatched coverage warns but never changes execution authority.
|
|
124
138
|
|
|
125
139
|
The result is `{ ok, errors }`. Invalid scripts return a tool error and include line and column data when available. Validation checks syntax, portable nested-async rules, literal `runs.run` and `runs.all` keys and child `baseRef` values, duplicate literal keys in one `runs.all` group, direct keyed access to a known `runs.all` result, and statically clear non-JSON boundary values. It also looks up literal `agent` names in `runs.run`, `runs.all`, and `runs.lanes` children against the agents discovered for the request `cwd` and `agentScope`, and reports unknown or ambiguous names with a close match when one exists. Children with their own `cwd`, `agentScope`, or `resume`, object spreads, and names built at runtime are left to launch time. Dynamic keys and other runtime-only values are accepted without a warning. Validation does not launch children or create run artifacts. Executing a workflow runs the same agent-name check first, so an unknown literal agent fails before any child launches.
|
|
126
140
|
|
|
141
|
+
```js workflow
|
|
142
|
+
const scan = await runs.run("scan", { label: "Map codebase behavior", agent: "scout", task: "Scan the codebase" });
|
|
143
|
+
const reviews = await runs.all([
|
|
144
|
+
{ key: "correctness", label: "Review codebase correctness", agent: "reviewer", task: "Review correctness: " + scan.output },
|
|
145
|
+
{ key: "tests", label: "Review test coverage", agent: "reviewer", task: "Review tests: " + scan.output }
|
|
146
|
+
]);
|
|
147
|
+
return reviews.map(result => result.output);
|
|
148
|
+
```
|
|
149
|
+
|
|
127
150
|
```js
|
|
128
|
-
subagent({
|
|
129
|
-
const scan = await runs.run("scan", { label: "Map codebase behavior", agent: "scout", task: "Scan the codebase" });
|
|
130
|
-
const reviews = await runs.all([
|
|
131
|
-
{ key: "correctness", label: "Review codebase correctness", agent: "reviewer", task: "Review correctness: " + scan.output },
|
|
132
|
-
{ key: "tests", label: "Review test coverage", agent: "reviewer", task: "Review tests: " + scan.output }
|
|
133
|
-
]);
|
|
134
|
-
return reviews.map(result => result.output);
|
|
135
|
-
` });
|
|
151
|
+
subagent({ workflow: true });
|
|
136
152
|
```
|
|
137
153
|
|
|
138
|
-
Keep helper functions portable across Node and Bun. Use top-level `await`, plain helper functions that return `runs.run(...)`, or explicit Promise chains. Do not define nested `async function` helpers, async arrows, or async methods inside
|
|
154
|
+
Keep helper functions portable across Node and Bun. Use top-level `await`, plain helper functions that return `runs.run(...)`, or explicit Promise chains. Do not define nested `async function` helpers, async arrows, or async methods inside a workflow script; native async helpers hide child-launch observation in Bun and are rejected.
|
|
139
155
|
|
|
140
|
-
```js
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
return result.output;
|
|
147
|
-
` });
|
|
156
|
+
```js workflow
|
|
157
|
+
function scan() {
|
|
158
|
+
return runs.run("scan", { label: "Map codebase behavior", agent: "scout", task: "Scan the codebase" });
|
|
159
|
+
}
|
|
160
|
+
const result = await scan();
|
|
161
|
+
return result.output;
|
|
148
162
|
```
|
|
149
163
|
|
|
150
164
|
Chaining is still supported. The supported form is scripted chaining: await one `runs.run(...)` result, then pass its output into the next step. Parallel fanout uses `runs.all(...)` inside the same script.
|
|
151
165
|
|
|
152
|
-
```js
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
return patch.output;
|
|
157
|
-
` });
|
|
166
|
+
```js workflow
|
|
167
|
+
const plan = await runs.run("plan", { label: "Plan migration behavior", agent: "scout", task: "Plan the migration" });
|
|
168
|
+
const patch = await runs.run("patch", { label: "Implement migration behavior", agent: "worker", task: "Implement this plan:\n" + plan.output });
|
|
169
|
+
return patch.output;
|
|
158
170
|
```
|
|
159
171
|
|
|
160
172
|
### Parallel sequential lanes
|
|
161
173
|
|
|
162
|
-
For a bounded set of independent chains, `runs.lanes(...)` removes the mechanical loop that would otherwise connect each lane's stages. It is a helper inside
|
|
163
|
-
|
|
164
|
-
```js
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
}));
|
|
196
|
-
` });
|
|
174
|
+
For a bounded set of independent chains, `runs.lanes(...)` removes the mechanical loop that would otherwise connect each lane's stages. It is a helper inside a workflow script, not a new top-level `subagent` execution mode:
|
|
175
|
+
|
|
176
|
+
```js workflow
|
|
177
|
+
const board = await runs.lanes([
|
|
178
|
+
{
|
|
179
|
+
key: "api",
|
|
180
|
+
stages: [
|
|
181
|
+
{ key: "writer", label: "Implement API behavior", agent: "worker", task: "Implement the API change" },
|
|
182
|
+
{ key: "challenge", label: "Challenge API behavior", resume: "previous", task: "Challenge the API implementation" },
|
|
183
|
+
{ key: "review", label: "Review API behavior", agent: "reviewer", task: "Review the API lane" }
|
|
184
|
+
]
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
key: "ui",
|
|
188
|
+
stages: [
|
|
189
|
+
{ key: "writer", label: "Implement UI behavior", agent: "worker", task: "Implement the UI change" },
|
|
190
|
+
{ key: "review", label: "Review UI behavior", agent: "reviewer", task: "Review the UI lane" }
|
|
191
|
+
]
|
|
192
|
+
}
|
|
193
|
+
]);
|
|
194
|
+
return board.map((lane) => ({
|
|
195
|
+
key: lane.key,
|
|
196
|
+
state: lane.state,
|
|
197
|
+
failedStage: lane.failedStage,
|
|
198
|
+
stages: lane.stages.map((stage) => ({
|
|
199
|
+
key: stage.key,
|
|
200
|
+
state: stage.state,
|
|
201
|
+
ok: stage.ok,
|
|
202
|
+
runId: stage.runId,
|
|
203
|
+
outputReference: stage.outputReference,
|
|
204
|
+
verdict: stage.verdict
|
|
205
|
+
}))
|
|
206
|
+
}));
|
|
197
207
|
```
|
|
198
208
|
|
|
199
209
|
The first stage from every lane is launched in one existing `runs.all(...)` batch. Later stages in each lane start only after the preceding stage settles. A later stage with `resume: "previous"` requires the preceding child to return a retained `runId`; the helper then uses the existing retained-resume launch checks and does not accept an arbitrary run id. Generated child keys use `<lane>.<stage>`, while the returned board uses the local lane and stage keys.
|
|
@@ -208,18 +218,16 @@ Two ways to put a small classifier (a script, a lookup, a fast evaluation model)
|
|
|
208
218
|
|
|
209
219
|
**A typed gate** runs a command after a child finishes and turns its JSON stdout into that child's `structuredOutput`:
|
|
210
220
|
|
|
211
|
-
```js
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
return { verdict: review.structuredOutput.verdict, report: "reports/review.md" };
|
|
222
|
-
` });
|
|
221
|
+
```js workflow
|
|
222
|
+
const review = await runs.run("review", {
|
|
223
|
+
agent: "reviewer", task: args.packet,
|
|
224
|
+
output: "reports/review.md", outputMode: "file-only",
|
|
225
|
+
gate: { command: "classify --report reports/review.md", output: "json" }
|
|
226
|
+
});
|
|
227
|
+
if (review.structuredOutput.verdict === "blocked") {
|
|
228
|
+
return runs.run("fix", { agent: "worker", task: "Fix the findings in reports/review.md" });
|
|
229
|
+
}
|
|
230
|
+
return { verdict: review.structuredOutput.verdict, report: "reports/review.md" };
|
|
223
231
|
```
|
|
224
232
|
|
|
225
233
|
The parent receives a pointer plus a verdict instead of the review text. See [typed gates](tool-reference.md#typed-gates) for the contract and failure rules.
|
|
@@ -264,13 +272,11 @@ The first named resource version supports only `npm test` and `npm run typecheck
|
|
|
264
272
|
|
|
265
273
|
Use `await runs.steer(key, message, options?)` after `runs.run` or `runs.all` has launched that stable key. Scripts do not target raw run ids. The optional fields are `mode: "steer" | "follow_up" | "auto"`, a non-negative child `index`, and a positive `ackTimeoutMs`.
|
|
266
274
|
|
|
267
|
-
```js
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
return { writer: await writer, receipt };
|
|
273
|
-
` });
|
|
275
|
+
```js workflow
|
|
276
|
+
const writer = runs.run("writer", { agent: "worker", task: "Implement the change" });
|
|
277
|
+
const evidence = await runs.run("evidence", { agent: "scout", task: "Find the exact contract" });
|
|
278
|
+
const receipt = await runs.steer("writer", "Also check: " + evidence.output, { mode: "follow_up" });
|
|
279
|
+
return { writer: await writer, receipt };
|
|
274
280
|
```
|
|
275
281
|
|
|
276
282
|
The receipt state is `queued`, `delivered`, `missed`, or `failed`. For an async child, `delivered` means it consumed the correlated user input; for a foreground child, it means the in-process Pi transport accepted the input. It does not mean the model followed it. `missed` means the keyed child became terminal or had no live route before delivery. This first slice uses the existing foreground and async steering transports but does not start steering recovery. Workflow traces include one steering attempt entry and one receipt entry.
|
|
@@ -281,111 +287,99 @@ Always await or return a `runs.steer` promise. The workflow waits for an observe
|
|
|
281
287
|
|
|
282
288
|
`runs.run` starts a keyed child when you call it. You do not need separate `runs.start`, `runs.next`, or `runs.collect` helpers for rolling councils or staged reviews. This is the advanced exception to ordinary `runs.all` fanout: keep launched promises only when the script later observes each one with direct `await`, `Promise.race`, or `Promise.all`. Use `Promise.race` to wait for the next completed child, steer a still-running sibling by its stable key, and use `Promise.all` to collect the remaining children.
|
|
283
289
|
|
|
284
|
-
```js
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
];
|
|
290
|
+
```js workflow
|
|
291
|
+
let pending = [
|
|
292
|
+
{ key: "analysis-a", promise: runs.run("analysis-a", { agent: "reviewer", task: "Analyze option A" }).then((result) => ({ key: "analysis-a", result })) },
|
|
293
|
+
{ key: "analysis-b", promise: runs.run("analysis-b", { agent: "reviewer", task: "Analyze option B" }).then((result) => ({ key: "analysis-b", result })) },
|
|
294
|
+
{ key: "critic", promise: runs.run("critic", { agent: "reviewer", task: "Find the strongest objection" }).then((result) => ({ key: "critic", result })) }
|
|
295
|
+
];
|
|
291
296
|
|
|
292
|
-
|
|
293
|
-
|
|
297
|
+
const first = await Promise.race(pending.map((child) => child.promise));
|
|
298
|
+
pending = pending.filter((child) => child.key !== first.key);
|
|
294
299
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
300
|
+
const target = pending.find((child) => child.key === "critic") ?? pending[0];
|
|
301
|
+
const receipt = await runs.steer(target.key, "Challenge this early result:\n" + first.result.output, { mode: "auto" });
|
|
302
|
+
const rest = await Promise.all(pending.map((child) => child.promise));
|
|
298
303
|
|
|
299
|
-
|
|
300
|
-
` });
|
|
304
|
+
return { first: first.result.output, rest: rest.map((child) => child.result.output), receipt };
|
|
301
305
|
```
|
|
302
306
|
|
|
303
307
|
The workflow trace records the run completions and steering receipt. Scripts cannot access the filesystem or control inboxes; returned run and artifact references are data only. If the keyed child is terminal, stale, or has no live route when `runs.steer` runs, the receipt reports `missed` or `failed` and the script can decide whether to continue.
|
|
304
308
|
|
|
305
309
|
Use named outputs when later workflow steps need structured data or durable references:
|
|
306
310
|
|
|
307
|
-
```js
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
});
|
|
323
|
-
` });
|
|
311
|
+
```js workflow
|
|
312
|
+
const inventory = await runs.run("inventory", {
|
|
313
|
+
agent: "scout",
|
|
314
|
+
task: "List the files that need review.",
|
|
315
|
+
outputSchema: {
|
|
316
|
+
type: "object",
|
|
317
|
+
properties: { files: { type: "array", items: { type: "string" } } },
|
|
318
|
+
required: ["files"],
|
|
319
|
+
additionalProperties: false
|
|
320
|
+
}
|
|
321
|
+
});
|
|
322
|
+
return runs.run("review", {
|
|
323
|
+
agent: "reviewer",
|
|
324
|
+
task: "Review these files: " + inventory.structuredOutput.files.join(", ")
|
|
325
|
+
});
|
|
324
326
|
```
|
|
325
327
|
|
|
326
328
|
For dynamic fanout, have one step return a structured list, check it in JavaScript, then map the bounded entries into `runs.all(...)`:
|
|
327
329
|
|
|
328
|
-
```js
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
})));
|
|
346
|
-
` });
|
|
330
|
+
```js workflow
|
|
331
|
+
const targets = await runs.run("targets", {
|
|
332
|
+
agent: "scout",
|
|
333
|
+
task: "Return up to five source files that need review.",
|
|
334
|
+
outputSchema: {
|
|
335
|
+
type: "object",
|
|
336
|
+
properties: { files: { type: "array", items: { type: "string" }, maxItems: 5 } },
|
|
337
|
+
required: ["files"],
|
|
338
|
+
additionalProperties: false
|
|
339
|
+
}
|
|
340
|
+
});
|
|
341
|
+
const files = targets.structuredOutput.files.slice(0, 5);
|
|
342
|
+
return runs.all(files.map((file, index) => ({
|
|
343
|
+
key: "review-" + index,
|
|
344
|
+
agent: "reviewer",
|
|
345
|
+
task: "Review " + file
|
|
346
|
+
})));
|
|
347
347
|
```
|
|
348
348
|
|
|
349
349
|
For intermediate data that only later steps need, prefer the prior child's returned output or `structuredOutput` instead of writing shared files:
|
|
350
350
|
|
|
351
|
-
```js
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
return runs.run("fix", { agent: "worker", task: "Implement these findings:\n" + scan.output });
|
|
355
|
-
` });
|
|
351
|
+
```js workflow
|
|
352
|
+
const scan = await runs.run("scan", { agent: "scout", task: "Find the files that need fixes." });
|
|
353
|
+
return runs.run("fix", { agent: "worker", task: "Implement these findings:\n" + scan.output });
|
|
356
354
|
```
|
|
357
355
|
|
|
358
356
|
`{chain_dir}` remains available inside scripted workflow step templates for legacy-compatible path templates. It expands to the workflow cwd, not to private temporary storage.
|
|
359
357
|
|
|
360
358
|
### Migrating old chain shapes
|
|
361
359
|
|
|
362
|
-
Legacy top-level `chain`, `tasks`, `parallel`, `chainDir`, `/chain`, `/parallel`, `/run-chain`, and durable `.chain.md` execution are no longer the public workflow API. Rewrite them as JavaScript:
|
|
360
|
+
Legacy top-level `chain`, `tasks`, `parallel`, `chainDir`, `/chain`, `/parallel`, `/run-chain`, and durable `.chain.md` execution are no longer the public workflow API. Rewrite them as JavaScript. The exception is `disabledFeatures: ["workflow-scripts"]`, which replaces workflow scripts with top-level `chain` and `tasks` (see [configuration](configuration.md#chain-and-tasks-without-workflow-scripts)).
|
|
363
361
|
|
|
364
|
-
```js
|
|
362
|
+
```js workflow
|
|
365
363
|
// Old shape, no longer supported:
|
|
366
364
|
// { chain: [{ agent: "scout", task: "Scan" }, { agent: "worker", task: "Fix from {previous}" }] }
|
|
367
365
|
|
|
368
|
-
// Current shape:
|
|
369
|
-
{
|
|
370
|
-
|
|
371
|
-
return runs.run("fix", { agent: "worker", task: "Fix from: " + scan.output });
|
|
372
|
-
` }
|
|
366
|
+
// Current shape: this ```js workflow block plus subagent({ workflow: true })
|
|
367
|
+
const scan = await runs.run("scan", { agent: "scout", task: "Scan" });
|
|
368
|
+
return runs.run("fix", { agent: "worker", task: "Fix from: " + scan.output });
|
|
373
369
|
```
|
|
374
370
|
|
|
375
|
-
```js
|
|
371
|
+
```js workflow
|
|
376
372
|
// Old shape, no longer supported:
|
|
377
373
|
// { tasks: [{ agent: "reviewer", task: "Review API" }, { agent: "reviewer", task: "Review UI" }] }
|
|
378
374
|
|
|
379
|
-
// Current shape:
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
]);
|
|
385
|
-
` }
|
|
375
|
+
// Current shape: this ```js workflow block plus subagent({ workflow: true })
|
|
376
|
+
return runs.all([
|
|
377
|
+
{ key: "api", agent: "reviewer", task: "Review API" },
|
|
378
|
+
{ key: "ui", agent: "reviewer", task: "Review UI" }
|
|
379
|
+
]);
|
|
386
380
|
```
|
|
387
381
|
|
|
388
|
-
For long task text with Markdown fences or shell blocks, use quoted lines instead of a raw template literal:
|
|
382
|
+
For long task text with Markdown fences or shell blocks, use quoted lines instead of a raw template literal. In a reply block, a line containing only ```` ``` ```` would end the block:
|
|
389
383
|
|
|
390
384
|
````js
|
|
391
385
|
const task = [
|
|
@@ -403,7 +397,7 @@ A plain workflow creates one enclosing mission by default. Its children do not c
|
|
|
403
397
|
|
|
404
398
|
Use stable child keys and keep process logic in ordinary JavaScript. `runs.run` launches one child, `runs.all` launches independent children together, and later steps can use each completed child's `output`. Put long task text in arrays joined with `"\n"` so Markdown fences do not conflict with the script string.
|
|
405
399
|
|
|
406
|
-
For a process you run often, save the task as a prompt template under `.pi/prompts/` or `~/.pi/agent/prompts/` and launch it with `/prompt-workflow`. The adapter compiles prompt steps into
|
|
400
|
+
For a process you run often, save the task as a prompt template under `.pi/prompts/` or `~/.pi/agent/prompts/` and launch it with `/prompt-workflow`. The adapter compiles prompt steps into a workflow script, so templates describe the work instead of embedding raw `subagent` tool calls. You can ask the parent agent to create or update these prompt files from a process described in natural language.
|
|
407
401
|
|
|
408
402
|
```md
|
|
409
403
|
---
|
|
@@ -450,11 +444,11 @@ return { api: api.artifactPaths, ui: ui.artifactPaths };
|
|
|
450
444
|
|
|
451
445
|
Each child uses the existing worktree lifecycle: it branches from clean HEAD, journals ownership before launch, captures a patch and handoff manifest, then removes cleanly captured temporary worktrees and branches. The handoff manifest path remains available in the child's `artifactPaths`; return or emit it when the orchestrator needs to apply or inspect the patches. `runs.ref` stays concise and intentionally omits full paths.
|
|
452
446
|
|
|
453
|
-
A top-level `{
|
|
447
|
+
A top-level `{ workflow: true, worktree: true }` makes isolation the default for every workflow child. An individual child can override that default with `worktree: false`. Keep one writer when parallel writes are not intentionally isolated.
|
|
454
448
|
|
|
455
449
|
Before a materialized `runs.run` or `runs.all` group dispatches fresh children, isolated sources must be Git repositories with clean working trees (excluding `.pi/subagents/` runtime state). A rejected group dispatches no children and spends no fan-out slots or child output claims; key-level failure traces can remain. Checks are shared only within that group, are cancellable, and run again at allocation because sources can change. Retained resumes keep their stored contracts. Select the correct cwd or arrange an operator-approved commit/stash; isolation is never dropped automatically.
|
|
456
450
|
|
|
457
|
-
Use `baseRef` to branch managed worktrees from `HEAD` or a supported named ref such as `refs/heads/release`, `refs/tags/v1`, or `origin/main`. Full 40/64-character commit IDs and revision expressions such as `HEAD~1` are unsupported. For example, `{
|
|
451
|
+
Use `baseRef` to branch managed worktrees from `HEAD` or a supported named ref such as `refs/heads/release`, `refs/tags/v1`, or `origin/main`. Full 40/64-character commit IDs and revision expressions such as `HEAD~1` are unsupported. For example, `{ workflow: true, worktree: true, baseRef: "refs/heads/release" }` applies the release ref to children unless a child supplies its own `baseRef`. If omitted, the default `HEAD` is resolved at worktree allocation, not when the script is validated or a schedule is created. The source checkout must still be clean, and the ref must resolve to a commit before any worktree is allocated.
|
|
458
452
|
|
|
459
453
|
Configure the worktree provider, native path layout, base directory, and setup hook in [configuration.md](configuration.md).
|
|
460
454
|
|
|
@@ -523,7 +517,7 @@ For A → B → C, C's request belongs to B, not A. B can escalate a separate qu
|
|
|
523
517
|
|
|
524
518
|
Child-side routine completion handoffs are not expected. If a child appears stalled, needs-attention notices show up in the parent session with useful next actions, such as checking `subagent({ action: "status" })`, interrupting the run, or nudging the child.
|
|
525
519
|
|
|
526
|
-
If a
|
|
520
|
+
If a workflow script child detaches through `contact_supervisor`, the enclosing async workflow stays `paused` until that child exits. Then the extension reconciles it to `complete` or `failed`. Wait on the child until that happens.
|
|
527
521
|
|
|
528
522
|
If messages do not show up, run `/subagents-doctor`. Advanced users can tune the bridge with `intercomBridge` in [configuration.md](configuration.md).
|
|
529
523
|
|
|
@@ -571,4 +565,4 @@ Then run it through the native adapter:
|
|
|
571
565
|
|
|
572
566
|
The adapter delegates to the named subagent, applies `model`, `skill`, `cwd`, and fork/fresh context metadata, and supports runtime overrides such as `--subagent reviewer`, `--fork`, `--fresh`, and `--bg`.
|
|
573
567
|
|
|
574
|
-
Prompt templates with `chain:` frontmatter are translated into
|
|
568
|
+
Prompt templates with `chain:` frontmatter are translated into a workflow script and launched through `/prompt-workflow`; `/chain-prompts` is no longer registered.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "pi-subagents",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.74.0",
|
|
5
5
|
"description": "Pi extension for single-agent delegation and scripted multi-agent workflows",
|
|
6
6
|
"author": "Nico Bailon",
|
|
7
7
|
"license": "MIT",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"dependencies": {
|
|
20
20
|
"acorn": "8.18.0",
|
|
21
21
|
"jiti": "2.7.0",
|
|
22
|
-
"undici": "8.10.
|
|
22
|
+
"undici": "8.10.2",
|
|
23
23
|
"yaml": "2.8.3"
|
|
24
24
|
},
|
|
25
25
|
"peerDependencies": {
|
package/prompts/review-loop.md
CHANGED
|
@@ -8,7 +8,7 @@ Use the `subagent` tool. Keep the parent session as the loop controller and fina
|
|
|
8
8
|
|
|
9
9
|
Default to a maximum of 3 review rounds unless I specify a different cap. Count a review round each time fresh-context reviewers inspect the current diff after a worker pass. Stop early when reviewers find no P0 findings, no P1 fixes worth doing now, and no approved P2 notes that should be handled in this loop.
|
|
10
10
|
|
|
11
|
-
If the invocation includes an implementation request, first launch one async `worker` to implement the approved scope. If the current diff is already the target, start with review. The sequence can be launched up front
|
|
11
|
+
If the invocation includes an implementation request, first launch one async `worker` to implement the approved scope. If the current diff is already the target, start with review. The sequence can be launched up front as a workflow script (a ```` ```js workflow ```` block plus `subagent({ workflow: true })`) when it is already clear, or continued as follow-up single-agent runs after each async completion. For an initial workflow script, pass `async: true` so the main chat is unblocked; do not set `clarify: true` unless I explicitly want the foreground clarify UI. Use only one writer against the active worktree at a time unless I explicitly ask for isolated worktrees.
|
|
12
12
|
|
|
13
13
|
As a conservative orchestration policy, do not set a hard `toolBudget` or tight `usageBudget` on implementation or fix workers. A default tool budget blocks read/search tools rather than mutation tools, and reported usage has no reservation model, so count or usage limits still do not measure delivery safety. Give each writer a narrow delivery slice and an outer elapsed deadline with enough margin. Before that deadline, request a checkpoint after the current tool returns with changed files, build/test state, remaining work, and commit or PR state. An elapsed timeout is not a mutation-safe boundary and must not be the checkpoint trigger.
|
|
14
14
|
|
|
@@ -32,7 +32,7 @@ Pass 1 is independent reports. Pass 2 is one cross-exam. Run Pass 3 only when `-
|
|
|
32
32
|
|
|
33
33
|
1. Write the council brief: question, scope, non-goals, evidence targets, roster, known advisor context modes, and pass cap.
|
|
34
34
|
2. Tell the user the roster, context modes, and pass cap.
|
|
35
|
-
3. Launch one async `
|
|
35
|
+
3. Launch one async workflow script (a ```` ```js workflow ```` block plus `subagent({ workflow: true, async: true })`) with `runs.all` for Pass 1. Use stable keys, `phase: "Council pass 1"`, concise labels, and `output: false` unless separate artifacts are useful. Set `context` only when the profile context is known or a fallback rule requires it.
|
|
36
36
|
4. Return one aggregate Pass 1 receipt. On completion, tell the user completion count, agreement count, dispute count, and whether Pass 2 is needed.
|
|
37
37
|
5. Synthesize the claim matrix in the parent: agreements, disputed claims, missing proof, owner decisions, and at most five material relay claims per advisor.
|
|
38
38
|
6. For Pass 2, tell the user which claims are relayed and why they matter. Resume each advisor with a curated challenge packet. A resume needs a retained run id and task; it excludes `agent` and rejects `gate`. Record each new run id; Pass 3 resumes those latest ids with new stable keys.
|
|
@@ -29,19 +29,26 @@ and their resolved `tools` allow `subagent`.
|
|
|
29
29
|
| Need | Use |
|
|
30
30
|
| --- | --- |
|
|
31
31
|
| One bounded task for one child | direct `{ agent, task }` |
|
|
32
|
-
| JavaScript control flow or data-dependent branching; sequence, fanout, retry, rolling fanout, or aggregation |
|
|
33
|
-
| A broad plan split into visible narrow stages per lane |
|
|
32
|
+
| JavaScript control flow or data-dependent branching; sequence, fanout, retry, rolling fanout, or aggregation | a workflow script with `runs.run(...)` / `runs.all(...)` |
|
|
33
|
+
| A broad plan split into visible narrow stages per lane | a workflow script with `runs.lanes([{ key, stages: [...] }])` |
|
|
34
34
|
| Independent worktree or repository lanes | `references/multi-lane-orchestration.md` |
|
|
35
35
|
| Council of advisors | `../council-mode/SKILL.md` |
|
|
36
36
|
| Management, status, steering, authoring, or inspection | `action` |
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
To launch a workflow script, write it as one ```` ```js workflow ```` fenced
|
|
39
|
+
block in your reply, then call `subagent({ workflow: true, ... })` in the same
|
|
40
|
+
reply. Use `workflow: "./path/to/script.js"` for a script file and
|
|
41
|
+
`workflow: "<name>"` for a named resource.
|
|
42
|
+
|
|
43
|
+
A workflow script is code-driven: `runs.run(...)` for keyed steps,
|
|
39
44
|
`runs.all([...])` for fanout, plain JavaScript for branching and aggregation.
|
|
40
45
|
Keep scripts portable: use top-level `await`, plain helpers, or explicit Promise
|
|
41
46
|
chains, not nested async helpers. Legacy top-level `chain` / `tasks` inputs and
|
|
42
|
-
durable `.chain.md` execution are inspection or migration material only
|
|
47
|
+
durable `.chain.md` execution are inspection or migration material only, except
|
|
48
|
+
that `disabledFeatures: ["workflow-scripts"]` replaces scripts with top-level
|
|
49
|
+
`chain` and `tasks` (see [configuration](../../docs/configuration.md#chain-and-tasks-without-workflow-scripts)).
|
|
43
50
|
|
|
44
|
-
Use `runs.lanes(...)` only inside a
|
|
51
|
+
Use `runs.lanes(...)` only inside a workflow script, not as a top-level mode,
|
|
45
52
|
when a broad, predeclared plan benefits from visible per-lane stages; otherwise
|
|
46
53
|
use ordinary `runs.run(...)` / `runs.all(...)`. See the [canonical staged-lane
|
|
47
54
|
example](../../docs/workflows.md#parallel-sequential-lanes). Keep assignments
|
|
@@ -34,8 +34,8 @@ For durable evidence, copy only the final summary to session memory, a PR body/c
|
|
|
34
34
|
|
|
35
35
|
## Best Practices
|
|
36
36
|
|
|
37
|
-
- Run subagents asynchronously by default; direct one-child execution is enough for one bounded task, while `
|
|
38
|
-
- For a predeclared broad plan split into visible narrow stages, use `runs.lanes([...])` inside
|
|
37
|
+
- Run subagents asynchronously by default; direct one-child execution is enough for one bounded task, while a workflow script (a ```` ```js workflow ```` block plus `subagent({ workflow: true })`) is the composition surface for JavaScript control flow and data-dependent branching. Use `async: false` only when the parent must block. See `references/execution-controls.md` → Async/background for wait semantics.
|
|
38
|
+
- For a predeclared broad plan split into visible narrow stages, use `runs.lanes([...])` inside a workflow script; use raw `runs.run(...)`/`runs.all(...)` for conditional or rolling flows. See [`execution-controls.md`](execution-controls.md#parallel-sequential-lanes).
|
|
39
39
|
- Keep one writer per cwd/worktree. Parallelize reading, review, and validation; concurrent writers need isolated worktrees. Give every child a cold-start packet with its goal, target/ref, authority, context, success criteria, validation, output, and stop rules.
|
|
40
40
|
- Keep tasks narrow and standalone; do not rely on issue numbers, broad globs, or supervisor round-trips to supply missing context.
|
|
41
41
|
- Keep authority with the parent. Escalate unapproved product, scope, architecture, merge, credential, or release decisions; checks, receipts, and review bots are evidence, not authority.
|
|
@@ -64,7 +64,7 @@ its overhead. Recipes select a shape; they do not authorize delegation:
|
|
|
64
64
|
|
|
65
65
|
## Error Handling
|
|
66
66
|
|
|
67
|
-
- **Unknown agent:** run `subagent({ action: "list" })`; check scope/precedence and author new orchestration
|
|
67
|
+
- **Unknown agent:** run `subagent({ action: "list" })`; check scope/precedence and author new orchestration as a workflow script, not legacy chains.
|
|
68
68
|
- **Setup, discovery, or intercom confusion:** run `subagent({ action: "doctor" })`.
|
|
69
69
|
- **Max subagent depth exceeded:** flatten the workflow or raise `maxSubagentDepth` in config.
|
|
70
70
|
- **Missing session file for a fork:** persist the parent session before using `context: "fork"`.
|