pi-subagents 0.77.0 → 0.78.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 (152) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/agents/evidence-auditor.md +1 -0
  3. package/agents/oracle.md +1 -0
  4. package/agents/reviewer.md +1 -0
  5. package/docs/agents.md +1 -1
  6. package/docs/configuration.md +21 -5
  7. package/docs/extension-api.md +5 -1
  8. package/docs/observability.md +2 -0
  9. package/docs/tool-reference.md +2 -2
  10. package/docs/workflows.md +2 -2
  11. package/package.json +1 -1
  12. package/skills/pi-subagents/SKILL.md +1 -1
  13. package/skills/pi-subagents/references/multi-lane-orchestration.md +1 -1
  14. package/src/api/external-runs.d.ts.map +1 -1
  15. package/src/api/external-runs.js +5 -4
  16. package/src/api/external-runs.js.map +1 -1
  17. package/src/api/preflight.js +1 -1
  18. package/src/api/preflight.js.map +1 -1
  19. package/src/extension/active-runs-prompt.d.ts +8 -0
  20. package/src/extension/active-runs-prompt.d.ts.map +1 -0
  21. package/src/extension/active-runs-prompt.js +30 -0
  22. package/src/extension/active-runs-prompt.js.map +1 -0
  23. package/src/extension/config.d.ts.map +1 -1
  24. package/src/extension/config.js +6 -0
  25. package/src/extension/config.js.map +1 -1
  26. package/src/extension/declaration-pinning.d.ts +5 -0
  27. package/src/extension/declaration-pinning.d.ts.map +1 -1
  28. package/src/extension/declaration-pinning.js +9 -2
  29. package/src/extension/declaration-pinning.js.map +1 -1
  30. package/src/extension/index.d.ts +0 -1
  31. package/src/extension/index.d.ts.map +1 -1
  32. package/src/extension/index.js +56 -14
  33. package/src/extension/index.js.map +1 -1
  34. package/src/extension/tool-activation.d.ts.map +1 -1
  35. package/src/extension/tool-activation.js +4 -2
  36. package/src/extension/tool-activation.js.map +1 -1
  37. package/src/intercom/native-supervisor-channel.d.ts +16 -1
  38. package/src/intercom/native-supervisor-channel.d.ts.map +1 -1
  39. package/src/intercom/native-supervisor-channel.js +25 -6
  40. package/src/intercom/native-supervisor-channel.js.map +1 -1
  41. package/src/runs/background/active-async-capacity.d.ts +2 -1
  42. package/src/runs/background/active-async-capacity.d.ts.map +1 -1
  43. package/src/runs/background/active-async-capacity.js +10 -6
  44. package/src/runs/background/active-async-capacity.js.map +1 -1
  45. package/src/runs/background/async-execution.js +3 -3
  46. package/src/runs/background/async-execution.js.map +1 -1
  47. package/src/runs/background/async-resume.d.ts.map +1 -1
  48. package/src/runs/background/async-resume.js +3 -1
  49. package/src/runs/background/async-resume.js.map +1 -1
  50. package/src/runs/background/chain-root-attachment.js +4 -4
  51. package/src/runs/background/chain-root-attachment.js.map +1 -1
  52. package/src/runs/background/control-channel.d.ts +1 -0
  53. package/src/runs/background/control-channel.d.ts.map +1 -1
  54. package/src/runs/background/control-channel.js +27 -3
  55. package/src/runs/background/control-channel.js.map +1 -1
  56. package/src/runs/background/notify.d.ts +1 -1
  57. package/src/runs/background/notify.d.ts.map +1 -1
  58. package/src/runs/background/notify.js +8 -4
  59. package/src/runs/background/notify.js.map +1 -1
  60. package/src/runs/background/run-child-session.d.ts.map +1 -1
  61. package/src/runs/background/run-child-session.js +7 -14
  62. package/src/runs/background/run-child-session.js.map +1 -1
  63. package/src/runs/background/runner-aliases.d.ts.map +1 -1
  64. package/src/runs/background/runner-aliases.js +11 -8
  65. package/src/runs/background/runner-aliases.js.map +1 -1
  66. package/src/runs/background/subagent-runner.d.ts.map +1 -1
  67. package/src/runs/background/subagent-runner.js +198 -279
  68. package/src/runs/background/subagent-runner.js.map +1 -1
  69. package/src/runs/background/workflow-terminal-proof.d.ts +1 -1
  70. package/src/runs/background/workflow-terminal-proof.d.ts.map +1 -1
  71. package/src/runs/background/workflow-terminal-proof.js +12 -3
  72. package/src/runs/background/workflow-terminal-proof.js.map +1 -1
  73. package/src/runs/foreground/async-stop-action.d.ts.map +1 -1
  74. package/src/runs/foreground/async-stop-action.js +6 -7
  75. package/src/runs/foreground/async-stop-action.js.map +1 -1
  76. package/src/runs/foreground/execution.d.ts.map +1 -1
  77. package/src/runs/foreground/execution.js +51 -55
  78. package/src/runs/foreground/execution.js.map +1 -1
  79. package/src/runs/foreground/subagent-executor.d.ts.map +1 -1
  80. package/src/runs/foreground/subagent-executor.js +26 -35
  81. package/src/runs/foreground/subagent-executor.js.map +1 -1
  82. package/src/runs/shared/effective-system-prompt.d.ts +4 -4
  83. package/src/runs/shared/effective-system-prompt.d.ts.map +1 -1
  84. package/src/runs/shared/effective-system-prompt.js +5 -4
  85. package/src/runs/shared/effective-system-prompt.js.map +1 -1
  86. package/src/runs/shared/external-cli-runner.d.ts.map +1 -1
  87. package/src/runs/shared/external-cli-runner.js +3 -2
  88. package/src/runs/shared/external-cli-runner.js.map +1 -1
  89. package/src/runs/shared/model-resolution-diagnostic.d.ts +7 -5
  90. package/src/runs/shared/model-resolution-diagnostic.d.ts.map +1 -1
  91. package/src/runs/shared/model-resolution-diagnostic.js +13 -10
  92. package/src/runs/shared/model-resolution-diagnostic.js.map +1 -1
  93. package/src/runs/shared/orca-progress-tabs.js +1 -1
  94. package/src/runs/shared/orca-progress-tabs.js.map +1 -1
  95. package/src/runs/shared/partial-output.d.ts +7 -0
  96. package/src/runs/shared/partial-output.d.ts.map +1 -1
  97. package/src/runs/shared/partial-output.js +7 -0
  98. package/src/runs/shared/partial-output.js.map +1 -1
  99. package/src/runs/shared/single-output.d.ts +11 -1
  100. package/src/runs/shared/single-output.d.ts.map +1 -1
  101. package/src/runs/shared/single-output.js +48 -26
  102. package/src/runs/shared/single-output.js.map +1 -1
  103. package/src/runs/shared/structured-output.d.ts +2 -0
  104. package/src/runs/shared/structured-output.d.ts.map +1 -1
  105. package/src/runs/shared/structured-output.js +9 -0
  106. package/src/runs/shared/structured-output.js.map +1 -1
  107. package/src/runs/shared/subagent-prompt-runtime.d.ts +29 -0
  108. package/src/runs/shared/subagent-prompt-runtime.d.ts.map +1 -1
  109. package/src/runs/shared/subagent-prompt-runtime.js +87 -2
  110. package/src/runs/shared/subagent-prompt-runtime.js.map +1 -1
  111. package/src/runs/shared/tool-budget.js +1 -1
  112. package/src/runs/shared/tool-budget.js.map +1 -1
  113. package/src/shared/child-transcript.js +1 -1
  114. package/src/shared/child-transcript.js.map +1 -1
  115. package/src/shared/extension-context.d.ts +5 -0
  116. package/src/shared/extension-context.d.ts.map +1 -1
  117. package/src/shared/extension-context.js +7 -0
  118. package/src/shared/extension-context.js.map +1 -1
  119. package/src/shared/parent-wake.d.ts +6 -0
  120. package/src/shared/parent-wake.d.ts.map +1 -1
  121. package/src/shared/parent-wake.js +11 -0
  122. package/src/shared/parent-wake.js.map +1 -1
  123. package/src/shared/types.d.ts +7 -8
  124. package/src/shared/types.d.ts.map +1 -1
  125. package/src/shared/types.js +4 -4
  126. package/src/shared/types.js.map +1 -1
  127. package/src/shared/utils.d.ts +2 -0
  128. package/src/shared/utils.d.ts.map +1 -1
  129. package/src/shared/utils.js +2 -0
  130. package/src/shared/utils.js.map +1 -1
  131. package/src/slash/slash-commands.d.ts.map +1 -1
  132. package/src/slash/slash-commands.js +20 -9
  133. package/src/slash/slash-commands.js.map +1 -1
  134. package/src/slash/subagents-admin.d.ts.map +1 -1
  135. package/src/slash/subagents-admin.js +3 -2
  136. package/src/slash/subagents-admin.js.map +1 -1
  137. package/src/tui/fleet-status.d.ts +5 -0
  138. package/src/tui/fleet-status.d.ts.map +1 -1
  139. package/src/tui/fleet-status.js +24 -3
  140. package/src/tui/fleet-status.js.map +1 -1
  141. package/src/tui/fleet.js +2 -2
  142. package/src/tui/fleet.js.map +1 -1
  143. package/src/watchdog/change-signature.d.ts.map +1 -1
  144. package/src/watchdog/change-signature.js +1 -3
  145. package/src/watchdog/change-signature.js.map +1 -1
  146. package/src/workflows/scripted-workflow.d.ts.map +1 -1
  147. package/src/workflows/scripted-workflow.js +13 -4
  148. package/src/workflows/scripted-workflow.js.map +1 -1
  149. package/src/runs/shared/run-history.d.ts +0 -67
  150. package/src/runs/shared/run-history.d.ts.map +0 -1
  151. package/src/runs/shared/run-history.js +0 -270
  152. package/src/runs/shared/run-history.js.map +0 -1
