pi-subagents 0.59.0 → 0.60.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.
Files changed (43) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/docs/tool-reference.md +4 -1
  3. package/docs/workflows.md +2 -2
  4. package/package.json +1 -1
  5. package/skills/council-mode/SKILL.md +48 -243
  6. package/skills/council-mode/references/pass-contracts.md +150 -0
  7. package/skills/pi-subagents/SKILL.md +87 -37
  8. package/skills/pi-subagents/references/constraints-and-recipes.md +29 -233
  9. package/skills/pi-subagents/references/execution-controls.md +47 -6
  10. package/skills/pi-subagents/references/management-authoring-rpc.md +2 -2
  11. package/skills/pi-subagents/references/multi-lane-orchestration.md +13 -1
  12. package/skills/pi-subagents/references/prompting-and-roles.md +34 -27
  13. package/skills/pi-subagents/references/review-and-validation.md +73 -0
  14. package/src/agents/agent-management.ts +154 -25
  15. package/src/api/shared-types.ts +2 -0
  16. package/src/extension/public-execution.ts +1 -0
  17. package/src/extension/schemas.ts +1 -0
  18. package/src/extension/tool-description.ts +8 -4
  19. package/src/runs/background/async-execution.ts +2 -2
  20. package/src/runs/background/async-job-tracker.ts +3 -0
  21. package/src/runs/background/async-status.ts +45 -2
  22. package/src/runs/background/control-channel.ts +3 -2
  23. package/src/runs/background/run-status.ts +13 -2
  24. package/src/runs/background/subagent-runner.ts +5 -1
  25. package/src/runs/background/subagent-wait.ts +10 -2
  26. package/src/runs/background/wait-completions.ts +3 -0
  27. package/src/runs/foreground/execution.ts +11 -2
  28. package/src/runs/foreground/subagent-executor.ts +98 -1
  29. package/src/runs/shared/async-status-projection.ts +138 -4
  30. package/src/runs/shared/background-process-options.ts +9 -0
  31. package/src/runs/shared/mcp-direct-tool-grant.ts +2 -5
  32. package/src/runs/shared/mutation-evidence.ts +52 -3
  33. package/src/runs/shared/pi-args.ts +47 -1
  34. package/src/runs/shared/single-output.ts +45 -18
  35. package/src/runs/shared/subagent-prompt-runtime.ts +20 -2
  36. package/src/runs/shared/workflow-graph.ts +15 -0
  37. package/src/shared/types.ts +34 -1
  38. package/src/tui/fleet-status.ts +11 -3
  39. package/src/tui/render-helpers.ts +31 -0
  40. package/src/tui/render.ts +597 -112
  41. package/src/watchdog/change-signature.ts +40 -1
  42. package/src/workflows/host-command.ts +6 -1
  43. package/src/workflows/scripted-workflow.ts +53 -2
package/CHANGELOG.md CHANGED
@@ -1,7 +1,44 @@
1
1
  # Changelog
2
2
 
3
+
3
4
  ## [Unreleased]
4
5
 
