pi-subagents 0.63.0 → 0.65.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 (107) hide show
  1. package/CHANGELOG.md +57 -1
  2. package/README.md +2 -2
  3. package/agents/reviewer.md +1 -1
  4. package/agents/scout.md +1 -1
  5. package/docs/agents.md +18 -16
  6. package/docs/configuration.md +7 -15
  7. package/docs/extension-api.md +15 -6
  8. package/docs/missions.md +2 -0
  9. package/docs/observability.md +10 -12
  10. package/docs/tool-reference.md +7 -6
  11. package/docs/watchdog.md +92 -114
  12. package/docs/workflows.md +5 -3
  13. package/package.json +3 -4
  14. package/skills/pi-subagents/references/constraints-and-recipes.md +1 -1
  15. package/skills/pi-subagents/references/execution-controls.md +6 -5
  16. package/src/agents/agent-management.ts +47 -15
  17. package/src/api/capability-ceiling.ts +0 -1
  18. package/src/api/{pi-args.ts → child-tool-plan.ts} +1 -1
  19. package/src/api/preflight.ts +2 -3
  20. package/src/extension/doctor.ts +2 -10
  21. package/src/extension/fanout-child.ts +9 -11
  22. package/src/extension/index.ts +27 -5
  23. package/src/extension/public-execution.ts +14 -0
  24. package/src/extension/rpc.ts +3 -2
  25. package/src/extension/schemas.ts +2 -1
  26. package/src/extension/tool-description.ts +9 -8
  27. package/src/intercom/native-supervisor-channel.ts +138 -60
  28. package/src/intercom/supervisor-ui.ts +243 -0
  29. package/src/runs/background/async-execution.ts +46 -24
  30. package/src/runs/background/async-job-tracker.ts +11 -0
  31. package/src/runs/background/async-resume.ts +11 -2
  32. package/src/runs/background/control-channel.ts +2 -204
  33. package/src/runs/background/notify.ts +41 -2
  34. package/src/runs/background/process-terminal.ts +1 -1
  35. package/src/runs/background/run-child-session.ts +613 -0
  36. package/src/runs/background/run-status.ts +0 -1
  37. package/src/runs/background/runner-aliases.ts +125 -0
  38. package/src/runs/background/runner-child-sessions.ts +31 -0
  39. package/src/runs/background/scheduled-runs.ts +18 -4
  40. package/src/runs/background/subagent-runner.ts +203 -898
  41. package/src/runs/foreground/async-steering-action.ts +1 -17
  42. package/src/runs/foreground/execution.ts +196 -378
  43. package/src/runs/foreground/foreground-control.ts +4 -0
  44. package/src/runs/foreground/subagent-executor.ts +121 -58
  45. package/src/runs/foreground/workflow-foreground-steering.ts +24 -98
  46. package/src/runs/shared/abort-recovery.ts +3 -3
  47. package/src/runs/shared/acceptance.ts +10 -0
  48. package/src/runs/shared/async-status-projection.ts +11 -43
  49. package/src/runs/shared/capability-ceiling.ts +1 -2
  50. package/src/runs/shared/child-hooks.ts +25 -0
  51. package/src/runs/shared/child-identity.ts +13 -2
  52. package/src/runs/shared/child-launch.ts +314 -0
  53. package/src/runs/shared/child-lifecycle.ts +25 -0
  54. package/src/runs/shared/child-runtime-config.ts +126 -0
  55. package/src/runs/shared/child-session.ts +342 -0
  56. package/src/runs/shared/child-tool-plan.ts +530 -0
  57. package/src/runs/shared/claude-code-adapter.ts +5 -1
  58. package/src/runs/shared/completion-guard.ts +1 -1
  59. package/src/runs/shared/external-cli-preflight.ts +16 -0
  60. package/src/runs/shared/mcp-direct-tool-allowlist.ts +5 -4
  61. package/src/runs/shared/model-exclusions.ts +82 -14
  62. package/src/runs/shared/model-fallback.ts +47 -4
  63. package/src/runs/shared/nested-events.ts +29 -45
  64. package/src/runs/shared/nested-path.ts +0 -14
  65. package/src/runs/shared/orca-progress-tabs.ts +12 -7
  66. package/src/runs/shared/parallel-utils.ts +0 -2
  67. package/src/runs/shared/permissions.ts +0 -13
  68. package/src/runs/shared/process-signal.ts +4 -1
  69. package/src/runs/shared/run-fanout-budget.ts +0 -13
  70. package/src/runs/shared/runtime-acknowledged-extensions.ts +0 -27
  71. package/src/runs/shared/structured-output.ts +17 -4
  72. package/src/runs/shared/subagent-control.ts +6 -2
  73. package/src/runs/shared/subagent-prompt-runtime.ts +87 -384
  74. package/src/runs/shared/tool-availability.ts +18 -62
  75. package/src/runs/shared/tool-budget.ts +0 -14
  76. package/src/runs/shared/worktree-cleanup-plan.ts +25 -6
  77. package/src/runs/shared/worktree.ts +117 -30
  78. package/src/shared/child-session-name.ts +1 -1
  79. package/src/shared/jsonl-writer.ts +11 -0
  80. package/src/shared/thinking-ceiling.ts +0 -6
  81. package/src/shared/types.ts +64 -30
  82. package/src/shared/utils.ts +3 -4
  83. package/src/slash/slash-commands.ts +0 -6
  84. package/src/tui/fleet.ts +0 -1
  85. package/src/tui/render.ts +238 -31
  86. package/src/watchdog/child-status.ts +54 -34
  87. package/src/watchdog/diff-tool.ts +77 -0
  88. package/src/watchdog/emission-guard.ts +5 -3
  89. package/src/watchdog/guidance.ts +20 -0
  90. package/src/watchdog/register-child.ts +28 -25
  91. package/src/watchdog/register-main.ts +10 -9
  92. package/src/watchdog/render.ts +4 -5
  93. package/src/watchdog/review.ts +15 -4
  94. package/src/watchdog/rules.ts +70 -0
  95. package/src/watchdog/runtime.ts +75 -92
  96. package/src/watchdog/scope.ts +0 -11
  97. package/src/watchdog/settings.ts +48 -104
  98. package/src/watchdog/types.ts +18 -32
  99. package/src/watchdog/warning-format.ts +0 -1
  100. package/src/workflows/chat-progress.ts +3 -2
  101. package/src/workflows/scripted-workflow.ts +48 -1
  102. package/src/workflows/workflow-checklist.ts +10 -12
  103. package/src/workflows/workflow-preflight.ts +28 -1
  104. package/src/runs/shared/child-protocol.ts +0 -415
  105. package/src/runs/shared/pi-args.ts +0 -1062
  106. package/src/runs/shared/subagent-startup-retry.ts +0 -116
  107. package/src/shared/post-exit-stdio-guard.ts +0 -85
