@selesai/code 0.13.2 → 0.13.4
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 +20 -0
- package/dist/defaults/models.json +85 -13
- package/dist/extensions/cost-reconcile.test.ts +200 -4
- package/dist/extensions/cost-reconcile.ts +88 -102
- package/dist/extensions/pi-intercom/CHANGELOG.md +13 -0
- package/dist/extensions/pi-intercom/README.md +4 -5
- package/dist/extensions/pi-intercom/config.test.ts +3 -31
- package/dist/extensions/pi-intercom/config.ts +0 -15
- package/dist/extensions/pi-intercom/index.ts +9 -46
- package/dist/extensions/pi-intercom/intercom.integration.test.ts +49 -57
- package/dist/extensions/pi-intercom/package.json +1 -1
- package/dist/extensions/pi-intercom/reply-tracker.test.ts +20 -0
- package/dist/extensions/pi-intercom/reply-tracker.ts +8 -0
- package/dist/extensions/pi-subagents/CHANGELOG.md +27 -0
- package/dist/extensions/pi-subagents/docs/tool-reference.md +4 -1
- package/dist/extensions/pi-subagents/docs/workflows.md +2 -2
- package/dist/extensions/pi-subagents/package-lock.json +2 -2
- package/dist/extensions/pi-subagents/package.json +1 -1
- package/dist/extensions/pi-subagents/skills/council-mode/SKILL.md +48 -243
- package/dist/extensions/pi-subagents/skills/council-mode/references/pass-contracts.md +150 -0
- package/dist/extensions/pi-subagents/skills/pi-subagents/SKILL.md +87 -37
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/constraints-and-recipes.md +29 -233
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/execution-controls.md +49 -8
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/management-authoring-rpc.md +2 -2
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/multi-lane-orchestration.md +13 -1
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/prompting-and-roles.md +34 -27
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/review-and-validation.md +73 -0
- package/dist/extensions/pi-subagents/src/agents/agent-management.ts +157 -28
- package/dist/extensions/pi-subagents/src/api/shared-types.ts +2 -0
- package/dist/extensions/pi-subagents/src/extension/public-execution.ts +1 -0
- package/dist/extensions/pi-subagents/src/extension/schemas.ts +1 -0
- package/dist/extensions/pi-subagents/src/extension/tool-description.ts +4 -1
- package/dist/extensions/pi-subagents/src/runs/background/async-execution.ts +2 -2
- package/dist/extensions/pi-subagents/src/runs/background/async-job-tracker.ts +3 -0
- package/dist/extensions/pi-subagents/src/runs/background/async-status.ts +45 -2
- package/dist/extensions/pi-subagents/src/runs/background/control-channel.ts +3 -2
- package/dist/extensions/pi-subagents/src/runs/background/run-status.ts +13 -2
- package/dist/extensions/pi-subagents/src/runs/background/subagent-runner.ts +5 -1
- package/dist/extensions/pi-subagents/src/runs/background/subagent-wait.ts +10 -2
- package/dist/extensions/pi-subagents/src/runs/background/wait-completions.ts +3 -0
- package/dist/extensions/pi-subagents/src/runs/foreground/execution.ts +11 -2
- package/dist/extensions/pi-subagents/src/runs/foreground/subagent-executor.ts +98 -1
- package/dist/extensions/pi-subagents/src/runs/shared/async-status-projection.ts +138 -4
- package/dist/extensions/pi-subagents/src/runs/shared/background-process-options.ts +9 -0
- package/dist/extensions/pi-subagents/src/runs/shared/mcp-direct-tool-grant.ts +2 -5
- package/dist/extensions/pi-subagents/src/runs/shared/mutation-evidence.ts +52 -3
- package/dist/extensions/pi-subagents/src/runs/shared/pi-args.ts +47 -1
- package/dist/extensions/pi-subagents/src/runs/shared/single-output.ts +45 -18
- package/dist/extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.ts +21 -2
- package/dist/extensions/pi-subagents/src/runs/shared/workflow-graph.ts +15 -0
- package/dist/extensions/pi-subagents/src/shared/types.ts +34 -1
- package/dist/extensions/pi-subagents/src/tui/fleet-status.ts +11 -3
- package/dist/extensions/pi-subagents/src/tui/render-helpers.ts +31 -0
- package/dist/extensions/pi-subagents/src/tui/render.ts +597 -112
- package/dist/extensions/pi-subagents/src/watchdog/change-signature.ts +40 -1
- package/dist/extensions/pi-subagents/src/workflows/host-command.ts +6 -1
- package/dist/extensions/pi-subagents/src/workflows/scripted-workflow.ts +53 -2
- package/dist/extensions/pi-subagents/test/integration/async-execution.test.ts +55 -6
- package/dist/extensions/pi-subagents/test/integration/async-status.test.ts +111 -1
- package/dist/extensions/pi-subagents/test/integration/render-fork-badge.test.ts +206 -38
- package/dist/extensions/pi-subagents/test/integration/render-widget.test.ts +522 -31
- package/dist/extensions/pi-subagents/test/integration/single-execution.test.ts +123 -0
- package/dist/extensions/pi-subagents/test/unit/agent-management.test.ts +48 -0
- package/dist/extensions/pi-subagents/test/unit/async-status-projection.test.ts +57 -1
- package/dist/extensions/pi-subagents/test/unit/background-process-options.test.ts +17 -0
- package/dist/extensions/pi-subagents/test/unit/external-cli-runner.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/unit/fleet-status.test.ts +44 -4
- package/dist/extensions/pi-subagents/test/unit/fork-cache-key.test.ts +91 -0
- package/dist/extensions/pi-subagents/test/unit/host-command.test.ts +1 -0
- package/dist/extensions/pi-subagents/test/unit/index-child-registration.test.ts +0 -1
- package/dist/extensions/pi-subagents/test/unit/mcp-direct-tool-grant.test.ts +20 -3
- package/dist/extensions/pi-subagents/test/unit/mutation-evidence.test.ts +27 -0
- package/dist/extensions/pi-subagents/test/unit/pi-args.test.ts +93 -17
- package/dist/extensions/pi-subagents/test/unit/public-execution.test.ts +1 -0
- package/dist/extensions/pi-subagents/test/unit/render-helpers.test.ts +103 -26
- package/dist/extensions/pi-subagents/test/unit/run-status.test.ts +58 -0
- package/dist/extensions/pi-subagents/test/unit/schemas.test.ts +22 -2
- package/dist/extensions/pi-subagents/test/unit/scripted-workflow.test.ts +21 -0
- package/dist/extensions/pi-subagents/test/unit/single-output.test.ts +13 -0
- package/dist/extensions/pi-subagents/test/unit/subagent-wait.test.ts +54 -0
- package/dist/extensions/pi-subagents/test/unit/tool-description.test.ts +2 -0
- package/dist/extensions/pi-subagents/test/unit/wait-completions.test.ts +32 -0
- package/dist/extensions/pi-subagents/test/unit/watchdog-change-signature.test.ts +48 -1
- package/dist/extensions/pi-subagents/test/unit/widget-nested-render.test.ts +21 -6
- package/dist/extensions/pi-subagents/test/unit/windows-hide-spawn.test.ts +11 -0
- package/dist/extensions/pi-web-agent/CHANGELOG.md +410 -0
- package/dist/extensions/pi-web-agent/README.md +131 -0
- package/dist/extensions/pi-web-agent/package.json +4 -2
- package/dist/extensions/pi-web-agent/src/backends/config.ts +62 -5
- package/dist/extensions/pi-web-agent/src/backends/doctor.ts +136 -0
- package/dist/extensions/pi-web-agent/src/backends/factory.ts +96 -6
- package/dist/extensions/pi-web-agent/src/commands/web-agent-config.ts +183 -47
- package/dist/extensions/pi-web-agent/src/extension.ts +62 -25
- package/dist/extensions/pi-web-agent/src/extract/readability.ts +19 -11
- package/dist/extensions/pi-web-agent/src/orchestration/candidate-selector.ts +5 -4
- package/dist/extensions/pi-web-agent/src/orchestration/direct-url.ts +2 -25
- package/dist/extensions/pi-web-agent/src/orchestration/evidence-quality.ts +5 -2
- package/dist/extensions/pi-web-agent/src/orchestration/evidence-ranker.ts +2 -0
- package/dist/extensions/pi-web-agent/src/orchestration/research-orchestrator.ts +72 -7
- package/dist/extensions/pi-web-agent/src/orchestration/research-types.ts +8 -1
- package/dist/extensions/pi-web-agent/src/orchestration/research-worker.ts +28 -3
- package/dist/extensions/pi-web-agent/src/orchestration/source-profile.ts +4 -0
- package/dist/extensions/pi-web-agent/src/orchestration/url.ts +35 -0
- package/dist/extensions/pi-web-agent/src/presentation/explore-presentation.ts +18 -6
- package/dist/extensions/pi-web-agent/src/presentation/search-presentation.ts +14 -2
- package/dist/extensions/pi-web-agent/src/readers/github-reader.ts +150 -0
- package/dist/extensions/pi-web-agent/src/readers/limits.ts +3 -0
- package/dist/extensions/pi-web-agent/src/readers/pdf-reader.ts +87 -0
- package/dist/extensions/pi-web-agent/src/readers/resolver.ts +25 -0
- package/dist/extensions/pi-web-agent/src/readers/types.ts +11 -0
- package/dist/extensions/pi-web-agent/src/readers/youtube-reader.ts +79 -0
- package/dist/extensions/pi-web-agent/src/search/duckduckgo.ts +32 -5
- package/dist/extensions/pi-web-agent/src/search/exa.ts +109 -0
- package/dist/extensions/pi-web-agent/src/search/fanout.ts +154 -0
- package/dist/extensions/pi-web-agent/src/search/tavily.ts +113 -0
- package/dist/extensions/pi-web-agent/src/search/youcom.ts +109 -0
- package/dist/extensions/pi-web-agent/src/tools/web-search.ts +22 -9
- package/dist/extensions/pi-web-agent/src/types.ts +19 -4
- package/dist/extensions/tokenin-onboarding.ts +302 -0
- package/package.json +1 -1
|
@@ -1672,59 +1672,7 @@ test("intercom tool result hook marks failed details as errors", async () => {
|
|
|
1672
1672
|
assert.deepEqual(okResults.filter(Boolean), []);
|
|
1673
1673
|
});
|
|
1674
1674
|
|
|
1675
|
-
test("
|
|
1676
|
-
const { default: piIntercomExtension } = await import("./index.ts");
|
|
1677
|
-
|
|
1678
|
-
await withIntercomConfig({ toolVisibility: "after-first-use" }, () => withChildOrchestratorEnv({
|
|
1679
|
-
orchestratorTarget: "orchestrator",
|
|
1680
|
-
runId: "78f659a3",
|
|
1681
|
-
agent: "worker",
|
|
1682
|
-
index: "0",
|
|
1683
|
-
}, async () => {
|
|
1684
|
-
const harness = createExtensionHarness("lazy-skill-worker", { activeTools: ["read", "bash"] });
|
|
1685
|
-
piIntercomExtension(harness.pi as never);
|
|
1686
|
-
|
|
1687
|
-
try {
|
|
1688
|
-
await harness.emitLifecycle("session_start");
|
|
1689
|
-
assert.deepEqual(harness.getActiveTools(), ["read", "bash", "contact_supervisor"]);
|
|
1690
|
-
|
|
1691
|
-
harness.pi.events.emit("subagent:control-intercom", {
|
|
1692
|
-
to: "session-child-test",
|
|
1693
|
-
message: "Local relay traffic should not reveal the generic tool.",
|
|
1694
|
-
});
|
|
1695
|
-
assert.equal(harness.sentMessages.at(-1)?.activeTools.includes("intercom"), false);
|
|
1696
|
-
assert.equal(harness.getActiveTools().includes("intercom"), false);
|
|
1697
|
-
|
|
1698
|
-
await harness.emitLifecycle("tool_result", {
|
|
1699
|
-
toolName: "read",
|
|
1700
|
-
input: { path: path.join(repoDir, "README.md") },
|
|
1701
|
-
isError: false,
|
|
1702
|
-
});
|
|
1703
|
-
await harness.emitLifecycle("tool_result", {
|
|
1704
|
-
toolName: "read",
|
|
1705
|
-
input: { path: path.join(repoDir, "skills", "pi-intercom", "SKILL.md") },
|
|
1706
|
-
isError: true,
|
|
1707
|
-
});
|
|
1708
|
-
assert.equal(harness.getActiveTools().includes("intercom"), false);
|
|
1709
|
-
|
|
1710
|
-
await harness.emitLifecycle("tool_result", {
|
|
1711
|
-
toolName: "read",
|
|
1712
|
-
input: { path: path.join(repoDir, "skills", "pi-intercom", "SKILL.md") },
|
|
1713
|
-
isError: false,
|
|
1714
|
-
});
|
|
1715
|
-
assert.deepEqual(harness.getActiveTools(), ["read", "bash", "contact_supervisor", "intercom"]);
|
|
1716
|
-
|
|
1717
|
-
await harness.emitLifecycle("session_start");
|
|
1718
|
-
assert.equal(harness.getActiveTools().includes("intercom"), false);
|
|
1719
|
-
await harness.emitLifecycle("input", { text: " /skill: pi-intercom", source: "user" });
|
|
1720
|
-
assert.equal(harness.getActiveTools().includes("intercom"), true);
|
|
1721
|
-
} finally {
|
|
1722
|
-
await harness.emitLifecycle("session_shutdown");
|
|
1723
|
-
}
|
|
1724
|
-
}));
|
|
1725
|
-
});
|
|
1726
|
-
|
|
1727
|
-
test("lazy tool visibility reveals intercom before broker injection and after an overlay send", { concurrency: false }, async () => {
|
|
1675
|
+
test("obsolete toolVisibility config never hides or reveals the intercom tool", { concurrency: false }, async () => {
|
|
1728
1676
|
const { default: piIntercomExtension } = await import("./index.ts");
|
|
1729
1677
|
|
|
1730
1678
|
await withIntercomConfig({ toolVisibility: "after-first-use" }, async () => {
|
|
@@ -1754,14 +1702,14 @@ test("lazy tool visibility reveals intercom before broker injection and after an
|
|
|
1754
1702
|
piIntercomExtension(inboundHarness.pi as never);
|
|
1755
1703
|
await overlayHarness.emitLifecycle("session_start");
|
|
1756
1704
|
await inboundHarness.emitLifecycle("session_start");
|
|
1757
|
-
assert.equal(overlayHarness.getActiveTools().includes("intercom"),
|
|
1758
|
-
assert.equal(inboundHarness.getActiveTools().includes("intercom"),
|
|
1705
|
+
assert.equal(overlayHarness.getActiveTools().includes("intercom"), true);
|
|
1706
|
+
assert.equal(inboundHarness.getActiveTools().includes("intercom"), true);
|
|
1759
1707
|
|
|
1760
1708
|
selectedSession = await waitForSessionByName(planner, "planner");
|
|
1761
1709
|
const inboundSession = await waitForSessionByName(planner, "lazy-inbound-worker");
|
|
1762
1710
|
const delivered = await planner.send(inboundSession.id, {
|
|
1763
|
-
messageId: "
|
|
1764
|
-
text: "
|
|
1711
|
+
messageId: "stable-inbound-message",
|
|
1712
|
+
text: "Keep intercom active before injecting this message.",
|
|
1765
1713
|
});
|
|
1766
1714
|
assert.equal(delivered.delivered, true);
|
|
1767
1715
|
const deadline = Date.now() + 1000;
|
|
@@ -1770,6 +1718,13 @@ test("lazy tool visibility reveals intercom before broker injection and after an
|
|
|
1770
1718
|
}
|
|
1771
1719
|
assert.equal(inboundHarness.sentMessages[0]?.activeTools.includes("intercom"), true);
|
|
1772
1720
|
|
|
1721
|
+
await inboundHarness.emitLifecycle("tool_result", {
|
|
1722
|
+
toolName: "read",
|
|
1723
|
+
input: { path: path.join(repoDir, "skills", "pi-intercom", "SKILL.md") },
|
|
1724
|
+
isError: false,
|
|
1725
|
+
});
|
|
1726
|
+
assert.equal(inboundHarness.getActiveTools().includes("intercom"), true);
|
|
1727
|
+
|
|
1773
1728
|
await overlayHarness.commands.get("intercom")!("", overlayHarness.ctx);
|
|
1774
1729
|
assert.equal(overlayStep, 2);
|
|
1775
1730
|
assert.equal(overlayHarness.getActiveTools().includes("intercom"), true);
|
|
@@ -3148,6 +3103,43 @@ test("intercom reply sends attachments", { concurrency: false }, async () => {
|
|
|
3148
3103
|
}
|
|
3149
3104
|
});
|
|
3150
3105
|
|
|
3106
|
+
test("intercom send refuses a different target during an active inbound ask turn", { concurrency: false }, async () => {
|
|
3107
|
+
const { planner, orchestrator, cleanup } = await setupClients();
|
|
3108
|
+
const { default: piIntercomExtension } = await import("./index.ts");
|
|
3109
|
+
const harness = createExtensionHarness("cwd-reply-worker");
|
|
3110
|
+
|
|
3111
|
+
try {
|
|
3112
|
+
piIntercomExtension(harness.pi as never);
|
|
3113
|
+
await harness.emitLifecycle("session_start");
|
|
3114
|
+
const worker = await waitForSessionByName(planner, "cwd-reply-worker");
|
|
3115
|
+
|
|
3116
|
+
assert.equal((await planner.send(worker.id, {
|
|
3117
|
+
messageId: "cwd-hierarchy-ask",
|
|
3118
|
+
text: "Please answer me, not the repo-root session.",
|
|
3119
|
+
expectsReply: true,
|
|
3120
|
+
})).delivered, true);
|
|
3121
|
+
const deadline = Date.now() + 1000;
|
|
3122
|
+
while (harness.sentMessages.length === 0 && Date.now() < deadline) {
|
|
3123
|
+
await new Promise((resolve) => setTimeout(resolve, 20));
|
|
3124
|
+
}
|
|
3125
|
+
await harness.emitLifecycle("turn_start");
|
|
3126
|
+
|
|
3127
|
+
const intercomTool = harness.tools.find((tool) => tool.name === "intercom")!;
|
|
3128
|
+
const result = await intercomTool.execute("misdirected-send", {
|
|
3129
|
+
action: "send",
|
|
3130
|
+
to: "orchestrator",
|
|
3131
|
+
message: "This was meant as the ask answer.",
|
|
3132
|
+
}, new AbortController().signal, undefined, harness.ctx);
|
|
3133
|
+
|
|
3134
|
+
assert.equal(result.details?.error, true);
|
|
3135
|
+
assert.equal(result.details?.replyTo, "cwd-hierarchy-ask");
|
|
3136
|
+
assert.match(result.content[0]?.text ?? "", /Refusing non-reply send to "orchestrator"/);
|
|
3137
|
+
} finally {
|
|
3138
|
+
await harness.emitLifecycle("session_shutdown");
|
|
3139
|
+
await cleanup();
|
|
3140
|
+
}
|
|
3141
|
+
});
|
|
3142
|
+
|
|
3151
3143
|
test("intercom reply targets one of multiple pending asks by short session ID", { concurrency: false }, async () => {
|
|
3152
3144
|
const { planner, orchestrator, cleanup } = await setupClients();
|
|
3153
3145
|
const { default: piIntercomExtension } = await import("./index.ts");
|
|
@@ -93,6 +93,26 @@ test("explicit to overrides the current turn context", () => {
|
|
|
93
93
|
assert.throws(() => tracker.resolveReplyTarget({ to: "missing" }, 1003), /No pending ask from/);
|
|
94
94
|
});
|
|
95
95
|
|
|
96
|
+
test("active ask context flags non-reply sends to a different target", () => {
|
|
97
|
+
const tracker = new ReplyTracker();
|
|
98
|
+
const current = tracker.recordIncomingMessage(createSession("planner-id", "planner"), createMessage("ask-1", "Need a reply"), 1000);
|
|
99
|
+
tracker.queueTurnContext(current);
|
|
100
|
+
tracker.beginTurn(1001);
|
|
101
|
+
|
|
102
|
+
assert.equal(tracker.findActiveReplyTargetMismatch("planner-id", 1002), null);
|
|
103
|
+
assert.equal(tracker.findActiveReplyTargetMismatch("planner", 1002)?.message.id, "ask-1");
|
|
104
|
+
assert.equal(tracker.findActiveReplyTargetMismatch("repo-root", 1002)?.message.id, "ask-1");
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
test("active ask context does not trust sender names as destination identity", () => {
|
|
108
|
+
const tracker = new ReplyTracker();
|
|
109
|
+
const current = tracker.recordIncomingMessage(createSession("asker-session", "root-session"), createMessage("ask-1", "Need a reply"), 1000);
|
|
110
|
+
tracker.queueTurnContext(current);
|
|
111
|
+
tracker.beginTurn(1001);
|
|
112
|
+
|
|
113
|
+
assert.equal(tracker.findActiveReplyTargetMismatch("root-session", 1002)?.message.id, "ask-1");
|
|
114
|
+
});
|
|
115
|
+
|
|
96
116
|
test("replyTo resolves the exact pending ask", () => {
|
|
97
117
|
const tracker = new ReplyTracker();
|
|
98
118
|
tracker.recordIncomingMessage(createSession("planner-id", "planner"), createMessage("ask-1", "First"), 1000);
|
|
@@ -121,6 +121,14 @@ export class ReplyTracker {
|
|
|
121
121
|
return candidates.length === 1 ? candidates[0]! : null;
|
|
122
122
|
}
|
|
123
123
|
|
|
124
|
+
findActiveReplyTargetMismatch(to: string, now = Date.now()): IntercomContext | null {
|
|
125
|
+
this.pruneExpired(now);
|
|
126
|
+
if (!this.currentTurnContext?.message.expectsReply) {
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
return this.currentTurnContext.from.id === to ? null : this.currentTurnContext;
|
|
130
|
+
}
|
|
131
|
+
|
|
124
132
|
markReplied(replyTo: string): void {
|
|
125
133
|
this.dismissPendingAsk(replyTo);
|
|
126
134
|
}
|
|
@@ -2,6 +2,33 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.60.0] - 2026-08-31
|
|
6
|
+
|
|
7
|
+
### Highlights
|
|
8
|
+
- Ask for the runtime delegation catalog as clean rows: `subagent({ action: "list", capabilities: true })` returns compact, prompt-free capability rows and machine metadata.
|
|
9
|
+
- Timeout recovery is explainable: async status and `subagent_wait` completions report the missing/written report and changed tracked files for timed-out children with dirty worktrees.
|
|
10
|
+
- Forked children reuse prompt caches: fork-context launches stamp an OpenAI-compatible `prompt_cache_key` on provider requests.
|
|
11
|
+
- `runs.lanes` plans show up as workflow-graph stages in status and TUI views.
|
|
12
|
+
- Watchdog and single-output evidence are cheaper and kinder: home-root/entry-less repos skip untracked scans, and stat errors propagate instead of being swallowed.
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
- Add `capabilities` option to management `list`: returns executable/restricted status, restriction sources, aliases, runner (pi / external-cli / external-job with capabilities), tools (ambient, mcp-direct, mutation), model (value/fallbacks/thinking), execution (defaultAsync, timeoutMs), output, and extensions snapshot per agent, plus total restricted count and capability-ceiling sources, as versioned `details.agentCapabilities` (`details.catalog`).
|
|
16
|
+
- Emit `lanePlan` metadata from `runs.lanes` (stages, phase, label, agent, output name, structured flag) and render workflow-graph stage nodes in async status and TUI views.
|
|
17
|
+
- Stamp `prompt_cache_key` (`pi-fork:<sha256>`) on supported provider requests for fork-context children via `before_provider_request`.
|
|
18
|
+
- Project timeout-recovery evidence (termination, changed files, report status, dirty-worktree reason) into async status steps and `subagent_wait` completion output.
|
|
19
|
+
|
|
20
|
+
### Changed
|
|
21
|
+
- `runs.host` rejects per-step `cwd` with an actionable hint (use outer request cwd or a trusted `cd` in the command).
|
|
22
|
+
- Watchdog repo-change signatures skip `--untracked-files=all` for home-repo roots and repositories with no tracked entries, keeping status probes cheap and bounded.
|
|
23
|
+
- Single-output snapshots propagate non-ENOENT stat errors instead of treating every failure as "file missing".
|
|
24
|
+
- Background spawns use `windowsHide` consistently and `detached` only on non-Windows.
|
|
25
|
+
- `workflowScript` guidance documents the portability rules (no nested async helpers) and `runs.host` cwd semantics.
|
|
26
|
+
|
|
27
|
+
### Fixed
|
|
28
|
+
- "Running" spinners in the TUI advance on wall-clock time instead of only on model activity.
|
|
29
|
+
- Noisy repeated single-step status rows are suppressed in workflow status rendering.
|
|
30
|
+
- Timeout recovery summaries no longer claim a written report when the required output is missing.
|
|
31
|
+
|
|
5
32
|
## [0.59.0] - 2026-08-28
|
|
6
33
|
|
|
7
34
|
### 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`.
|
|
@@ -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
|
-
|
|
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
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-subagents",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.60.0",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "pi-subagents",
|
|
9
|
-
"version": "0.
|
|
9
|
+
"version": "0.60.0",
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"acorn": "8.18.0",
|
|
@@ -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
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
`skills/
|
|
16
|
-
|
|
17
|
-
## Roster
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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.
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
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.
|