@@ -27,7 +27,6 @@ import { normalizeParentModel, resolveEffectiveSubagentModel, resolveModelOrigin
27
27
  import { projectChainOutputSchemas, resolveEffectiveOutputSchema } from "../shared/child-launch-plan.js";
28
28
  import { formatRetainedChildren, listRetainedChildren } from "../background/retained-children.js";
29
29
  import { resolveModelScopesForAgent } from "../shared/model-scope.js";
30
- import { recordRun } from "../shared/run-history.js";
31
30
  import { getStepAgents, isParallelStep, isDynamicParallelStep, resolveExistingReadPaths, } from "../../shared/settings.js";
32
31
  import { normalizeSkillInput } from "../../agents/skills.js";
33
32
  import { buildAsyncRunnerSteps, DEFAULT_ASYNC_TIMEOUT_MS, executeAsyncChain, executeAsyncSingle, formatAsyncStartedMessage, isAsyncAvailable, workflowAwaitedAsyncResultPath } from "../background/async-execution.js";
@@ -637,6 +636,7 @@ function resolveForegroundResumeTarget(params, state, options = {}) {
637
636
  ...(child.thinking ? { thinking: child.thinking } : {}),
638
637
  ...(child.launchContractDigest ? { launchContractDigest: child.launchContractDigest } : {}),
639
638
  ...(child.resumeContract ? { resumeContract: child.resumeContract } : {}),
639
+ ...(child.savedOutputPath ? { savedOutputPath: child.savedOutputPath } : {}),
640
640
  ...(child.extensionBindings ? { extensionBindings: normalizeExtensionBindings(child.extensionBindings).value } : {}),
641
641
  ...(child.requiredExtensions ? { requiredExtensions: child.requiredExtensions } : {}),
642
642
  ...(child.capabilityCeiling ? { capabilityCeiling: child.capabilityCeiling } : {}),
@@ -1882,6 +1882,13 @@ async function resumeAsyncRun(input) {
1882
1882
  const availableModels = input.ctx.modelRegistry.getAvailable().map(toModelInfo);
1883
1883
  const parentModel = input.parentModel;
1884
1884
  const revivalAsyncDir = path.join(DIRS.async, runId);
1885
+ const revivalOutputBaseDir = resolveSingleRunOutputBaseDir(input.deps, artifactsDir, runId);
1886
+ const inheritedOutput = foregroundContract?.output ?? recoveryDescriptor?.outputPath;
1887
+ // The original run owns its saved output, so a resume without its own output writes next to it instead of over it.
1888
+ // Workflow resumes are routed by the workflow's output claims instead.
1889
+ const inheritedOutputPath = input.params.output === undefined && input.params.workflowParentRunId === undefined
1890
+ ? (target.source === "foreground" ? target.savedOutputPath : undefined) ?? resolveSingleOutputPath(inheritedOutput, input.requestCwd, effectiveCwd, revivalOutputBaseDir)
1891
+ : undefined;
1885
1892
  const result = await executeAsyncSingle(runId, compactOptional({
1886
1893
  agent: target.agent,
1887
1894
  task: buildRevivedAsyncTask(target, effectiveFollowUp),
@@ -1929,7 +1936,7 @@ async function resumeAsyncRun(input) {
1929
1936
  thinkingCeiling: recoveryDescriptor?.thinkingCeiling ?? ("thinkingCeiling" in target ? target.thinkingCeiling : undefined),
1930
1937
  extensionBindings: recoveryDescriptor?.extensionBindings ?? ("extensionBindings" in target ? target.extensionBindings : undefined),
1931
1938
  requiredExtensions: recoveryDescriptor?.requiredExtensions ?? target.requiredExtensions,
1932
- outputBaseDir: resolveSingleRunOutputBaseDir(input.deps, artifactsDir, runId),
1939
+ outputBaseDir: revivalOutputBaseDir,
1933
1940
  maxSubagentDepth: recoveryDescriptor?.maxSubagentDepth ?? resolveCurrentMaxSubagentDepth(input.deps.config.maxSubagentDepth, input.deps.childRuntime),
1934
1941
  waitToolEnabled: input.deps.waitToolEnabled,
1935
1942
  waitToolDefaultTimeoutMs: input.deps.waitToolDefaultTimeoutMs,
@@ -1948,7 +1955,7 @@ async function resumeAsyncRun(input) {
1948
1955
  controlIntercomTarget: intercomBridge.active ? intercomBridge.orchestratorTarget : undefined,
1949
1956
  childIntercomTarget: intercomBridge.active ? (agent, index) => resolveSubagentIntercomTarget(runId, agent, index) : undefined,
1950
1957
  availableModels,
1951
- output: input.params.output !== undefined ? input.params.output : foregroundContract?.output ?? recoveryDescriptor?.outputPath,
1958
+ output: input.params.output !== undefined ? input.params.output : inheritedOutputPath ? suffixedOutputPath(inheritedOutputPath, runId.slice(0, 8)) : inheritedOutput,
1952
1959
  outputMode: input.params.outputMode ?? foregroundContract?.outputMode ?? recoveryDescriptor?.outputMode,
1953
1960
  outputClaimPath: input.params.workflowOutputClaimPath,
1954
1961
  ...(agentContract ? { agentContract } : {}),
@@ -3231,11 +3238,14 @@ export function sanitizeRunPathSegment(value, maxBytes = 120) {
3231
3238
  function resolveSingleRunOutputBaseDir(deps, artifactsDir, runId) {
3232
3239
  return resolveConfiguredSingleRunOutputBaseDir(deps) ?? path.join(artifactsDir, "outputs", sanitizeRunPathSegment(runId));
3233
3240
  }
3241
+ /** `<dir>/<name>.<suffix><ext>` next to outputPath, with `.md` when it has no extension. */
3242
+ function suffixedOutputPath(outputPath, suffix) {
3243
+ const parsed = path.parse(outputPath);
3244
+ return path.join(parsed.dir, `${parsed.name}.${suffix}${parsed.ext || ".md"}`);
3245
+ }
3234
3246
  function workflowChildDefaultOutput(aggregateOutputPath, artifactsDir, workflowRunId, workflowKey) {
3235
- if (aggregateOutputPath) {
3236
- const parsed = path.parse(aggregateOutputPath);
3237
- return path.join(parsed.dir, `${parsed.name}.${workflowKey}${parsed.ext || ".md"}`);
3238
- }
3247
+ if (aggregateOutputPath)
3248
+ return suffixedOutputPath(aggregateOutputPath, workflowKey);
3239
3249
  return path.join(artifactsDir, "outputs", sanitizeRunPathSegment(workflowRunId), `${workflowKey}.md`);
3240
3250
  }
3241
3251
  function workflowHostCommandRunner(input) {
@@ -3328,9 +3338,8 @@ function resolveWorkflowChildOutputPath(input) {
3328
3338
  const recoveryOutput = "recoveryDescriptor" in target ? target.recoveryDescriptor?.outputPath : undefined;
3329
3339
  if (hasExplicitOutput)
3330
3340
  return { path: recoveryOutput, inherited: false };
3331
- // An output-less foreground resume reuses its recorded output; only an absolute path is known before the new run id exists.
3332
- const foregroundOutput = target.source === "foreground" ? target.resumeContract?.output : undefined;
3333
- return { path: recoveryOutput, inherited: false, resumedOutput: recoveryOutput ?? (typeof foregroundOutput === "string" && path.isAbsolute(foregroundOutput) ? foregroundOutput : undefined) };
3341
+ const savedPath = recoveryOutput ?? (target.source === "foreground" ? target.savedOutputPath ?? resolveSingleOutputPath(target.resumeContract?.output, input.ctxCwd) : undefined);
3342
+ return { inherited: false, ...(savedPath ? { resumedSavedPath: savedPath } : {}) };
3334
3343
  }
3335
3344
  const childCwd = resolveWorkflowChildLocalCwd(input);
3336
3345
  let agentOutput;
@@ -3370,10 +3379,12 @@ function workflowChildOutputClaims(input) {
3370
3379
  }
3371
3380
  const overrides = new Map();
3372
3381
  for (const entry of resolvedEntries) {
3373
- // An output-less resume keeps its retained path unless an earlier child of this workflow already owns it.
3374
- const resumeCollides = entry.resumedOutput !== undefined && input.claimedOutputPaths.has(resolveWorkflowHostOutputClaimPath(entry.resumedOutput));
3375
- if (resumeCollides || (entry.inherited && entry.path && (paths.get(resolveWorkflowHostOutputClaimPath(entry.path)) ?? 0) > 1)) {
3376
- const output = workflowChildDefaultOutput(input.aggregateOutputPath, input.artifactsDir, input.workflowRunId, entry.key);
3382
+ // The resumed run owns the report it saved, inside or outside this workflow, so an output-less resume writes its own.
3383
+ if (entry.resumedSavedPath || (entry.inherited && entry.path && (paths.get(resolveWorkflowHostOutputClaimPath(entry.path)) ?? 0) > 1)) {
3384
+ let output = workflowChildDefaultOutput(input.aggregateOutputPath, input.artifactsDir, input.workflowRunId, entry.key);
3385
+ // A rerun of the same workflow and key generates the very file the resumed run saved.
3386
+ if (entry.resumedSavedPath && resolveWorkflowHostOutputClaimPath(output) === resolveWorkflowHostOutputClaimPath(entry.resumedSavedPath))
3387
+ output = suffixedOutputPath(output, input.workflowRunId.slice(0, 8));
3377
3388
  overrides.set(entry.key, output);
3378
3389
  entry.path = output;
3379
3390
  }
@@ -3390,16 +3401,6 @@ function workflowChildOutputClaims(input) {
3390
3401
  claims.set(claimPath, key);
3391
3402
  childClaims.set(key, claimPath);
3392
3403
  }
3393
- // Record a discovered output-less resume path for later admissions without adding same-batch duplicate errors.
3394
- for (const { key, path: resolved, resumedOutput } of resolvedEntries) {
3395
- if (resolved || !resumedOutput)
3396
- continue;
3397
- const claimPath = resolveWorkflowHostOutputClaimPath(resumedOutput);
3398
- if (claims.has(claimPath))
3399
- continue;
3400
- claims.set(claimPath, key);
3401
- childClaims.set(key, claimPath);
3402
- }
3403
3404
  return { claims, childClaims, overrides };
3404
3405
  }
3405
3406
  function applyWorkflowChildOutputClaims(target, claims) {
@@ -3622,7 +3623,6 @@ async function runSinglePath(data, deps) {
3622
3623
  if (shouldForkAgent(contextPolicy, params.agent)) {
3623
3624
  task = wrapForkTask(task);
3624
3625
  }
3625
- const cleanTask = task;
3626
3626
  const outputPath = resolveSingleOutputPath(effectiveOutput, ctx.cwd, singleCwd, resolveSingleRunOutputBaseDir(deps, artifactsDir, runId));
3627
3627
  const validationError = validateFileOnlyOutputMode(effectiveOutputMode, outputPath, `Single run (${params.agent})`);
3628
3628
  if (validationError) {
@@ -3839,7 +3839,6 @@ async function runSinglePath(data, deps) {
3839
3839
  }
3840
3840
  }
3841
3841
  }
3842
- recordRun(params.agent, cleanTask, result.exitCode, result.progressSummary?.durationMs ?? 0, result);
3843
3842
  },
3844
3843
  timeoutMs: data.timeoutMs,
3845
3844
  deadlineAt,
@@ -3880,9 +3879,6 @@ async function runSinglePath(data, deps) {
3880
3879
  finishTrackedForegroundChild();
3881
3880
  }
3882
3881
  }
3883
- if (!r.detached) {
3884
- recordRun(params.agent, cleanTask, r.exitCode, r.progressSummary?.durationMs ?? 0, r);
3885
- }
3886
3882
  let worktreeHandoff;
3887
3883
  if (worktreeSetup) {
3888
3884
  worktreeHandoff = r.detached
@@ -4820,12 +4816,7 @@ export function createSubagentExecutor(deps) {
4820
4816
  if (launchBlockingErrors.length > 0) {
4821
4817
  return buildRequestedModeError(requestParams, `Workflow '${_id}' validation failed before child launch; no children launched. ${launchBlockingErrors.map((error) => error.message).join(" ")}`);
4822
4818
  }
4823
- // A package chain's per-step stop check defeats static launch counting; runtime fan-out enforcement still applies.
4824
- const structuredResource = workflowResource?.provenance.name === "chain" || workflowResource?.provenance.name === "tasks";
4825
- for (const warning of workflowValidation.warnings ?? []) {
4826
- if (!(structuredResource && warning.kind === "dynamic-spawn-count"))
4827
- console.warn(`[pi-subagents] ${warning.message}`);
4828
- }
4819
+ // Validation warnings belong to the validate action; a launch does not repeat them on every run.
4829
4820
  const acceptanceErrors = validateAcceptanceInput(requestParams.acceptance);
4830
4821
  if (acceptanceErrors.length > 0)
4831
4822
  return buildRequestedModeError(requestParams, acceptanceErrors.join(" "));