@@ -14,7 +14,7 @@ import {
14
14
  createCompletionBatcher,
15
15
  resolveCompletionBatchConfig,
16
16
  } from "./completion-batcher.ts";
17
- import { SUBAGENT_ASYNC_COMPLETE_EVENT, SUBAGENT_FOREGROUND_COMPLETE_EVENT, type ParallelHandoffReference, type ScheduleOrigin, type SubagentState } from "../../shared/types.ts";
17
+ import { SUBAGENT_ASYNC_COMPLETE_EVENT, SUBAGENT_FOREGROUND_COMPLETE_EVENT, type ChildWatchdogProgress, type ChildWatchdogWarningSummary, type ParallelHandoffReference, type ScheduleOrigin, type SubagentState } from "../../shared/types.ts";
18
18
  import { safeTerminalText } from "../../shared/display-text.ts";
19
19
  import { resolveSubagentResultStatus } from "../../intercom/result-intercom.ts";
20
20
  import { isUnexplainedProcessSignal } from "../shared/process-signal.ts";
@@ -31,6 +31,8 @@ export interface SubagentNotifyChildOutput {
31
31
  previewUnavailableReason?: string;
32
32
  }
33
33
 
34
+ export type SubagentNotifyWatchdogBlocker = Pick<ChildWatchdogWarningSummary, "summary" | "addressed" | "stalemate"> & { agent: string };
35
+
34
36
  export interface SubagentNotifyDetails {
35
37
  agent: string;
36
38
  status: "completed" | "failed" | "paused" | "stopped";
@@ -47,6 +49,7 @@ export interface SubagentNotifyDetails {
47
49
  handoffPath?: string;
48
50
  /** Present when a durable schedule launched the run. */
49
51
  scheduleOrigin?: ScheduleOrigin;
52
+ watchdogBlockers?: SubagentNotifyWatchdogBlocker[];
50
53
  }
51
54
 
52
55
  export interface CompletionNotification {
@@ -85,7 +88,9 @@ export interface CompletionNotification {
85
88
  timedOut?: boolean;
86
89
  stopped?: boolean;
87
90
  turnBudgetExceeded?: boolean;
91
+ watchdog?: ChildWatchdogProgress;
88
92
  }>;
93
+ watchdog?: ChildWatchdogProgress;
89
94
  timestamp?: number;
90
95
  durationMs?: number;
91
96
  cwd?: string;
@@ -249,9 +254,28 @@ function formatCorrelationLines(details: SubagentNotifyDetails): string[] {
249
254
  ].filter((line): line is string => line !== undefined);
250
255
  }
251
256
 
257
+ const WATCHDOG_BLOCKERS_HEADING = "Watchdog blockers:";
258
+
259
+ function formatWatchdogBlockerLines(details: SubagentNotifyDetails): string[] {
260
+ if (!details.watchdogBlockers?.length) return [];
261
+ return [WATCHDOG_BLOCKERS_HEADING, ...details.watchdogBlockers.map((blocker) => `- ${blocker.agent}: ${blocker.summary} (${blocker.stalemate ? "stalemate" : blocker.addressed ? "addressed" : "unaddressed"})`)];
262
+ }
263
+
264
+ // A stalemate blocker parses back as unaddressed; acceptance treats both as unresolved.
265
+ function parseWatchdogBlockerLines(lines: string[]): SubagentNotifyWatchdogBlocker[] {
266
+ const blockers: SubagentNotifyWatchdogBlocker[] = [];
267
+ for (const line of lines) {
268
+ const match = line.match(/^- (.+?): (.+) \((addressed|unaddressed|stalemate)\)$/);
269
+ if (!match) break;
270
+ blockers.push({ agent: match[1]!, summary: match[2]!, addressed: match[3] === "addressed", stalemate: match[3] === "stalemate" });
271
+ }
272
+ return blockers;
273
+ }
274
+
252
275
  export function formatSingleCompletion(details: SubagentNotifyDetails): string {
253
276
  const sessionLine = formatSessionLine(details);
254
277
  const correlationLines = formatCorrelationLines(details);
278
+ const watchdogLines = formatWatchdogBlockerLines(details);
255
279
  const taskKind = details.source === "foreground" ? "Detached foreground task" : "Background task";
256
280
  const scheduleLine = details.scheduleOrigin
257
281
  ? `Scheduled run from **${details.scheduleOrigin.name ?? details.scheduleOrigin.id}** (schedule ${details.scheduleOrigin.id}).`
@@ -262,6 +286,7 @@ export function formatSingleCompletion(details: SubagentNotifyDetails): string {
262
286
  scheduleLine,
263
287
  scheduleLine ? "" : undefined,
264
288
  formatResultPreview(details),
289
+ ...(watchdogLines.length ? ["", ...watchdogLines] : []),
265
290
  details.handoffPath ? "" : undefined,
266
291
  details.handoffPath ? `Parallel handoff: ${details.handoffPath}` : undefined,
267
292
  correlationLines.length && !details.handoffPath ? "" : undefined,
@@ -300,7 +325,9 @@ export function parseSubagentNotifyContent(content: string): SubagentNotifyDetai
300
325
  const workflowRunIndex = body.findIndex((line) => line.startsWith("Workflow run: "));
301
326
  const childRunsIndex = body.findIndex((line) => line.startsWith("Child runs: "));
302
327
  const reconciledIndex = body.findIndex((line) => line.startsWith("Reconciled detached child: "));
303
- const metadataIndexes = [sessionIndex, handoffIndex, workflowRunIndex, childRunsIndex, reconciledIndex].filter((index) => index >= 0);
328
+ const watchdogIndex = body.findIndex((line) => line === WATCHDOG_BLOCKERS_HEADING);
329
+ const watchdogBlockers = watchdogIndex >= 0 ? parseWatchdogBlockerLines(body.slice(watchdogIndex + 1)) : [];
330
+ const metadataIndexes = [sessionIndex, handoffIndex, workflowRunIndex, childRunsIndex, reconciledIndex, watchdogIndex].filter((index) => index >= 0);
304
331
  const firstMetadataIndex = metadataIndexes.length ? Math.min(...metadataIndexes) : body.length;
305
332
  const resultEnd = firstMetadataIndex > 0 && body[firstMetadataIndex - 1]?.trim() === "" ? firstMetadataIndex - 1 : firstMetadataIndex;
306
333
  const resultPreview = body.slice(0, resultEnd).join("\n").trim() || "(no output)";
@@ -336,6 +363,7 @@ export function parseSubagentNotifyContent(content: string): SubagentNotifyDetai
336
363
  ...(workflowRunId ? { workflowRunId } : {}),
337
364
  ...(childRuns?.length ? { childRuns } : {}),
338
365
  ...(reconciledFromDetachedChild ? { reconciledFromDetachedChild } : {}),
366
+ ...(watchdogBlockers.length ? { watchdogBlockers } : {}),
339
367
  ...(sessionLabel && sessionValue ? { sessionLabel, sessionValue } : {}),
340
368
  };
341
369
  }
@@ -349,6 +377,7 @@ export function formatGroupedCompletion(details: SubagentNotifyDetails[]): strin
349
377
  const sessionLine = formatSessionLine(detail);
350
378
  blocks.push(`${index + 1}. ${detail.agent}${detail.taskInfo ?? ""}${detail.scheduleOrigin ? ` — scheduled run from ${detail.scheduleOrigin.name ?? detail.scheduleOrigin.id} (schedule ${detail.scheduleOrigin.id})` : ""}`);
351
379
  blocks.push(formatResultPreview(detail));
380
+ blocks.push(...formatWatchdogBlockerLines(detail));
352
381
  if (detail.handoffPath) blocks.push(`Parallel handoff: ${detail.handoffPath}`);
353
382
  blocks.push(...formatCorrelationLines(detail));
354
383
  if (sessionLine) blocks.push(sessionLine);
@@ -462,6 +491,15 @@ export function buildCompletionDetails(result: CompletionNotification): Subagent
462
491
  })