6
+ ## [0.60.0] - 2026-08-30
7
+
8
+ ### Highlights
9
+ - Agent selection is easier with compact capability lists and structured capability details.
10
+ - Async status views are calmer and show workflow progress with clearer grouping and labels.
11
+ - Subagent guidance is clearer about when to work directly and when to orchestrate delegated planning, implementation, and review.
12
+ - Windows and macOS runs avoid more distracting console flashes, delayed failures, and startup hangs.
13
+ - Recovery paths preserve better diagnostics when child runs time out, fail early, or cannot provide requested output.
14
+
15
+ ### Added
16
+ - Add `action: "list", capabilities: true` for compact prompt-free agent capability discovery. Thanks to [@peedrr](https://github.com/peedrr) for #1717.
17
+ - Add structured `details.agentCapabilities` records so callers can select agents without parsing prose rows (#1720).
18
+
19
+ ### Changed
20
+ - Show `runs.lanes(...)` workflows with active-stage focus and planned-stage progress in async status widgets (#1699).
21
+ - Align foreground subagent result labels with async widget labels and disambiguate duplicate rows (#1697).
22
+ - Render parallel subagent workflow groups as readable cards with nested agent rows (#1696).
23
+ - Remove repeated one-child async widget status labels and compact progress echoes (#1695).
24
+ - Tighten packaged subagent and Council Mode guidance for one-child launches, composed `workflowScript` runs, generic review validation, and private policy boundaries.
25
+ - Clarify portable model-tier guidance for parent, worker, scout, reviewer, and critique subagents without requiring a specific provider.
26
+ - Trim duplicated orchestration recipes from the packaged skill while keeping detailed policy and execution references in one place.
27
+ - Clarify when the parent should work directly versus orchestrate delegated subagent work, including who owns decisions and publication (#1722).
28
+ - Clarify `workflowScript` portability and `runs.host(...)` working-directory limits, including outer workflow `cwd` and trusted `cd ... && command` patterns (#1679).
29
+
30
+ ### Fixed
31
+ - Treat malformed persisted async status states as partial, bound persisted workflow stage text, and fail closed when an explicit child-output path cannot be inspected before a run.
32
+ - Surface recovery diagnostics for dirty timed-out children that miss requested reports, while keeping them fail-closed (#1713).
33
+ - Keep retained-session resume runners from flashing console windows on Windows while preserving Unix background detachment. Thanks to [@Zethu5](https://github.com/Zethu5) for #1711.
34
+ - Hide mutation-evidence Git subprocess windows on Windows to prevent visible console flashes or terminal tabs. Thanks to [@dnnkeeper](https://github.com/dnnkeeper) for #1706.
35
+ - Deliver immediate async workflow terminal failures on macOS without requiring a later status refresh (#1700).
36
+ - Skip untracked-file enumeration for watchdog signatures when the Git root is the user home or has no tracked files, avoiding startup and turn hangs in accidental large home repositories. Thanks to [@AluxesLAS](https://github.com/AluxesLAS) for #1693.
37
+ - Reuse a fork-family prompt cache key for OpenAI-style forked subagent requests so sibling fork children keep cache affinity without pooling fresh children. Thanks to [@Shinkicast](https://github.com/Shinkicast) for #1682.
38
+ - Show workflow child `[fresh]` and `[fork]` context labels in Fleet status rows alongside model and thinking badges.
39
+ - Match pi-mcp-adapter direct-tool names when configured MCP server names contain hyphens. Thanks to [@unrelentingfox](https://github.com/unrelentingfox) for #1685.
40
+ - Animate running FleetView glyphs from the wall clock and repaint unchanged running entries. Thanks to [@Pudgey](https://github.com/Pudgey) for #1688.
41
+
5
42
  ## [0.59.0] - 2026-08-28
6
43
 
7
44
  ### Highlights
@@ -4,7 +4,7 @@ Parameters and actions for the `subagent` tool. These are what the LLM passes wh
4
4
 
5
5
  ## Execution examples
6
6
 
7
- Chaining is code-driven through `workflowScript`. Use `await runs.run(...)` for sequential steps and `await runs.all([{ key, agent, task }, ...])` for ordinary parallel fanout. `runs.all` resolves to an ordered array, not a key map, so use indexes, destructuring, or `.map(...)`, not `results.<key>`. Do not read `.output` from an unawaited `runs.run` launch. Stored `runs.run` promises are only for the advanced rolling fanout pattern under [Workflow steering](#workflow-steering), where every promise is later observed with direct `await`, `Promise.race`, or `Promise.all`. Legacy top-level `chain`, `tasks`, and `parallel` inputs are not supported. Helper functions must be plain functions or explicit Promise chains. Nested `async function` helpers, async arrows, and async methods are rejected so child-launch tracking stays portable across Node and Bun.
7
+ Chaining is code-driven through `workflowScript`. Use `await runs.run(...)` for sequential steps and `await runs.all([{ key, agent, task }, ...])` for ordinary parallel fanout. `runs.all` resolves to an ordered array, not a key map, so use indexes, destructuring, or `.map(...)`, not `results.<key>`. Do not read `.output` from an unawaited `runs.run` launch. Stored `runs.run` promises are only for the advanced rolling fanout pattern under [Workflow steering](#workflow-steering), where every promise is later observed with direct `await`, `Promise.race`, or `Promise.all`. Legacy top-level `chain`, `tasks`, and `parallel` inputs are not supported. Helper functions must be plain functions or explicit Promise chains. Nested `async function` helpers, async arrows, and async methods are rejected so child-launch tracking stays portable across Node and Bun. Host steps are similarly narrow: use `runs.host(key, { kind: "command", command, timeoutMs, output?, role?, provider? })`; there is no per-step `cwd`, and commands and relative output paths use the workflow `cwd`. Set `cwd` on the outer `subagent({...})` request instead, or put a trusted directory change in the command (for example, `cd /path/to/worktree && npm test`).
8
8
 
9
9
  Use `{ action: "validate", workflowScript }` to check statically decidable syntax and structure without launching children. It returns `{ ok, errors }` and fails the tool call when `ok` is false. Dynamic keys and values remain valid because runtime-only cases are not guessed.
10
10
 
@@ -95,6 +95,7 @@ The complete plain-JSON inventory is validated before the first launch (maximum
95
95
  | `view` | `fleet \| transcript` | - | Optional `status` view for the active fleet surface or transcript tail inspection. |
96
96
  | `lines` | number | `80` | Maximum transcript lines for `action: "status", view: "transcript"`; capped at 500. |
97
97
  | `agentScope` | `user \| project \| both` | `both` | Agent discovery scope. Project wins on collisions. |
98
+ | `capabilities` | boolean | `false` | With `action: "list"`, return compact prompt-free rows and `details.agentCapabilities` machine-readable records for each agent's declared/default routing capabilities. |
98
99
  | `async` | boolean | default-on | Background execution. Workflows default to background. `async:false` blocks the parent until completion. |
99
100
  | `chatProgress` | `auto \| off \| live-card` | `auto` | WorkflowScript chat projection. `auto` renders a live in-chat card only for watched foreground workflows in the same Git repository, including managed worktrees; it is off otherwise. Explicit `live-card` requires `async:false` and the same Git repository. Async workflows have no inline live card, so omit `chatProgress` or use `auto`/`off`; use `async:false` only when the parent must block. |
100
101
  | `isolation` | `none \| worktree` | - | Workflow child isolation. `none` runs in the shared cwd and does not need Git. `worktree` requires a managed Git worktree. Do not combine it with a contradictory `worktree` value. |
@@ -192,6 +193,7 @@ Agent definitions are not loaded into context by default. Management actions let
192
193
  ```ts
193
194
  { action: "list" }
194
195
  { action: "list", agentScope: "project" }
196
+ { action: "list", capabilities: true }
195
197
  { action: "get", agent: "scout" }
196
198
  { action: "models" }
197
199
  { action: "models", agent: "reviewer" }
@@ -235,6 +237,7 @@ Agent definitions are not loaded into context by default. Management actions let
235
237
 
236
238
  Rules:
237
239
 
240
+ - `capabilities: true` changes `action: "list"` to compact one-line rows and adds `details.agentCapabilities: { agents, restrictedCount, capabilityCeilingSources? }`. Each agent row includes source, aliases, runner type/capabilities, tools, MCP direct tools, mutation tools, model/thinking/fallbacks, default async/timeout, output path/mode, skills/extensions, and whether the current capability ceiling allows execution. It never includes an agent's system prompt. Rows show declared/default capabilities, not task-specific launch resolution; use preflight when exact launch validation is needed.
238
241
  - `create` uses `config.scope`, not `agentScope`.
239
242
  - `config.name` is the local frontmatter name; optional `config.package` registers the runtime name as `{package}.{name}` and is saved as separate `name` and `package` frontmatter.
240
243
  - `config.aliases` accepts a comma-separated string, string array, or `false` to clear aliases. Aliases resolve to the canonical agent name for execution and are shown by `list`/`get`.
package/docs/workflows.md CHANGED
@@ -35,7 +35,7 @@ Add `autofix` to `/parallel-review` or `/parallel-cleanup` to apply only the syn
35
35
 
36
36
  ## Scripted workflows (workflowScript)
37
37
 
38
- All model-facing subagent execution is expressed through `workflowScript` in the `subagent` tool. Use stable keys and ordinary JavaScript for one child, sequence, and parallelism. 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:
38
+ Use direct `{ agent, task }` for one bounded child. Use `workflowScript` 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:
39
39
 
40
40
  Child results cross into the script as plain JSON data. Non-JSON host metadata is omitted, so use returned fields such as `runId`, `ok`, `output`, and `structuredOutput` for workflow control.
41
41
 
@@ -178,7 +178,7 @@ subagent({ workflowScript: `
178
178
  ` });
179
179
  ```
180
180
 
181
- The first version supports only `kind: "command"`. `command` and `timeoutMs` are required; `output` must be a relative path without traversal. `role` may be `ci` or `gate`, and `provider` is display metadata only. The command has no stdin, receives the workflow cwd, and must be awaited or returned. Stdout, stderr, and the saved log are bounded. A nonzero exit, timeout, abort, or output-write failure fails the workflow. Async status and terminal receipts store the bounded host-step state; renderers do not run commands or read command output.
181
+ The first version supports only `kind: "command"`. `command` and `timeoutMs` are required; `output` must be a relative path without traversal. `role` may be `ci` or `gate`, and `provider` is display metadata only. **There is no per-step `cwd` field:** the command and relative output path use the workflow cwd. Set `cwd` on the outer `subagent({...})` request when the workflow should run in another directory, or put a trusted directory change in the command (for example, `cd /path/to/worktree && npm test`) when only that step differs. The command has no stdin, receives the workflow cwd, and must be awaited or returned. Stdout, stderr, and the saved log are bounded. A nonzero exit, timeout, abort, or output-write failure fails the workflow. Async status and terminal receipts store the bounded host-step state; renderers do not run commands or read command output.
182
182
 
183
183
  ### Steering a workflow child
184
184
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-subagents",
3
- "version": "0.59.0",
3
+ "version": "0.60.0",
4
4
  "description": "Pi extension for single-agent delegation and scripted multi-agent workflows",
5
5
  "author": "Nico Bailon",
6
6
  "license": "MIT",
@@ -5,250 +5,55 @@ description: Run a bounded supervisor-mediated advisor council. Use when the use
5
5
 
6
6
  # Council Mode
7
7
 
8
- This skill is for the parent supervisor only. Do not inject it into advisors. The
9
- parent selects the roster, curates all cross-advisor communication, decides which
10
- feedback is valid, and writes the decision memo. Advisors do not talk directly or
11
- see peer transcripts by default. This is not free-form agent chat.
12
-
13
- Use council mode for a material decision with real tradeoffs. Do not use it for a
14
- trivial or settled question, or for implementation work. Read
15
- `skills/pi-subagents/references/execution-controls.md` before you launch advisors.
16
-
17
- ## Roster and limits
18
-
19
- Use advisor profile names directly. A `council-*` profile defines model, tools,
20
- context, output defaults, and any persistent stance in the profile body. Its
21
- profile configuration or explicit invocation owns its context choice.
22
-
23
- Package advisors can also join the roster only when their package Pi extension is
24
- installed and their external-job provider is registered. For Surf, `gpt-pro` is
25
- available only after the `surf-cli` Pi extension loads Surf's `surf-oracle`
26
- provider. Treat it as a normal advisor name in `runs.all` after that provider is
27
- visible. It is background-only, so omit `async` unless you explicitly want
28
- detached receipt semantics; workflow execution will await the terminal provider
29
- result. External runners can lack repo tools, structured-output support, or
30
- resumability. For them, include the needed evidence or file excerpts in the task,
31
- use the text JSON contract below instead of `outputSchema`, and use the
32
- fresh-context fallback path for cross-exam when the run is not resumable.
33
-
34
- Create model-based profiles in your user or project agent directory. Do not add
35
- them to this package. This is a valid example:
36
-
37
- ```markdown
38
- ---
39
- name: council-sol
40
- description: Read-only fresh-context advisor for bounded council decisions
41
- tools: read, grep, find, ls
42
- model: openai-codex/gpt-5.6-sol
43
- thinking: high
44
- systemPromptMode: replace
45
- inheritProjectContext: true
46
- inheritSkills: false
47
- defaultContext: fresh
48
- acceptanceRole: read-only
49
- ---
8
+ Council mode is parent-supervised advice for a material decision with real tradeoffs. It is not free-form agent chat, implementation work, a transcript dump, mutation authority, or a council UI.
9
+
10
+ The parent selects the roster, relays only curated claims, decides validity, and writes the memo. Advisors stay read-only and do not see peer transcripts by default.
11
+
12
+ Before launch, read:
13
+
14
+ - `skills/pi-subagents/references/execution-controls.md`
15
+ - `skills/council-mode/references/pass-contracts.md`
16
+
17
+ ## Roster
18
+
19
+ Run `subagent({ action: "list" })`, then choose 2-3 executable advisor names that start with `council-`. The prefix is convention only. Never use more than four advisors.
20
+
21
+ If fewer than two council profiles are available, fill with `oracle`, then `reviewer`. Launch fallback `oracle` with `context: "fork"`; let fallback `reviewer` use its normal profile context. Note fallbacks and known context modes in the memo. If fewer than two advisors remain, use the normal one-oracle consultation loop and label it degraded mode.
22
+
23
+ `council-*` profiles live in user or project agent directories, not this package. A profile defines model, tools, context, output defaults, and persistent stance. Keep advisors read-only, disable inherited skills unless needed, and put stance in the profile body instead of inventing per-run role labels.
50
24
 
51
- Analyze the council question independently. Inspect evidence directly. Do not
52
- edit, run mutating commands, commit, push, contact peers, or spawn subagents.
53
- Return concise, cited advice using the report contract in the council task.
54
- ```
55
-
56
- After `subagent({ action: "list" })`, prefer 2–3 executable names that start with
57
- `council-`. The prefix is a naming convention, not runtime selection. If fewer
58
- than two profiles are available, fill the roster with `oracle`, then `reviewer`,
59
- until it has two advisors. Launch fallback `oracle` with `context: "fork"` so
60
- global defaults cannot remove its parent-chat context. Let fallback `reviewer`
61
- use its normal profile context. Note the fallback and known context modes in the
62
- memo. Use the normal single-oracle consultation loop only when a requested roster
63
- or unavailable builtins leaves fewer than two advisors.
64
- Label that result as degraded mode. Never use more than four advisors.
65
-
66
- Pass 1 is independent reports. Pass 2 is one cross-exam. The default pass cap is
67
- 2. Run pass 3 only when `--max-passes 3` was requested and a material dispute can
68
- be settled by evidence an advisor can produce. Never run an unbounded loop.
25
+ External-job/package advisors may join only when their provider is registered. Treat them as ordinary advisor names in `runs.all`, but honor their runner limits: they may lack repo tools, structured output, or resumability. Include evidence they cannot read, request JSON text instead of `outputSchema`, and use a fresh-context fallback when they cannot resume for cross-exam.
26
+
27
+ ## Passes
28
+
29
+ Pass 1 is independent reports. Pass 2 is one cross-exam. Run Pass 3 only when `--max-passes 3` was requested and a material dispute can still be settled by evidence. Never run an unbounded loop.
69
30
 
70
31
  ## Protocol
71
32
 
72
- 1. The parent writes a brief with the question, scope, non-goals, evidence targets,
73
- roster, known advisor context modes, and pass cap. If the user wants a specific
74
- lens, keep it in the question, scope, or profile body instead of inventing a
75
- per-advisor label.
76
- 2. Before Pass 1, tell the user the roster, requested or known context modes, and
77
- pass cap. Use a stable key, `phase`, and concise `label` for every
78
- workflow child. For example, use `advisor-oracle`, `phase: "Council pass 1"`,
79
- and `label: "Oracle — intent and consistency"`.
80
- 3. Launch one async `workflowScript` with `runs.all` for independent advisor
81
- reports. Set `context` when the selected advisor has a known profile context or
82
- a fallback rule requests one, because a global default can otherwise override
83
- that profile. Set `context: "fork"` for fallback `oracle`. If no advisor context
84
- is known, omit `context` and disclose the unknown runtime default in the memo.
85
- Each advisor is read-only and must not spawn children, edit files, run mutating
86
- commands, commit, or push. Set `output: false` unless separate advisor artifacts
87
- are explicitly requested or useful for the decision. When separate artifacts are
88
- useful, give advisors relative output paths so the runtime stores them under its
89
- managed artifact directory; do not ask them to write root-level council report
90
- files. For installed
91
- external-runner advisors such as Surf `gpt-pro` after `surf-oracle` is
92
- registered, do not pass `outputSchema`; put the schema request in the task text
93
- and accept `result.output` as the report.
94
- 4. Return one aggregate Pass 1 receipt. After it completes, tell the user the
95
- completion count, agreement count, dispute count, and whether Pass 2 is needed.
96
- 5. The parent synthesizes a claim matrix in session. It contains agreements,
97
- disputed claims, missing proof, owner decisions, and a relay set of at most five
98
- high-impact claims per advisor. Do not delegate this synthesis.
99
- 6. Before Pass 2, tell the user how many claims are relayed and why each is
100
- material. Launch a second async `workflowScript` with `runs.all` resume calls.
101
- Each task is a curated challenge packet, not a peer transcript. A resume requires
102
- a retained run id and a non-empty task. It excludes `agent` and rejects `gate`.
103
- Record the new run id from every resume. Pass 3 resumes those latest ids. Return
104
- one aggregate Pass 2 receipt.
105
- 7. After Pass 2, tell the user whether the council converged or which owner
106
- decisions remain. The parent writes the final memo. Do not delegate it.
107
-
108
- If an advisor is not resumable, run the same profile in fresh context with its own
109
- pass-1 report and the challenge packet. Label that response as a fresh-context
110
- fallback, not a true cross-exam.
111
-
112
- Do not set `clarify`, `worktree`, `gate`, tool budgets, or tight usage
113
- budgets on advisors. Bound work through the roster, pass cap, and report length.
114
-
115
- ## Advisor contracts and pass receipts
116
-
117
- Pass-1 reports are at most about 600 words. Give native Pi advisors the same
118
- `outputSchema`, so reports are comparable without heading cleanup. For
119
- external-runner advisors, do not pass `outputSchema`; ask them to return compact
120
- JSON text with the same fields. The following shape is a contract template. Use
121
- the runtime schema syntax supported by the workflow for native advisors and keep
122
- narrative fields as strings:
123
-
124
- ```js
125
- const pass1OutputSchema = {
126
- type: "object",
127
- required: [
128
- "recommendation", "evidence", "assumptions", "risks", "confidence",
129
- "challengeClaims", "ownerDecisions", "changeMyMind"
130
- ],
131
- properties: {
132
- recommendation: { type: "string" },
133
- evidence: {
134
- type: "array",
135
- items: {
136
- type: "object",
137
- required: ["claim", "sources"],
138
- properties: {
139
- claim: { type: "string" },
140
- sources: { type: "array", items: { type: "string" } }
141
- }
142
- }
143
- },
144
- assumptions: {
145
- type: "array",
146
- items: {
147
- type: "object",
148
- required: ["assumption", "status"],
149
- properties: {
150
- assumption: { type: "string" },
151
- status: { enum: ["verified", "unverified"] }
152
- }
153
- }
154
- },
155
- risks: { type: "array", items: { type: "string" } },
156
- confidence: {
157
- type: "object",
158
- required: ["level", "reason"],
159
- properties: {
160
- level: { enum: ["high", "medium", "low"] },
161
- reason: { type: "string" }
162
- }
163
- },
164
- challengeClaims: { type: "array", items: { type: "string" }, maxItems: 3 },
165
- ownerDecisions: { type: "array", items: { type: "string" } },
166
- changeMyMind: { type: "array", items: { type: "string" } }
167
- }
168
- };
169
- ```
170
-
171
- Include this contract in each Pass 1 task: inspect supplied evidence directly; do
172
- not see or ask about other advisors; stay read-only; do not spawn children; return
173
- only the structured report. For external-runner advisors, say `Return only JSON
174
- matching this shape. Do not wrap it in Markdown.` and include any evidence they
175
- cannot read through tools.
176
-
177
- After `runs.all`, return one aggregate receipt rather than making the parent find
178
- separate artifacts. Preserve the result order or map it by stable key so each row
179
- contains the advisor identity and report:
180
-
181
- ```js
182
- return {
183
- pass: 1,
184
- advisors: results.map((result, index) => ({
185
- key: result.key,
186
- agent: result.agent,
187
- requestedContext: roster[index].context ?? "runtime-default-unknown",
188
- runId: result.runId,
189
- report: result.structuredOutput ?? result.output
190
- }))
191
- };
192
- ```
193
-
194
- Do not replace `runtime-default-unknown` with a guessed context. It records that
195
- the launch intentionally omitted context.
196
-
197
- A challenge packet contains only disputed claims, strong conflicting evidence,
198
- missing proof, owner decisions, and high-impact risks. Attribute peer content as
199
- "another advisor". Do not include full peer reports. Use a common Pass 2 contract:
200
-
201
- ```js
202
- const pass2OutputSchema = {
203
- type: "object",
204
- required: ["responses", "recommendationChanged", "outOfScopeFindings"],
205
- properties: {
206
- responses: {
207
- type: "array",
208
- items: {
209
- type: "object",
210
- required: ["claimId", "disposition", "reason", "sources"],
211
- properties: {
212
- claimId: { type: "string" },
213
- disposition: {
214
- enum: ["accept", "reject", "refine", "owner-decision"]
215
- },
216
- reason: { type: "string" },
217
- sources: { type: "array", items: { type: "string" } }
218
- }
219
- }
220
- },
221
- recommendationChanged: {
222
- type: "object",
223
- required: ["changed", "reason"],
224
- properties: { changed: { type: "boolean" }, reason: { type: "string" } }
225
- },
226
- outOfScopeFindings: { type: "array", items: { type: "string" } }
227
- }
228
- };
229
- ```
230
-
231
- Use stable resume keys such as `cross-oracle`, `phase: "Council pass 2"`, concise
232
- labels, and `output: false` unless separate artifacts are requested or useful. Keep
233
- any artifact outputs under the managed run artifact directory. Do not pass
234
- `outputSchema` to external-runner fallback launches; ask for compact JSON text
235
- instead. The aggregate Pass 2 receipt uses the same row shape as Pass 1, with the
236
- new `runId` and `structuredOutput ?? output`.
237
-
238
- ## Stop and memo
239
-
240
- Converged means no disputed claim remains that both materially affects the
241
- recommendation and can plausibly be settled by evidence. Stop at convergence, the
242
- pass cap, failed fallback, or user interruption. Put unresolved disputes in owner
243
- decisions. Never add a round for polish or symmetry.
244
-
245
- The parent memo states the question and scope, recommendation, rationale, accepted
246
- and rejected feedback with reasons, owner decisions, evidence and run ids,
247
- confidence, what would change the decision, and the roster, passes, fallbacks, and
248
- known advisor context modes. Identify advisors by profile name or model-based
249
- profile, not by invented role labels. State that fallback `oracle` is context-aware
250
- and forked.
251
-
252
- Council mode is not agent-to-agent chat, a transcript dump, mutation authority,
253
- auto-escalation to writer lanes, or a council UI. Escalate to a writer only after
254
- the parent memo and only when the user explicitly requests it.
33
+ 1. Write the council brief: question, scope, non-goals, evidence targets, roster, known advisor context modes, and pass cap.
34
+ 2. Tell the user the roster, context modes, and pass cap.
35
+ 3. Launch one async `workflowScript` 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
+ 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
+ 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
+ 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.
39
+ 7. Stop at convergence, pass cap, failed fallback, or user interruption. The parent writes the final memo.
40
+
41
+ If an advisor is not resumable, run the same profile fresh with its Pass 1 report and challenge packet. Label it a fresh-context fallback, not true cross-exam.
42
+
43
+ Do not set `clarify`, `worktree`, `gate`, tool budgets, or tight usage budgets on advisors. Bound work through the roster, pass cap, and report length.
44
+
45
+ ## Memo
46
+
47
+ Converged means no disputed claim remains that both affects the recommendation and can plausibly be settled by advisor evidence. Put unresolved disputes in owner decisions. Do not add a round for polish or symmetry.
48
+
49
+ The memo states:
50
+
51
+ - question and scope
52
+ - recommendation and rationale
53
+ - accepted and rejected feedback with reasons
54
+ - owner decisions
55
+ - evidence and run ids
56
+ - confidence and what would change the decision
57
+ - roster, passes, fallbacks, and known advisor context modes
58
+
59
+ Identify advisors by profile name. State when fallback `oracle` was forked and context-aware. Escalate to a writer only after the memo and only when the user requests it.
@@ -0,0 +1,150 @@
1
+ # Council Mode Pass Contracts
2
+
3
+ Load this before launching council advisors.
4
+
5
+ ## Pass 1 report
6
+
7
+ Native Pi advisors should receive this `outputSchema`. External runners should receive the same shape as plain JSON text and no `outputSchema`.
8
+
9
+ ```js
10
+ const pass1OutputSchema = {
11
+ type: "object",
12
+ required: [
13
+ "recommendation",
14
+ "evidence",
15
+ "assumptions",
16
+ "risks",
17
+ "confidence",
18
+ "challengeClaims",
19
+ "ownerDecisions",
20
+ "changeMyMind"
21
+ ],
22
+ properties: {
23
+ recommendation: { type: "string" },
24
+ evidence: {
25
+ type: "array",
26
+ items: {
27
+ type: "object",
28
+ required: ["claim", "sources"],
29
+ properties: {
30
+ claim: { type: "string" },
31
+ sources: { type: "array", items: { type: "string" } }
32
+ }
33
+ }
34
+ },
35
+ assumptions: {
36
+ type: "array",
37
+ items: {
38
+ type: "object",
39
+ required: ["assumption", "status"],
40
+ properties: {
41
+ assumption: { type: "string" },
42
+ status: { enum: ["verified", "unverified"] }
43
+ }
44
+ }
45
+ },
46
+ risks: { type: "array", items: { type: "string" } },
47
+ confidence: {
48
+ type: "object",
49
+ required: ["level", "reason"],
50
+ properties: {
51
+ level: { enum: ["high", "medium", "low"] },
52
+ reason: { type: "string" }
53
+ }
54
+ },
55
+ challengeClaims: { type: "array", items: { type: "string" }, maxItems: 3 },
56
+ ownerDecisions: { type: "array", items: { type: "string" } },
57
+ changeMyMind: { type: "array", items: { type: "string" } }
58
+ }
59
+ };
60
+ ```
61
+
62
+ Task text:
63
+
64
+ - inspect supplied evidence directly
65
+ - do not ask other advisors or read peer reports
66
+ - stay read-only
67
+ - do not spawn children
68
+ - return only the structured report
69
+ - keep the report under about 600 words
70
+
71
+ For external runners, say: `Return only JSON matching this shape. Do not wrap it in Markdown.` Include any evidence they cannot read with tools.
72
+
73
+ ## Pass 1 aggregate receipt
74
+
75
+ Return one aggregate receipt. Preserve result order or map it by stable key.
76
+
77
+ ```js
78
+ return {
79
+ pass: 1,
80
+ advisors: results.map((result, index) => ({
81
+ key: result.key,
82
+ agent: result.agent,
83
+ requestedContext: roster[index].context ?? "runtime-default-unknown",
84
+ runId: result.runId,
85
+ report: result.structuredOutput ?? result.output
86
+ }))
87
+ };
88
+ ```
89
+
90
+ Do not replace `runtime-default-unknown` with a guessed context.
91
+
92
+ ## Pass 2 challenge
93
+
94
+ A challenge packet contains only disputed claims, strong conflicting evidence, missing proof, owner decisions, and high-impact risks. Attribute peer content as "another advisor". Do not include full peer reports.
95
+
96
+ Native Pi advisors receive `pass2OutputSchema`. External runners and fresh external fallbacks receive the same shape as JSON-only task text and no `outputSchema`.
97
+
98
+ ```js
99
+ const pass2OutputSchema = {
100
+ type: "object",
101
+ required: ["responses", "recommendationChanged", "outOfScopeFindings"],
102
+ properties: {
103
+ responses: {
104
+ type: "array",
105
+ items: {
106
+ type: "object",
107
+ required: ["claimId", "disposition", "reason", "sources"],
108
+ properties: {
109
+ claimId: { type: "string" },
110
+ disposition: { enum: ["accept", "reject", "refine", "owner-decision"] },
111
+ reason: { type: "string" },
112
+ sources: { type: "array", items: { type: "string" } }
113
+ }
114
+ }
115
+ },
116
+ recommendationChanged: {
117
+ type: "object",
118
+ required: ["changed", "reason"],
119
+ properties: {
120
+ changed: { type: "boolean" },
121
+ reason: { type: "string" }
122
+ }
123
+ },
124
+ outOfScopeFindings: { type: "array", items: { type: "string" } }
125
+ }
126
+ };
127
+ ```
128
+
129
+ Use stable resume keys such as `cross-oracle`, `phase: "Council pass 2"`, concise labels, and `output: false` unless separate artifacts are useful. The aggregate Pass 2 receipt uses the Pass 1 row shape with the new `runId` and `structuredOutput ?? output`. Pass 3 resumes those latest ids with new stable keys.
130
+
131
+ ## Advisor profile template
132
+
133
+ Create model-based advisors in the user or project agent directory, not in this package:
134
+
135
+ ```markdown
136
+ ---
137
+ name: council-sol
138
+ description: Read-only fresh-context advisor for bounded council decisions
139
+ tools: read, grep, find, ls
140
+ model: provider/top-reasoning-model
141
+ thinking: high
142
+ systemPromptMode: replace
143
+ inheritProjectContext: true
144
+ inheritSkills: false
145
+ defaultContext: fresh
146
+ acceptanceRole: read-only
147
+ ---
148
+
149
+ Analyze the council question independently. Inspect evidence directly. Do not edit, run mutating commands, commit, push, contact peers, or spawn subagents. Return concise, cited advice using the report contract in the council task.
150
+ ```