463
492
  : undefined;
464
493
  const reconciledFromDetachedChild = typeof result.reconciledFromDetachedChild === "string" ? result.reconciledFromDetachedChild : undefined;
494
+ const watchdogBlockers: SubagentNotifyWatchdogBlocker[] = [];
495
+ const collectWatchdogBlockers = (owner: string, progress: ChildWatchdogProgress | undefined) => {
496
+ for (const warning of progress?.warnings ?? []) {
497
+ if (warning.severity !== "blocker") continue;
498
+ watchdogBlockers.push({ agent: owner, summary: warning.summary, addressed: warning.addressed, stalemate: warning.stalemate });
499
+ }
500
+ };
501
+ collectWatchdogBlockers(agent, result.watchdog);
502
+ for (const child of result.results ?? []) collectWatchdogBlockers(typeof child.agent === "string" ? child.agent : agent, child.watchdog);
465
503
  const session =
466
504
  result.shareUrl
467
505
  ? { label: "Session", value: result.shareUrl }
@@ -487,6 +525,7 @@ export function buildCompletionDetails(result: CompletionNotification): Subagent
487
525
  ...(childRuns.length ? { childRuns } : {}),
488
526
  ...(childOutputs?.length ? { childOutputs } : {}),
489
527
  ...(reconciledFromDetachedChild ? { reconciledFromDetachedChild } : {}),
528
+ ...(watchdogBlockers.length ? { watchdogBlockers } : {}),
490
529
  ...(session ? { sessionLabel: session.label, sessionValue: session.value } : {}),
491
530
  };
492
531
  }
@@ -115,7 +115,7 @@ export function writeProcessTerminalCandidate(asyncDir: string, candidate: Proce
115
115
  writePrivateAtomicJson(processTerminalCandidatePath(asyncDir), candidate);
116
116
  }
117
117
 
118
- /** Establish ownership before authorizing a runner to launch any child process. */
118
+ /** Establish ownership before authorizing a runner to start any child session. */
119
119
  export function initializeProcessTerminal(asyncDir: string, runId: string, runnerProcessInstanceId: string): void {
120
120
  writeProcessTerminalCandidate(asyncDir, {
121
121
  version: 1,