@fitchmultz/pi-subagents 0.44.7 → 0.45.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 (947) hide show
  1. package/CHANGELOG.md +258 -7
  2. package/LICENSE +1 -0
  3. package/README.md +58 -1483
  4. package/agents/context-builder.md +19 -1
  5. package/agents/debugger.md +10 -3
  6. package/agents/delegate.md +1 -0
  7. package/agents/fixer.md +4 -1
  8. package/agents/oracle.md +13 -2
  9. package/agents/planner.md +14 -3
  10. package/agents/researcher.md +11 -2
  11. package/agents/reviewer-claude.md +11 -2
  12. package/agents/reviewer-gpt.md +12 -2
  13. package/agents/reviewer-ponytail.md +11 -1
  14. package/agents/reviewer-security.md +13 -2
  15. package/agents/reviewer.md +12 -3
  16. package/agents/scout.md +12 -1
  17. package/agents/ui-designer.md +10 -3
  18. package/agents/watcher.md +1 -0
  19. package/agents/worker.md +8 -2
  20. package/agents/writer.md +6 -3
  21. package/dist/agents/agent-defaults.js +9 -0
  22. package/dist/agents/agent-definition.js +196 -0
  23. package/dist/agents/agent-management.js +64 -905
  24. package/dist/agents/agent-scope.js +4 -2
  25. package/dist/agents/agent-selection.js +10 -5
  26. package/dist/agents/agent-serializer.js +55 -67
  27. package/dist/agents/agents.js +75 -716
  28. package/dist/agents/builtin-overrides.js +218 -0
  29. package/dist/agents/chain-serializer.js +3 -367
  30. package/dist/agents/config-values.js +52 -0
  31. package/dist/agents/discovery-paths.js +91 -0
  32. package/dist/agents/frontmatter.js +15 -5
  33. package/dist/agents/identity.js +25 -8
  34. package/dist/agents/json-chain.js +254 -0
  35. package/dist/agents/management-config.js +332 -0
  36. package/dist/agents/management-format.js +231 -0
  37. package/dist/agents/management-persistence.js +287 -0
  38. package/dist/agents/management-targets.js +136 -0
  39. package/dist/agents/management-warnings.js +81 -0
  40. package/dist/agents/markdown-chain.js +210 -0
  41. package/dist/agents/package-agents.js +154 -0
  42. package/dist/agents/skill-files.js +157 -0
  43. package/dist/agents/skill-search-paths.js +246 -0
  44. package/dist/agents/skill-types.js +1 -0
  45. package/dist/agents/skills.js +54 -499
  46. package/dist/extension/acceptance-schema.js +55 -0
  47. package/dist/extension/build-info.js +1 -1
  48. package/dist/extension/chain-schema.js +196 -0
  49. package/dist/extension/child-runtime.js +237 -0
  50. package/dist/extension/compact-tools.js +122 -51
  51. package/dist/extension/config-schema.js +29 -0
  52. package/dist/extension/config.js +27 -11
  53. package/dist/extension/control-notice-schema.js +37 -0
  54. package/dist/extension/control-notices.js +13 -6
  55. package/dist/extension/delegation-bridges.js +43 -0
  56. package/dist/extension/doctor.js +48 -25
  57. package/dist/extension/everyday-schemas.js +207 -0
  58. package/dist/extension/fanout-child.js +18 -319
  59. package/dist/extension/index.js +8 -563
  60. package/dist/extension/message-renderers.js +225 -0
  61. package/dist/extension/nested-control-inbox.js +154 -0
  62. package/dist/extension/parent-runtime.js +339 -0
  63. package/dist/extension/primary-tool.js +69 -0
  64. package/dist/extension/result-snapshot.js +22 -0
  65. package/dist/extension/runtime-reload.js +62 -0
  66. package/dist/extension/runtime-storage.js +43 -0
  67. package/dist/extension/schema-overrides.js +75 -0
  68. package/dist/extension/schemas.js +265 -336
  69. package/dist/extension/tool-input.js +27 -12
  70. package/dist/extension/tool-result.js +19 -4
  71. package/dist/history/answer-texts.js +57 -0
  72. package/dist/history/canonical-result.js +76 -43
  73. package/dist/history/canonical-selection.js +40 -0
  74. package/dist/history/database-generation.js +82 -0
  75. package/dist/history/database.js +57 -33
  76. package/dist/history/entry-ingestion.js +61 -0
  77. package/dist/history/index.js +242 -97
  78. package/dist/history/ingest.js +168 -331
  79. package/dist/history/output-digests.js +40 -0
  80. package/dist/history/preview.js +210 -0
  81. package/dist/history/prune.js +33 -0
  82. package/dist/history/queries.js +60 -349
  83. package/dist/history/query-scope.js +190 -0
  84. package/dist/history/rows.js +77 -0
  85. package/dist/history/run-projection.js +137 -0
  86. package/dist/history/run-queries.js +153 -0
  87. package/dist/history/schema.js +31 -0
  88. package/dist/history/search-queries.js +163 -0
  89. package/dist/history/selected-record.js +108 -0
  90. package/dist/history/source-file.js +45 -0
  91. package/dist/history/source-watches.js +141 -0
  92. package/dist/history/store.js +164 -153
  93. package/dist/history/text-chunks.js +169 -0
  94. package/dist/history/text.js +35 -0
  95. package/dist/history/transcript-queries.js +177 -0
  96. package/dist/history/types.js +5 -1
  97. package/dist/history/values.js +36 -0
  98. package/dist/history/wire-inputs.js +122 -0
  99. package/dist/history/wire-models.js +38 -0
  100. package/dist/history/worker-runtime.js +441 -0
  101. package/dist/history/worker.js +66 -462
  102. package/dist/intercom/intercom-bridge.js +48 -20
  103. package/dist/intercom/live-intercom.js +80 -23
  104. package/dist/intercom/nested-result-tree.js +163 -0
  105. package/dist/intercom/result-delivery.js +40 -0
  106. package/dist/intercom/result-intercom.js +178 -261
  107. package/dist/pi-intercom/agent-dir.js +7 -3
  108. package/dist/pi-intercom/async.js +27 -0
  109. package/dist/pi-intercom/bridge-ask.js +57 -0
  110. package/dist/pi-intercom/bridge-config.js +79 -0
  111. package/dist/pi-intercom/bridge-http.js +86 -0
  112. package/dist/pi-intercom/bridge-protocol.js +106 -0
  113. package/dist/pi-intercom/bridge-routes.js +64 -0
  114. package/dist/pi-intercom/bridge-session.js +416 -0
  115. package/dist/pi-intercom/bridge.js +182 -603
  116. package/dist/pi-intercom/broker/broker.js +236 -244
  117. package/dist/pi-intercom/broker/client.js +189 -304
  118. package/dist/pi-intercom/broker/connection.js +165 -0
  119. package/dist/pi-intercom/broker/framing.js +5 -3
  120. package/dist/pi-intercom/broker/paths.js +4 -1
  121. package/dist/pi-intercom/broker/pid.js +53 -25
  122. package/dist/pi-intercom/broker/snapshot-reader.js +78 -0
  123. package/dist/pi-intercom/broker/snapshots.js +188 -0
  124. package/dist/pi-intercom/broker/spawn.js +36 -25
  125. package/dist/pi-intercom/config.js +85 -71
  126. package/dist/pi-intercom/connection.js +297 -0
  127. package/dist/pi-intercom/identity.js +58 -0
  128. package/dist/pi-intercom/inbound-delivery.js +356 -0
  129. package/dist/pi-intercom/inbound-journal.js +303 -0
  130. package/dist/pi-intercom/inbound-record.js +113 -0
  131. package/dist/pi-intercom/inbound.js +179 -0
  132. package/dist/pi-intercom/index.js +79 -2933
  133. package/dist/pi-intercom/inspection.js +62 -0
  134. package/dist/pi-intercom/interview.js +236 -0
  135. package/dist/pi-intercom/lifecycle.js +168 -0
  136. package/dist/pi-intercom/message-format.js +69 -0
  137. package/dist/pi-intercom/outbound.js +304 -0
  138. package/dist/pi-intercom/peer-awareness.js +66 -0
  139. package/dist/pi-intercom/reply-tracker.js +62 -43
  140. package/dist/pi-intercom/reply-wait.js +201 -0
  141. package/dist/pi-intercom/runtime-types.js +3 -0
  142. package/dist/pi-intercom/session-events.js +180 -0
  143. package/dist/pi-intercom/session-targets.js +42 -34
  144. package/dist/pi-intercom/subagent-events.js +238 -0
  145. package/dist/pi-intercom/subagent-live-events.js +129 -86
  146. package/dist/pi-intercom/supervisor.js +282 -0
  147. package/dist/pi-intercom/tool-arguments.js +74 -0
  148. package/dist/pi-intercom/tool-registration.js +95 -0
  149. package/dist/pi-intercom/tool-results.js +38 -0
  150. package/dist/pi-intercom/tool-schemas.js +82 -0
  151. package/dist/pi-intercom/tools.js +51 -0
  152. package/dist/pi-intercom/topic-actions.js +177 -0
  153. package/dist/pi-intercom/topics.js +177 -92
  154. package/dist/pi-intercom/transport.js +1 -0
  155. package/dist/pi-intercom/types.js +151 -114
  156. package/dist/pi-intercom/ui/compose-paste.js +93 -0
  157. package/dist/pi-intercom/ui/compose.js +121 -143
  158. package/dist/pi-intercom/ui/inline-message.js +59 -59
  159. package/dist/pi-intercom/ui/message-renderers.js +147 -0
  160. package/dist/pi-intercom/ui/overlay.js +181 -0
  161. package/dist/pi-intercom/ui/session-format.js +124 -0
  162. package/dist/pi-intercom/ui/session-list.js +76 -43
  163. package/dist/pi-intercom/ui/tool-renderers.js +110 -0
  164. package/dist/pi-intercom/ui/topic-view.js +88 -0
  165. package/dist/pi-intercom/validation.js +59 -0
  166. package/dist/runs/background/async-chain-plan.js +265 -0
  167. package/dist/runs/background/async-control.js +134 -58
  168. package/dist/runs/background/async-execution.js +136 -633
  169. package/dist/runs/background/async-job-admission.js +40 -0
  170. package/dist/runs/background/async-job-projection.js +169 -0
  171. package/dist/runs/background/async-job-tracker.js +297 -327
  172. package/dist/runs/background/async-launch.js +216 -0
  173. package/dist/runs/background/async-plan.js +116 -0
  174. package/dist/runs/background/async-result-file.js +47 -23
  175. package/dist/runs/background/async-resume.js +195 -253
  176. package/dist/runs/background/async-run-discovery.js +213 -0
  177. package/dist/runs/background/async-run-location.js +135 -0
  178. package/dist/runs/background/async-run-record.js +1 -0
  179. package/dist/runs/background/async-run-repair.js +223 -0
  180. package/dist/runs/background/async-run-summary.js +1 -0
  181. package/dist/runs/background/async-single-plan.js +105 -0
  182. package/dist/runs/background/async-status-projection.js +155 -0
  183. package/dist/runs/background/async-status-render.js +117 -0
  184. package/dist/runs/background/async-status-validation.js +181 -0
  185. package/dist/runs/background/async-status.js +3 -442
  186. package/dist/runs/background/async-value.js +21 -0
  187. package/dist/runs/background/completion-dedupe.js +36 -12
  188. package/dist/runs/background/completion-delivery.js +211 -205
  189. package/dist/runs/background/completion-receipts.js +237 -0
  190. package/dist/runs/background/legacy-status-acceptance.js +34 -0
  191. package/dist/runs/background/notify.js +96 -48
  192. package/dist/runs/background/parallel-groups.js +36 -19
  193. package/dist/runs/background/result-payload.js +178 -0
  194. package/dist/runs/background/result-watcher.js +348 -339
  195. package/dist/runs/background/run-id-resolver.js +53 -33
  196. package/dist/runs/background/run-schemas.js +189 -0
  197. package/dist/runs/background/run-status-contracts.js +14 -0
  198. package/dist/runs/background/run-status-render.js +270 -0
  199. package/dist/runs/background/run-status.js +231 -339
  200. package/dist/runs/background/runner-attempt-output.js +155 -0
  201. package/dist/runs/background/runner-attempt.js +263 -0
  202. package/dist/runs/background/runner-child-executor.js +166 -0
  203. package/dist/runs/background/runner-child-observer.js +192 -0
  204. package/dist/runs/background/runner-completion-summary.js +71 -0
  205. package/dist/runs/background/runner-completion.js +211 -0
  206. package/dist/runs/background/runner-config.js +1 -0
  207. package/dist/runs/background/runner-contract.js +1 -0
  208. package/dist/runs/background/runner-dynamic.js +121 -0
  209. package/dist/runs/background/runner-finalization.js +149 -0
  210. package/dist/runs/background/runner-graph.js +68 -0
  211. package/dist/runs/background/runner-initial-status.js +60 -0
  212. package/dist/runs/background/runner-lifecycle.js +142 -0
  213. package/dist/runs/background/runner-monitor.js +309 -0
  214. package/dist/runs/background/runner-parallel.js +204 -0
  215. package/dist/runs/background/runner-prepare-step.js +86 -0
  216. package/dist/runs/background/runner-reporting.js +153 -0
  217. package/dist/runs/background/runner-status.js +148 -0
  218. package/dist/runs/background/runner-step-output.js +92 -0
  219. package/dist/runs/background/runner-step-record.js +45 -0
  220. package/dist/runs/background/runner-step.js +112 -0
  221. package/dist/runs/background/runner-streaming.js +173 -0
  222. package/dist/runs/background/runner-workflow.js +213 -0
  223. package/dist/runs/background/stale-run-reconciler.js +155 -292
  224. package/dist/runs/background/subagent-runner-launcher.js +33 -13
  225. package/dist/runs/background/subagent-runner.js +51 -1842
  226. package/dist/runs/background/top-level-async.js +2 -1
  227. package/dist/runs/foreground/chain-clarify.js +293 -1017
  228. package/dist/runs/foreground/clarification-draft.js +87 -0
  229. package/dist/runs/foreground/clarify-contracts.js +1 -0
  230. package/dist/runs/foreground/clarify-invocation.js +129 -38
  231. package/dist/runs/foreground/clarify-text-editor.js +210 -0
  232. package/dist/runs/foreground/clarify-view.js +167 -0
  233. package/dist/runs/foreground/execution-input.js +226 -353
  234. package/dist/runs/foreground/execution-routing.js +33 -0
  235. package/dist/runs/foreground/execution-timeout.js +81 -0
  236. package/dist/runs/foreground/foreground-control.js +222 -763
  237. package/dist/runs/foreground/foreground-memory.js +99 -0
  238. package/dist/runs/foreground/invocation-context.js +55 -0
  239. package/dist/runs/foreground/invocation-execution.js +331 -0
  240. package/dist/runs/foreground/invocation-expansion.js +48 -0
  241. package/dist/runs/foreground/management-actions.js +295 -0
  242. package/dist/runs/foreground/nested-control.js +179 -0
  243. package/dist/runs/foreground/question-continuation.js +78 -0
  244. package/dist/runs/foreground/question-control.js +155 -50
  245. package/dist/runs/foreground/resume-target.js +221 -0
  246. package/dist/runs/foreground/revival-launch-policy.js +58 -0
  247. package/dist/runs/foreground/run-async-path.js +190 -178
  248. package/dist/runs/foreground/run-interrupt.js +164 -0
  249. package/dist/runs/foreground/run-nudge.js +278 -0
  250. package/dist/runs/foreground/saved-revival.js +251 -0
  251. package/dist/runs/foreground/subagent-executor.js +135 -424
  252. package/dist/runs/foreground/subagent-params.js +67 -30
  253. package/dist/runs/foreground/wait-observation.js +104 -0
  254. package/dist/runs/foreground/wait-registration.js +17 -0
  255. package/dist/runs/foreground/wait-run.js +283 -123
  256. package/dist/runs/shared/acceptance-contract.js +193 -99
  257. package/dist/runs/shared/acceptance-defaults.js +1 -0
  258. package/dist/runs/shared/acceptance-evaluation.js +201 -181
  259. package/dist/runs/shared/acceptance-finalization.js +256 -180
  260. package/dist/runs/shared/acceptance-outcome.js +53 -0
  261. package/dist/runs/shared/acceptance-reports.js +137 -72
  262. package/dist/runs/shared/acceptance-submission.js +167 -0
  263. package/dist/runs/shared/acceptance-verification.js +100 -0
  264. package/dist/runs/shared/chain-outputs.js +80 -52
  265. package/dist/runs/shared/child-attempt-types.js +1 -0
  266. package/dist/runs/shared/child-attempt.js +314 -667
  267. package/dist/runs/shared/child-boundaries.js +173 -0
  268. package/dist/runs/shared/child-context-filter.js +44 -0
  269. package/dist/runs/shared/child-event-observer.js +390 -0
  270. package/dist/runs/shared/child-execution-cwd.js +73 -43
  271. package/dist/runs/shared/child-execution-outcome.js +72 -0
  272. package/dist/runs/shared/child-invocation.js +54 -0
  273. package/dist/runs/shared/child-message-validation.js +215 -0
  274. package/dist/runs/shared/child-native-accounting.js +106 -0
  275. package/dist/runs/shared/child-native-observation.js +69 -0
  276. package/dist/runs/shared/child-observation-spool.js +164 -0
  277. package/dist/runs/shared/child-observations.js +157 -76
  278. package/dist/runs/shared/child-presence.js +3 -0
  279. package/dist/runs/shared/child-route-env.js +119 -0
  280. package/dist/runs/shared/child-stream-observer.js +221 -0
  281. package/dist/runs/shared/child-stream-projection.js +137 -0
  282. package/dist/runs/shared/child-structured-tool.js +27 -0
  283. package/dist/runs/shared/claude-code.js +121 -158
  284. package/dist/runs/shared/claude-model.js +42 -0
  285. package/dist/runs/shared/claude-session.js +83 -0
  286. package/dist/runs/shared/claude-types.js +1 -0
  287. package/dist/runs/shared/completion-guard.js +18 -18
  288. package/dist/runs/shared/control-event-policy.js +8 -0
  289. package/dist/runs/shared/control-notification-owner.js +13 -0
  290. package/dist/runs/shared/dynamic-fanout.js +188 -173
  291. package/dist/runs/shared/dynamic-item.js +102 -0
  292. package/dist/runs/shared/history-index.js +62 -36
  293. package/dist/runs/shared/legacy-async-recovery.js +114 -0
  294. package/dist/runs/shared/legacy-output-recovery.js +148 -0
  295. package/dist/runs/shared/mcp-config-schema.js +36 -0
  296. package/dist/runs/shared/mcp-direct-tool-allowlist.js +147 -116
  297. package/dist/runs/shared/model-fallback.js +97 -38
  298. package/dist/runs/shared/mutating-tool-guard.js +128 -88
  299. package/dist/runs/shared/native-finalization-types.js +1 -0
  300. package/dist/runs/shared/native-finalization.js +155 -76
  301. package/dist/runs/shared/native-usage.js +238 -98
  302. package/dist/runs/shared/nested-control-records.js +128 -0
  303. package/dist/runs/shared/nested-events.js +8 -700
  304. package/dist/runs/shared/nested-path.js +32 -28
  305. package/dist/runs/shared/nested-projection.js +155 -0
  306. package/dist/runs/shared/nested-protocol.js +18 -0
  307. package/dist/runs/shared/nested-registry.js +191 -0
  308. package/dist/runs/shared/nested-render.js +106 -58
  309. package/dist/runs/shared/nested-route.js +220 -0
  310. package/dist/runs/shared/nested-validation.js +216 -0
  311. package/dist/runs/shared/owned-child-evidence.js +125 -0
  312. package/dist/runs/shared/owned-run-list.js +146 -0
  313. package/dist/runs/shared/owned-run-observation.js +267 -0
  314. package/dist/runs/shared/owned-run-progress.js +109 -0
  315. package/dist/runs/shared/owned-run-read-state.js +1 -0
  316. package/dist/runs/shared/owned-run-results.js +202 -0
  317. package/dist/runs/shared/owned-run-status.js +180 -0
  318. package/dist/runs/shared/owned-run-view.js +51 -0
  319. package/dist/runs/shared/owned-workflow-details.js +17 -0
  320. package/dist/runs/shared/owner-output.js +43 -0
  321. package/dist/runs/shared/parallel-utils.js +36 -28
  322. package/dist/runs/shared/parent-receipts.js +90 -32
  323. package/dist/runs/shared/parent-usage.js +169 -57
  324. package/dist/runs/shared/pi-args.js +108 -201
  325. package/dist/runs/shared/pi-launch-input.js +1 -0
  326. package/dist/runs/shared/pi-session-launch.js +86 -0
  327. package/dist/runs/shared/pi-spawn.js +35 -21
  328. package/dist/runs/shared/run-history-queries.js +126 -35
  329. package/dist/runs/shared/run-history.js +101 -35
  330. package/dist/runs/shared/run-metadata-paths.js +14 -0
  331. package/dist/runs/shared/run-metadata.js +158 -0
  332. package/dist/runs/shared/run-persistence.js +131 -0
  333. package/dist/runs/shared/run-records.js +9 -679
  334. package/dist/runs/shared/run-restoration.js +338 -0
  335. package/dist/runs/shared/run-state-owner.js +26 -0
  336. package/dist/runs/shared/session-cwd-preload.js +27 -18
  337. package/dist/runs/shared/single-output.js +148 -70
  338. package/dist/runs/shared/stable-value.js +15 -0
  339. package/dist/runs/shared/streaming-text.js +23 -12
  340. package/dist/runs/shared/structured-output.js +25 -13
  341. package/dist/runs/shared/subagent-control.js +167 -100
  342. package/dist/runs/shared/subagent-prompt-runtime.js +27 -130
  343. package/dist/runs/shared/subagent-tool-loop-guard.js +81 -52
  344. package/dist/runs/shared/supervisor-question-state.js +145 -0
  345. package/dist/runs/shared/supervisor-questions.js +185 -254
  346. package/dist/runs/shared/workflow-graph.js +259 -167
  347. package/dist/runs/shared/workflow-policy.js +120 -48
  348. package/dist/runs/shared/worktree-contract.js +1 -0
  349. package/dist/runs/shared/worktree-hook.js +138 -0
  350. package/dist/runs/shared/worktree-location.js +47 -0
  351. package/dist/runs/shared/worktree-preservation.js +8 -0
  352. package/dist/runs/shared/worktree-process.js +107 -0
  353. package/dist/runs/shared/worktree.js +183 -322
  354. package/dist/shared/agent-context-policy.js +34 -44
  355. package/dist/shared/agent-dir.js +14 -0
  356. package/dist/shared/artifacts.js +30 -12
  357. package/dist/shared/atomic-json.js +4 -1
  358. package/dist/shared/chain-files.js +72 -0
  359. package/dist/shared/concurrency.js +18 -0
  360. package/dist/shared/content-preview.js +115 -0
  361. package/dist/shared/cooperative.js +5 -2
  362. package/dist/shared/execution-cwd.js +13 -5
  363. package/dist/shared/file-coalescer.js +2 -1
  364. package/dist/shared/fork-context.js +10 -12
  365. package/dist/shared/formatters.js +45 -19
  366. package/dist/shared/journal-frames.js +164 -0
  367. package/dist/shared/journal-projections.js +121 -0
  368. package/dist/shared/journal-reader.js +6 -407
  369. package/dist/shared/json-projection.js +191 -0
  370. package/dist/shared/lazy-tools.js +19 -8
  371. package/dist/shared/message-output.js +116 -0
  372. package/dist/shared/model-info.js +31 -14
  373. package/dist/shared/native-import.js +20 -0
  374. package/dist/shared/native-journal.js +140 -0
  375. package/dist/shared/native-session.js +5 -2
  376. package/dist/shared/native-tui.js +7 -2
  377. package/dist/shared/native-typebox.js +15 -3
  378. package/dist/shared/output-page.js +63 -0
  379. package/dist/shared/post-exit-stdio-guard.js +128 -88
  380. package/dist/shared/prompt-sections.js +2 -0
  381. package/dist/shared/session-entries.js +70 -35
  382. package/dist/shared/session-identity.js +5 -3
  383. package/dist/shared/settings.js +62 -192
  384. package/dist/shared/status-format.js +97 -37
  385. package/dist/shared/task-file-policy.js +24 -0
  386. package/dist/shared/temp-root.js +44 -15
  387. package/dist/shared/types/acceptance.js +1 -0
  388. package/dist/shared/types/async.js +1 -0
  389. package/dist/shared/types/config.js +1 -0
  390. package/dist/shared/types/details.js +1 -0
  391. package/dist/shared/types/history.js +1 -0
  392. package/dist/shared/types/inputs.js +1 -0
  393. package/dist/shared/types/intercom.js +1 -0
  394. package/dist/shared/types/launch.js +1 -0
  395. package/dist/shared/types/messages.js +1 -0
  396. package/dist/shared/types/nested.js +1 -0
  397. package/dist/shared/types/owned-runs.js +1 -0
  398. package/dist/shared/types/progress.js +1 -0
  399. package/dist/shared/types/questions.js +1 -0
  400. package/dist/shared/types/results.js +1 -0
  401. package/dist/shared/types/state.js +1 -0
  402. package/dist/shared/types/usage.js +1 -0
  403. package/dist/shared/types/workflow.js +1 -0
  404. package/dist/shared/types.js +75 -30
  405. package/dist/shared/unknown.js +52 -0
  406. package/dist/shared/utils.js +54 -260
  407. package/dist/slash/command-discovery.js +82 -0
  408. package/dist/slash/command-input.js +190 -0
  409. package/dist/slash/prompt-template-bridge.js +94 -270
  410. package/dist/slash/prompt-template-contract.js +77 -0
  411. package/dist/slash/prompt-template-results.js +125 -0
  412. package/dist/slash/request-protocol.js +68 -0
  413. package/dist/slash/result-delivery.js +237 -0
  414. package/dist/slash/saved-chain.js +78 -0
  415. package/dist/slash/slash-bridge.js +123 -89
  416. package/dist/slash/slash-commands.js +101 -572
  417. package/dist/slash/slash-live-state.js +68 -47
  418. package/dist/tui/action-hints.js +50 -22
  419. package/dist/tui/activity-lines.js +32 -0
  420. package/dist/tui/agent-browser.js +290 -0
  421. package/dist/tui/agent-controls.js +289 -0
  422. package/dist/tui/agent-conversation.js +444 -0
  423. package/dist/tui/agent-dock.js +171 -0
  424. package/dist/tui/agent-history.js +50 -183
  425. package/dist/tui/agent-model.js +62 -0
  426. package/dist/tui/agent-picker.js +262 -0
  427. package/dist/tui/agent-view.js +232 -1564
  428. package/dist/tui/compact-results.js +193 -0
  429. package/dist/tui/conversation-details.js +190 -0
  430. package/dist/tui/conversation-frame.js +135 -0
  431. package/dist/tui/conversation-history.js +201 -0
  432. package/dist/tui/conversation-menu.js +78 -0
  433. package/dist/tui/conversation-notices.js +79 -0
  434. package/dist/tui/conversation-selection.js +58 -0
  435. package/dist/tui/conversation-viewport.js +129 -0
  436. package/dist/tui/direction-message.js +27 -0
  437. package/dist/tui/display.js +282 -0
  438. package/dist/tui/editor-viewport.js +18 -0
  439. package/dist/tui/expanded-content.js +87 -0
  440. package/dist/tui/expanded-multi.js +170 -0
  441. package/dist/tui/expanded-single.js +65 -0
  442. package/dist/tui/history-cards.js +216 -0
  443. package/dist/tui/history-display.js +238 -0
  444. package/dist/tui/history-json.js +16 -0
  445. package/dist/tui/history-metadata.js +152 -0
  446. package/dist/tui/history-record.js +251 -0
  447. package/dist/tui/history-text.js +34 -0
  448. package/dist/tui/indexed-history.js +116 -0
  449. package/dist/tui/nested-widget.js +120 -0
  450. package/dist/tui/picker-page.js +59 -0
  451. package/dist/tui/render.js +58 -1501
  452. package/dist/tui/result-facts.js +64 -0
  453. package/dist/tui/task-observation.js +59 -0
  454. package/dist/tui/task-store.js +366 -0
  455. package/dist/tui/text-values.js +16 -0
  456. package/dist/tui/view-connections.js +47 -0
  457. package/dist/tui/view-model.js +94 -0
  458. package/dist/tui/view-persistence.js +51 -0
  459. package/dist/tui/view-ports.js +1 -0
  460. package/dist/tui/view-session.js +37 -0
  461. package/dist/tui/widget-details.js +144 -0
  462. package/dist/tui/widget-status.js +245 -0
  463. package/dist/tui/widget.js +145 -0
  464. package/dist/tui/workflow-labels.js +223 -0
  465. package/dist/tui/workflow-outcomes.js +124 -0
  466. package/docs/code-quality.md +38 -0
  467. package/docs/development.md +99 -0
  468. package/docs/intercom-bridge.md +22 -17
  469. package/docs/intercom.md +132 -106
  470. package/docs/performance.md +19 -17
  471. package/docs/reference.md +1472 -0
  472. package/generated/RunValidators.d.ts +28 -0
  473. package/generated/RunValidators.js +2 -0
  474. package/package.json +27 -6
  475. package/prompts/parallel-cleanup.md +3 -0
  476. package/prompts/parallel-context-build.md +3 -0
  477. package/prompts/parallel-handoff-plan.md +6 -0
  478. package/prompts/parallel-research.md +4 -0
  479. package/prompts/parallel-review.md +2 -0
  480. package/prompts/review-loop.md +2 -0
  481. package/scripts/build.mjs +129 -85
  482. package/scripts/check-compat.mjs +48 -11
  483. package/scripts/compat-host.mjs +35 -7
  484. package/scripts/generate-run-schemas.mjs +210 -0
  485. package/scripts/intercom-bridge-credentials.mjs +155 -28
  486. package/scripts/intercom-remote.mjs +175 -50
  487. package/scripts/local-install-smoke.mjs +47 -37
  488. package/scripts/native-package-smoke.mjs +135 -25
  489. package/scripts/package-smoke.mjs +360 -140
  490. package/scripts/prepare.mjs +54 -34
  491. package/scripts/real-pi-processes.mjs +261 -0
  492. package/scripts/real-pi-smoke.mjs +432 -351
  493. package/scripts/run-tests.mjs +29 -15
  494. package/skills/pi-intercom/SKILL.md +11 -11
  495. package/skills/pi-intercom/references/peer-sessions.md +7 -2
  496. package/skills/pi-subagents/SKILL.md +1 -1
  497. package/skills/pi-subagents/references/full-orchestration-guide.md +254 -112
  498. package/src/agents/agent-defaults.ts +13 -0
  499. package/src/agents/agent-definition.ts +253 -0
  500. package/src/agents/agent-management.ts +111 -808
  501. package/src/agents/agent-scope.ts +7 -3
  502. package/src/agents/agent-selection.ts +26 -16
  503. package/src/agents/agent-serializer.ts +84 -93
  504. package/src/agents/agents.ts +199 -906
  505. package/src/agents/builtin-overrides.ts +297 -0
  506. package/src/agents/chain-serializer.ts +3 -329
  507. package/src/agents/config-values.ts +57 -0
  508. package/src/agents/discovery-paths.ts +134 -0
  509. package/src/agents/frontmatter.ts +35 -17
  510. package/src/agents/identity.ts +49 -18
  511. package/src/agents/json-chain.ts +305 -0
  512. package/src/agents/management-config.ts +342 -0
  513. package/src/agents/management-format.ts +243 -0
  514. package/src/agents/management-persistence.ts +408 -0
  515. package/src/agents/management-targets.ts +260 -0
  516. package/src/agents/management-warnings.ts +115 -0
  517. package/src/agents/markdown-chain.ts +237 -0
  518. package/src/agents/package-agents.ts +231 -0
  519. package/src/agents/skill-files.ts +182 -0
  520. package/src/agents/skill-search-paths.ts +289 -0
  521. package/src/agents/skill-types.ts +31 -0
  522. package/src/agents/skills.ts +152 -610
  523. package/src/extension/acceptance-schema.ts +88 -0
  524. package/src/extension/chain-schema.ts +276 -0
  525. package/src/extension/child-runtime.ts +302 -0
  526. package/src/extension/compact-tools.ts +259 -102
  527. package/src/extension/config-schema.ts +59 -0
  528. package/src/extension/config.ts +39 -17
  529. package/src/extension/control-notice-schema.ts +55 -0
  530. package/src/extension/control-notices.ts +57 -33
  531. package/src/extension/delegation-bridges.ts +59 -0
  532. package/src/extension/doctor.ts +171 -135
  533. package/src/extension/everyday-schemas.ts +252 -0
  534. package/src/extension/fanout-child.ts +29 -308
  535. package/src/extension/index.ts +17 -642
  536. package/src/extension/message-renderers.ts +334 -0
  537. package/src/extension/nested-control-inbox.ts +196 -0
  538. package/src/extension/parent-runtime.ts +405 -0
  539. package/src/extension/primary-tool.ts +130 -0
  540. package/src/extension/result-snapshot.ts +35 -0
  541. package/src/extension/runtime-reload.ts +72 -0
  542. package/src/extension/runtime-storage.ts +49 -0
  543. package/src/extension/schema-overrides.ts +114 -0
  544. package/src/extension/schemas.ts +451 -418
  545. package/src/extension/tool-input.ts +40 -13
  546. package/src/extension/tool-result.ts +45 -14
  547. package/src/history/answer-texts.ts +74 -0
  548. package/src/history/canonical-result.ts +127 -51
  549. package/src/history/canonical-selection.ts +54 -0
  550. package/src/history/database-generation.ts +86 -0
  551. package/src/history/database.ts +86 -48
  552. package/src/history/entry-ingestion.ts +129 -0
  553. package/src/history/index.ts +426 -148
  554. package/src/history/ingest.ts +372 -342
  555. package/src/history/output-digests.ts +41 -0
  556. package/src/history/preview.ts +235 -0
  557. package/src/history/prune.ts +48 -0
  558. package/src/history/queries.ts +122 -256
  559. package/src/history/query-scope.ts +278 -0
  560. package/src/history/rows.ts +118 -0
  561. package/src/history/run-projection.ts +164 -0
  562. package/src/history/run-queries.ts +199 -0
  563. package/src/history/schema.ts +34 -0
  564. package/src/history/search-queries.ts +216 -0
  565. package/src/history/selected-record.ts +140 -0
  566. package/src/history/source-file.ts +51 -0
  567. package/src/history/source-watches.ts +156 -0
  568. package/src/history/store.ts +310 -197
  569. package/src/history/text-chunks.ts +181 -0
  570. package/src/history/text.ts +43 -0
  571. package/src/history/transcript-queries.ts +251 -0
  572. package/src/history/types.ts +27 -164
  573. package/src/history/values.ts +36 -0
  574. package/src/history/wire-inputs.ts +141 -0
  575. package/src/history/wire-models.ts +51 -0
  576. package/src/history/worker-runtime.ts +502 -0
  577. package/src/history/worker.ts +94 -336
  578. package/src/intercom/intercom-bridge.ts +136 -69
  579. package/src/intercom/live-intercom.ts +197 -92
  580. package/src/intercom/nested-result-tree.ts +213 -0
  581. package/src/intercom/result-delivery.ts +56 -0
  582. package/src/intercom/result-intercom.ts +364 -382
  583. package/src/pi-intercom/agent-dir.ts +9 -3
  584. package/src/pi-intercom/async.ts +33 -0
  585. package/src/pi-intercom/bridge-ask.ts +64 -0
  586. package/src/pi-intercom/bridge-config.ts +101 -0
  587. package/src/pi-intercom/bridge-http.ts +97 -0
  588. package/src/pi-intercom/bridge-protocol.ts +123 -0
  589. package/src/pi-intercom/bridge-routes.ts +90 -0
  590. package/src/pi-intercom/bridge-session.ts +506 -0
  591. package/src/pi-intercom/bridge.ts +258 -547
  592. package/src/pi-intercom/broker/broker.ts +326 -263
  593. package/src/pi-intercom/broker/client.ts +273 -354
  594. package/src/pi-intercom/broker/connection.ts +192 -0
  595. package/src/pi-intercom/broker/framing.ts +11 -6
  596. package/src/pi-intercom/broker/paths.ts +28 -25
  597. package/src/pi-intercom/broker/pid.ts +68 -24
  598. package/src/pi-intercom/broker/snapshot-reader.ts +91 -0
  599. package/src/pi-intercom/broker/snapshots.ts +241 -0
  600. package/src/pi-intercom/broker/spawn.ts +58 -34
  601. package/src/pi-intercom/config.ts +113 -108
  602. package/src/pi-intercom/connection.ts +346 -0
  603. package/src/pi-intercom/identity.ts +71 -0
  604. package/src/pi-intercom/inbound-delivery.ts +450 -0
  605. package/src/pi-intercom/inbound-journal.ts +350 -0
  606. package/src/pi-intercom/inbound-record.ts +141 -0
  607. package/src/pi-intercom/inbound.ts +237 -0
  608. package/src/pi-intercom/index.ts +86 -2923
  609. package/src/pi-intercom/inspection.ts +82 -0
  610. package/src/pi-intercom/interview.ts +295 -0
  611. package/src/pi-intercom/lifecycle.ts +183 -0
  612. package/src/pi-intercom/message-format.ts +77 -0
  613. package/src/pi-intercom/outbound.ts +418 -0
  614. package/src/pi-intercom/peer-awareness.ts +84 -0
  615. package/src/pi-intercom/reply-tracker.ts +121 -59
  616. package/src/pi-intercom/reply-wait.ts +247 -0
  617. package/src/pi-intercom/runtime-types.ts +97 -0
  618. package/src/pi-intercom/session-events.ts +247 -0
  619. package/src/pi-intercom/session-targets.ts +124 -72
  620. package/src/pi-intercom/subagent-events.ts +299 -0
  621. package/src/pi-intercom/subagent-live-events.ts +212 -109
  622. package/src/pi-intercom/supervisor.ts +362 -0
  623. package/src/pi-intercom/tool-arguments.ts +120 -0
  624. package/src/pi-intercom/tool-registration.ts +121 -0
  625. package/src/pi-intercom/tool-results.ts +54 -0
  626. package/src/pi-intercom/tool-schemas.ts +134 -0
  627. package/src/pi-intercom/tools.ts +80 -0
  628. package/src/pi-intercom/topic-actions.ts +243 -0
  629. package/src/pi-intercom/topics.ts +267 -121
  630. package/src/pi-intercom/transport.ts +14 -0
  631. package/src/pi-intercom/types.ts +288 -190
  632. package/src/pi-intercom/ui/compose-paste.ts +109 -0
  633. package/src/pi-intercom/ui/compose.ts +173 -157
  634. package/src/pi-intercom/ui/inline-message.ts +80 -62
  635. package/src/pi-intercom/ui/message-renderers.ts +182 -0
  636. package/src/pi-intercom/ui/overlay.ts +238 -0
  637. package/src/pi-intercom/ui/session-format.ts +146 -0
  638. package/src/pi-intercom/ui/session-list.ts +145 -62
  639. package/src/pi-intercom/ui/tool-renderers.ts +148 -0
  640. package/src/pi-intercom/ui/topic-view.ts +107 -0
  641. package/src/pi-intercom/validation.ts +69 -0
  642. package/src/runs/background/async-chain-plan.ts +451 -0
  643. package/src/runs/background/async-control.ts +201 -71
  644. package/src/runs/background/async-execution.ts +206 -829
  645. package/src/runs/background/async-job-admission.ts +54 -0
  646. package/src/runs/background/async-job-projection.ts +225 -0
  647. package/src/runs/background/async-job-tracker.ts +416 -360
  648. package/src/runs/background/async-launch.ts +319 -0
  649. package/src/runs/background/async-plan.ts +285 -0
  650. package/src/runs/background/async-result-file.ts +79 -37
  651. package/src/runs/background/async-resume.ts +338 -285
  652. package/src/runs/background/async-run-discovery.ts +270 -0
  653. package/src/runs/background/async-run-location.ts +194 -0
  654. package/src/runs/background/async-run-record.ts +14 -0
  655. package/src/runs/background/async-run-repair.ts +307 -0
  656. package/src/runs/background/async-run-summary.ts +71 -0
  657. package/src/runs/background/async-single-plan.ts +168 -0
  658. package/src/runs/background/async-status-projection.ts +188 -0
  659. package/src/runs/background/async-status-render.ts +164 -0
  660. package/src/runs/background/async-status-validation.ts +238 -0
  661. package/src/runs/background/async-status.ts +9 -481
  662. package/src/runs/background/async-value.ts +29 -0
  663. package/src/runs/background/completion-dedupe.ts +103 -54
  664. package/src/runs/background/completion-delivery.ts +313 -187
  665. package/src/runs/background/completion-receipts.ts +309 -0
  666. package/src/runs/background/legacy-status-acceptance.ts +38 -0
  667. package/src/runs/background/notify.ts +167 -106
  668. package/src/runs/background/parallel-groups.ts +95 -46
  669. package/src/runs/background/result-payload.ts +268 -0
  670. package/src/runs/background/result-watcher.ts +484 -387
  671. package/src/runs/background/run-id-resolver.ts +126 -57
  672. package/src/runs/background/run-schemas.ts +240 -0
  673. package/src/runs/background/run-status-contracts.ts +46 -0
  674. package/src/runs/background/run-status-render.ts +364 -0
  675. package/src/runs/background/run-status.ts +338 -356
  676. package/src/runs/background/runner-attempt-output.ts +281 -0
  677. package/src/runs/background/runner-attempt.ts +354 -0
  678. package/src/runs/background/runner-child-executor.ts +232 -0
  679. package/src/runs/background/runner-child-observer.ts +270 -0
  680. package/src/runs/background/runner-completion-summary.ts +106 -0
  681. package/src/runs/background/runner-completion.ts +274 -0
  682. package/src/runs/background/runner-config.ts +52 -0
  683. package/src/runs/background/runner-contract.ts +51 -0
  684. package/src/runs/background/runner-dynamic.ts +185 -0
  685. package/src/runs/background/runner-finalization.ts +203 -0
  686. package/src/runs/background/runner-graph.ts +91 -0
  687. package/src/runs/background/runner-initial-status.ts +72 -0
  688. package/src/runs/background/runner-lifecycle.ts +159 -0
  689. package/src/runs/background/runner-monitor.ts +399 -0
  690. package/src/runs/background/runner-parallel.ts +280 -0
  691. package/src/runs/background/runner-prepare-step.ts +128 -0
  692. package/src/runs/background/runner-reporting.ts +192 -0
  693. package/src/runs/background/runner-status.ts +220 -0
  694. package/src/runs/background/runner-step-output.ts +158 -0
  695. package/src/runs/background/runner-step-record.ts +76 -0
  696. package/src/runs/background/runner-step.ts +150 -0
  697. package/src/runs/background/runner-streaming.ts +220 -0
  698. package/src/runs/background/runner-workflow.ts +284 -0
  699. package/src/runs/background/stale-run-reconciler.ts +279 -336
  700. package/src/runs/background/subagent-runner-launcher.ts +67 -35
  701. package/src/runs/background/subagent-runner.ts +80 -2048
  702. package/src/runs/background/top-level-async.ts +9 -7
  703. package/src/runs/foreground/chain-clarify.ts +499 -1334
  704. package/src/runs/foreground/clarification-draft.ts +92 -0
  705. package/src/runs/foreground/clarify-contracts.ts +33 -0
  706. package/src/runs/foreground/clarify-invocation.ts +192 -65
  707. package/src/runs/foreground/clarify-text-editor.ts +229 -0
  708. package/src/runs/foreground/clarify-view.ts +222 -0
  709. package/src/runs/foreground/execution-input.ts +358 -424
  710. package/src/runs/foreground/execution-routing.ts +41 -0
  711. package/src/runs/foreground/execution-timeout.ts +92 -0
  712. package/src/runs/foreground/foreground-control.ts +333 -812
  713. package/src/runs/foreground/foreground-memory.ts +132 -0
  714. package/src/runs/foreground/invocation-context.ts +88 -0
  715. package/src/runs/foreground/invocation-execution.ts +465 -0
  716. package/src/runs/foreground/invocation-expansion.ts +58 -0
  717. package/src/runs/foreground/management-actions.ts +360 -0
  718. package/src/runs/foreground/nested-control.ts +248 -0
  719. package/src/runs/foreground/question-continuation.ts +112 -0
  720. package/src/runs/foreground/question-control.ts +297 -70
  721. package/src/runs/foreground/resume-target.ts +330 -0
  722. package/src/runs/foreground/revival-launch-policy.ts +112 -0
  723. package/src/runs/foreground/run-async-path.ts +307 -223
  724. package/src/runs/foreground/run-interrupt.ts +202 -0
  725. package/src/runs/foreground/run-nudge.ts +355 -0
  726. package/src/runs/foreground/saved-revival.ts +356 -0
  727. package/src/runs/foreground/subagent-executor.ts +195 -493
  728. package/src/runs/foreground/subagent-params.ts +314 -242
  729. package/src/runs/foreground/wait-observation.ts +160 -0
  730. package/src/runs/foreground/wait-registration.ts +18 -0
  731. package/src/runs/foreground/wait-run.ts +361 -119
  732. package/src/runs/shared/acceptance-contract.ts +410 -209
  733. package/src/runs/shared/acceptance-defaults.ts +1 -0
  734. package/src/runs/shared/acceptance-evaluation.ts +314 -240
  735. package/src/runs/shared/acceptance-finalization.ts +447 -305
  736. package/src/runs/shared/acceptance-outcome.ts +69 -0
  737. package/src/runs/shared/acceptance-reports.ts +220 -126
  738. package/src/runs/shared/acceptance-submission.ts +251 -0
  739. package/src/runs/shared/acceptance-verification.ts +118 -0
  740. package/src/runs/shared/acceptance.ts +25 -25
  741. package/src/runs/shared/chain-outputs.ts +190 -98
  742. package/src/runs/shared/child-attempt-types.ts +118 -0
  743. package/src/runs/shared/child-attempt.ts +372 -608
  744. package/src/runs/shared/child-boundaries.ts +217 -0
  745. package/src/runs/shared/child-context-filter.ts +53 -0
  746. package/src/runs/shared/child-event-observer.ts +496 -0
  747. package/src/runs/shared/child-execution-cwd.ts +139 -68
  748. package/src/runs/shared/child-execution-outcome.ts +103 -0
  749. package/src/runs/shared/child-invocation.ts +74 -0
  750. package/src/runs/shared/child-message-validation.ts +233 -0
  751. package/src/runs/shared/child-native-accounting.ts +154 -0
  752. package/src/runs/shared/child-native-observation.ts +79 -0
  753. package/src/runs/shared/child-observation-spool.ts +188 -0
  754. package/src/runs/shared/child-observations.ts +219 -89
  755. package/src/runs/shared/child-presence.ts +6 -0
  756. package/src/runs/shared/child-route-env.ts +142 -0
  757. package/src/runs/shared/child-stream-observer.ts +302 -0
  758. package/src/runs/shared/child-stream-projection.ts +160 -0
  759. package/src/runs/shared/child-structured-tool.ts +38 -0
  760. package/src/runs/shared/claude-code.ts +201 -228
  761. package/src/runs/shared/claude-model.ts +67 -0
  762. package/src/runs/shared/claude-session.ts +124 -0
  763. package/src/runs/shared/claude-types.ts +31 -0
  764. package/src/runs/shared/completion-guard.ts +35 -26
  765. package/src/runs/shared/control-event-policy.ts +15 -0
  766. package/src/runs/shared/control-notification-owner.ts +20 -0
  767. package/src/runs/shared/dynamic-fanout.ts +402 -238
  768. package/src/runs/shared/dynamic-item.ts +114 -0
  769. package/src/runs/shared/history-index.ts +112 -51
  770. package/src/runs/shared/legacy-async-recovery.ts +153 -0
  771. package/src/runs/shared/legacy-output-recovery.ts +214 -0
  772. package/src/runs/shared/mcp-config-schema.ts +46 -0
  773. package/src/runs/shared/mcp-direct-tool-allowlist.ts +396 -307
  774. package/src/runs/shared/model-fallback.ts +302 -180
  775. package/src/runs/shared/mutating-tool-guard.ts +259 -158
  776. package/src/runs/shared/native-finalization-types.ts +29 -0
  777. package/src/runs/shared/native-finalization.ts +233 -109
  778. package/src/runs/shared/native-usage.ts +379 -96
  779. package/src/runs/shared/nested-control-records.ts +178 -0
  780. package/src/runs/shared/nested-events.ts +45 -752
  781. package/src/runs/shared/nested-path.ts +47 -34
  782. package/src/runs/shared/nested-projection.ts +230 -0
  783. package/src/runs/shared/nested-protocol.ts +67 -0
  784. package/src/runs/shared/nested-registry.ts +273 -0
  785. package/src/runs/shared/nested-render.ts +198 -100
  786. package/src/runs/shared/nested-route.ts +292 -0
  787. package/src/runs/shared/nested-validation.ts +291 -0
  788. package/src/runs/shared/owned-child-evidence.ts +184 -0
  789. package/src/runs/shared/owned-run-list.ts +187 -0
  790. package/src/runs/shared/owned-run-observation.ts +368 -0
  791. package/src/runs/shared/owned-run-progress.ts +172 -0
  792. package/src/runs/shared/owned-run-read-state.ts +7 -0
  793. package/src/runs/shared/owned-run-results.ts +289 -0
  794. package/src/runs/shared/owned-run-status.ts +239 -0
  795. package/src/runs/shared/owned-run-view.ts +65 -0
  796. package/src/runs/shared/owned-workflow-details.ts +24 -0
  797. package/src/runs/shared/owner-output.ts +73 -0
  798. package/src/runs/shared/parallel-utils.ts +93 -129
  799. package/src/runs/shared/parent-receipts.ts +177 -50
  800. package/src/runs/shared/parent-usage.ts +314 -91
  801. package/src/runs/shared/pi-args.ts +241 -311
  802. package/src/runs/shared/pi-launch-input.ts +48 -0
  803. package/src/runs/shared/pi-session-launch.ts +94 -0
  804. package/src/runs/shared/pi-spawn.ts +57 -33
  805. package/src/runs/shared/run-history-queries.ts +189 -38
  806. package/src/runs/shared/run-history.ts +197 -76
  807. package/src/runs/shared/run-id-ambiguity.ts +7 -3
  808. package/src/runs/shared/run-metadata-paths.ts +17 -0
  809. package/src/runs/shared/run-metadata.ts +240 -0
  810. package/src/runs/shared/run-persistence.ts +181 -0
  811. package/src/runs/shared/run-records.ts +19 -607
  812. package/src/runs/shared/run-restoration.ts +455 -0
  813. package/src/runs/shared/run-state-owner.ts +31 -0
  814. package/src/runs/shared/session-cwd-preload.ts +39 -19
  815. package/src/runs/shared/single-output.ts +358 -205
  816. package/src/runs/shared/stable-value.ts +15 -0
  817. package/src/runs/shared/streaming-text.ts +39 -12
  818. package/src/runs/shared/structured-output.ts +76 -46
  819. package/src/runs/shared/subagent-control.ts +330 -197
  820. package/src/runs/shared/subagent-prompt-runtime.ts +92 -174
  821. package/src/runs/shared/subagent-tool-loop-guard.ts +118 -68
  822. package/src/runs/shared/supervisor-question-state.ts +221 -0
  823. package/src/runs/shared/supervisor-questions.ts +396 -401
  824. package/src/runs/shared/workflow-graph.ts +400 -198
  825. package/src/runs/shared/workflow-policy.ts +245 -110
  826. package/src/runs/shared/worktree-contract.ts +29 -0
  827. package/src/runs/shared/worktree-hook.ts +181 -0
  828. package/src/runs/shared/worktree-location.ts +61 -0
  829. package/src/runs/shared/worktree-preservation.ts +10 -0
  830. package/src/runs/shared/worktree-process.ts +132 -0
  831. package/src/runs/shared/worktree.ts +459 -587
  832. package/src/shared/agent-context-policy.ts +176 -145
  833. package/src/shared/agent-dir.ts +15 -0
  834. package/src/shared/artifacts.ts +99 -68
  835. package/src/shared/atomic-json.ts +14 -11
  836. package/src/shared/chain-files.ts +72 -0
  837. package/src/shared/concurrency.ts +27 -0
  838. package/src/shared/content-preview.ts +117 -0
  839. package/src/shared/cooperative.ts +17 -13
  840. package/src/shared/execution-cwd.ts +34 -9
  841. package/src/shared/file-coalescer.ts +24 -22
  842. package/src/shared/fork-context.ts +52 -48
  843. package/src/shared/formatters.ts +88 -47
  844. package/src/shared/journal-frames.ts +197 -0
  845. package/src/shared/journal-projections.ts +133 -0
  846. package/src/shared/journal-reader.ts +18 -333
  847. package/src/shared/json-projection.ts +224 -0
  848. package/src/shared/lazy-tools.ts +76 -27
  849. package/src/shared/message-output.ts +146 -0
  850. package/src/shared/model-info.ts +94 -58
  851. package/src/shared/native-import.ts +25 -0
  852. package/src/shared/native-journal.ts +172 -0
  853. package/src/shared/native-session.ts +8 -3
  854. package/src/shared/native-tui.ts +13 -3
  855. package/src/shared/native-typebox.ts +18 -3
  856. package/src/shared/output-page.ts +76 -0
  857. package/src/shared/post-exit-stdio-guard.ts +232 -172
  858. package/src/shared/prompt-sections.ts +13 -7
  859. package/src/shared/session-entries.ts +103 -44
  860. package/src/shared/session-identity.ts +17 -10
  861. package/src/shared/settings.ts +182 -367
  862. package/src/shared/status-format.ts +207 -98
  863. package/src/shared/stream-json.d.ts +10 -0
  864. package/src/shared/task-file-policy.ts +35 -0
  865. package/src/shared/temp-root.ts +122 -71
  866. package/src/shared/types/acceptance.ts +149 -0
  867. package/src/shared/types/async.ts +247 -0
  868. package/src/shared/types/config.ts +139 -0
  869. package/src/shared/types/details.ts +104 -0
  870. package/src/shared/types/history.ts +217 -0
  871. package/src/shared/types/inputs.ts +4 -0
  872. package/src/shared/types/intercom.ts +57 -0
  873. package/src/shared/types/launch.ts +39 -0
  874. package/src/shared/types/messages.ts +104 -0
  875. package/src/shared/types/nested.ts +153 -0
  876. package/src/shared/types/owned-runs.ts +148 -0
  877. package/src/shared/types/progress.ts +106 -0
  878. package/src/shared/types/questions.ts +103 -0
  879. package/src/shared/types/results.ts +119 -0
  880. package/src/shared/types/state.ts +56 -0
  881. package/src/shared/types/usage.ts +36 -0
  882. package/src/shared/types/workflow.ts +187 -0
  883. package/src/shared/types.ts +222 -1161
  884. package/src/shared/ui-mode.ts +1 -1
  885. package/src/shared/unknown.ts +59 -0
  886. package/src/shared/utils.ts +111 -305
  887. package/src/slash/command-discovery.ts +109 -0
  888. package/src/slash/command-input.ts +232 -0
  889. package/src/slash/prompt-template-bridge.ts +153 -400
  890. package/src/slash/prompt-template-contract.ts +152 -0
  891. package/src/slash/prompt-template-results.ts +189 -0
  892. package/src/slash/request-protocol.ts +87 -0
  893. package/src/slash/result-delivery.ts +312 -0
  894. package/src/slash/saved-chain.ts +115 -0
  895. package/src/slash/slash-bridge.ts +202 -156
  896. package/src/slash/slash-commands.ts +176 -598
  897. package/src/slash/slash-live-state.ts +287 -229
  898. package/src/tui/action-hints.ts +147 -61
  899. package/src/tui/activity-lines.ts +40 -0
  900. package/src/tui/agent-browser.ts +354 -0
  901. package/src/tui/agent-controls.ts +355 -0
  902. package/src/tui/agent-conversation.ts +514 -0
  903. package/src/tui/agent-dock.ts +250 -0
  904. package/src/tui/agent-history.ts +78 -203
  905. package/src/tui/agent-model.ts +78 -0
  906. package/src/tui/agent-picker.ts +325 -0
  907. package/src/tui/agent-view.ts +391 -1333
  908. package/src/tui/compact-results.ts +342 -0
  909. package/src/tui/conversation-details.ts +206 -0
  910. package/src/tui/conversation-frame.ts +184 -0
  911. package/src/tui/conversation-history.ts +246 -0
  912. package/src/tui/conversation-menu.ts +119 -0
  913. package/src/tui/conversation-notices.ts +116 -0
  914. package/src/tui/conversation-selection.ts +66 -0
  915. package/src/tui/conversation-viewport.ts +169 -0
  916. package/src/tui/direction-message.ts +35 -0
  917. package/src/tui/display.ts +409 -0
  918. package/src/tui/editor-viewport.ts +19 -0
  919. package/src/tui/expanded-content.ts +134 -0
  920. package/src/tui/expanded-multi.ts +264 -0
  921. package/src/tui/expanded-single.ts +92 -0
  922. package/src/tui/history-cards.ts +316 -0
  923. package/src/tui/history-display.ts +334 -0
  924. package/src/tui/history-json.ts +17 -0
  925. package/src/tui/history-metadata.ts +177 -0
  926. package/src/tui/history-record.ts +321 -0
  927. package/src/tui/history-text.ts +34 -0
  928. package/src/tui/indexed-history.ts +149 -0
  929. package/src/tui/nested-widget.ts +192 -0
  930. package/src/tui/picker-page.ts +80 -0
  931. package/src/tui/render.ts +100 -1546
  932. package/src/tui/result-facts.ts +99 -0
  933. package/src/tui/task-observation.ts +96 -0
  934. package/src/tui/task-store.ts +432 -0
  935. package/src/tui/text-values.ts +20 -0
  936. package/src/tui/view-connections.ts +64 -0
  937. package/src/tui/view-model.ts +181 -0
  938. package/src/tui/view-persistence.ts +57 -0
  939. package/src/tui/view-ports.ts +55 -0
  940. package/src/tui/view-session.ts +42 -0
  941. package/src/tui/widget-details.ts +220 -0
  942. package/src/tui/widget-status.ts +331 -0
  943. package/src/tui/widget.ts +208 -0
  944. package/src/tui/workflow-labels.ts +340 -0
  945. package/src/tui/workflow-outcomes.ts +150 -0
  946. package/tsconfig.build.json +11 -10
  947. package/tsconfig.json +30 -17
@@ -1,333 +1,386 @@
1
1
  import * as fs from "node:fs";
2
- import { formatRunIdAmbiguity } from "../shared/run-id-ambiguity.ts";
3
2
  import * as path from "node:path";
4
- import { ASYNC_DIR, RESULTS_DIR, type AsyncStatus, type ResolvedAcceptanceConfig } from "../../shared/types.ts";
3
+ import {
4
+ ASYNC_DIR,
5
+ RESULTS_DIR,
6
+ type AsyncStatus,
7
+ type ResolvedAcceptanceConfig,
8
+ type SupervisorRunContract,
9
+ } from "../../shared/types.ts";
10
+ import type { ReadonlyInput } from "../../shared/types/inputs.ts";
5
11
  import { resolveSubagentIntercomTarget } from "../../intercom/intercom-bridge.ts";
6
12
  import { checkPidLiveness, reconcileAsyncRun } from "./stale-run-reconciler.ts";
7
- import { isDurableRun, readAsyncResultFile, type ParsedAsyncResultFile } from "./async-result-file.ts";
8
- import { QUESTIONS_DIR, readQuestionContract, readRunJson } from "../shared/supervisor-questions.ts";
9
- import { readStatus } from "../../shared/utils.ts";
13
+ import { readAsyncResultFile, type ParsedAsyncResultFile } from "./async-result-file.ts";
14
+ import { readQuestionContract } from "../shared/supervisor-questions.ts";
15
+ import { resolveAsyncRunLocation, type AsyncResumeParams } from "./async-run-location.ts";
16
+ import type { AsyncRunLocation } from "./async-run-record.ts";
17
+ import { hasText, isRecord } from "./async-value.ts";
10
18
 
11
- export interface AsyncResumeParams {
12
- id?: string;
13
- runId?: string;
14
- dir?: string;
15
- index?: number;
16
- }
19
+ export type { AsyncResumeParams } from "./async-run-location.ts";
20
+ export type { AsyncRunLocation, AsyncRunRecord } from "./async-run-record.ts";
21
+ export {
22
+ asyncRunRoots,
23
+ exactAsyncRunLocation,
24
+ readAsyncRunRecord,
25
+ findAsyncRunPrefixMatches,
26
+ resolveAsyncRunLocation,
27
+ } from "./async-run-location.ts";
17
28
 
18
29
  export interface AsyncResumeDeps {
19
- asyncDirRoot?: string;
20
- resultsDir?: string;
21
- kill?: (pid: number, signal?: NodeJS.Signals | 0) => boolean;
22
- now?: () => number;
30
+ readonly asyncDirRoot?: string;
31
+ readonly resultsDir?: string;
32
+ readonly kill?: (pid: number, signal?: NodeJS.Signals | 0) => boolean;
33
+ readonly now?: () => number;
23
34
  }
24
-
25
- export type AsyncResumeTarget = {
26
- kind: "live" | "revive";
27
- runId: string;
28
- asyncDir?: string;
29
- state: AsyncStatus["state"];
30
- agent: string;
31
- index: number;
32
- intercomTarget: string;
33
- cwd?: string;
34
- sessionFile?: string;
35
- effectiveAcceptance?: ResolvedAcceptanceConfig;
36
- };
37
-
38
- export interface AsyncRunLocation {
39
- asyncDir: string | null;
40
- resultPath: string | null;
41
- resolvedId?: string;
35
+ export interface AsyncResumeTarget {
36
+ readonly kind: "live" | "revive";
37
+ readonly runId: string;
38
+ readonly asyncDir?: string;
39
+ readonly state: AsyncStatus["state"];
40
+ readonly agent: string;
41
+ readonly index: number;
42
+ readonly intercomTarget: string;
43
+ readonly cwd?: string;
44
+ readonly sessionFile?: string;
45
+ readonly effectiveAcceptance?: ResolvedAcceptanceConfig;
42
46
  }
43
47
 
44
- export interface AsyncRunRecord {
45
- location: AsyncRunLocation;
46
- status: AsyncStatus | null;
47
- durable: boolean;
48
+ function optionalStrings(value: unknown, fields: readonly string[], source: string): void {
49
+ if (!isRecord(value)) {
50
+ throw new Error(`Invalid async status '${source}': expected an object.`);
51
+ }
52
+ for (const field of fields) {
53
+ if (value[field] !== undefined && typeof value[field] !== "string") {
54
+ throw new Error(`Invalid async status '${source}': ${field} must be a string.`);
55
+ }
56
+ }
48
57
  }
49
58
 
50
- function validateOptionalString(value: Record<string, unknown>, field: string, source: string, displayField = field): string | undefined {
51
- const fieldValue = value[field];
52
- if (fieldValue === undefined) return undefined;
53
- if (typeof fieldValue !== "string") throw new Error(`Invalid async result file '${source}': ${displayField} must be a string.`);
54
- return fieldValue;
59
+ function validateStatusForResume(value: unknown, source: string): void {
60
+ if (value === null) {
61
+ return;
62
+ }
63
+ if (!isRecord(value) || typeof value.runId !== "string") {
64
+ throw new Error(`Invalid async status '${source}': runId must be a string.`);
65
+ }
66
+ optionalStrings(value, ["sessionId", "cwd", "sessionFile"], source);
67
+ if (value.steps === undefined) {
68
+ return;
69
+ }
70
+ if (!Array.isArray(value.steps)) {
71
+ throw new Error(`Invalid async status '${source}': steps must be an array.`);
72
+ }
73
+ const steps: readonly unknown[] = value.steps;
74
+ steps.forEach((step, index) => {
75
+ if (!isRecord(step)) {
76
+ throw new Error(`Invalid async status '${source}': steps[${index}] must be an object.`);
77
+ }
78
+ if (typeof step.agent !== "string") {
79
+ throw new Error(`Invalid async status '${source}': steps[${index}].agent must be a string.`);
80
+ }
81
+ if (step.sessionFile !== undefined && typeof step.sessionFile !== "string") {
82
+ throw new Error(
83
+ `Invalid async status '${source}': steps[${index}].sessionFile must be a string.`,
84
+ );
85
+ }
86
+ });
55
87
  }
56
88
 
57
- function validateResultFile(data: ParsedAsyncResultFile, resultPath: string): ParsedAsyncResultFile {
58
- if (data.results !== undefined) {
59
- if (!Array.isArray(data.results)) throw new Error(`Invalid async result file '${resultPath}': results must be an array.`);
60
- data.results.forEach((child, index) => {
61
- const record = child as Record<string, unknown>;
62
- validateOptionalString(record, "agent", resultPath, `results[${index}].agent`);
63
- validateOptionalString(record, "sessionFile", resultPath, `results[${index}].sessionFile`);
64
- validateOptionalString(record, "intercomTarget", resultPath, `results[${index}].intercomTarget`);
65
- const success = child.success;
66
- if (success !== undefined && typeof success !== "boolean") throw new Error(`Invalid async result file '${resultPath}': results[${index}].success must be a boolean.`);
67
- });
68
- }
69
- const record = data as Record<string, unknown>;
70
- const success = data.success;
71
- if (success !== undefined && typeof success !== "boolean") throw new Error(`Invalid async result file '${resultPath}': success must be a boolean.`);
72
- validateOptionalString(record, "id", resultPath);
73
- validateOptionalString(record, "runId", resultPath);
74
- validateOptionalString(record, "agent", resultPath);
75
- validateOptionalString(record, "mode", resultPath);
76
- validateOptionalString(record, "state", resultPath);
77
- validateOptionalString(record, "cwd", resultPath);
78
- validateOptionalString(record, "sessionFile", resultPath);
79
- return data;
89
+ function validateResultRecord(value: unknown, resultPath: string, prefix = ""): void {
90
+ if (!isRecord(value)) {
91
+ throw new Error(`Invalid async result file '${resultPath}': expected an object.`);
92
+ }
93
+ const fields =
94
+ prefix.length > 0
95
+ ? ["agent", "sessionFile", "intercomTarget"]
96
+ : ["id", "runId", "agent", "mode", "state", "cwd", "sessionFile"];
97
+ for (const field of fields) {
98
+ if (value[field] !== undefined && typeof value[field] !== "string") {
99
+ throw new Error(
100
+ `Invalid async result file '${resultPath}': ${prefix}${field} must be a string.`,
101
+ );
102
+ }
103
+ }
104
+ if (value.success !== undefined && typeof value.success !== "boolean") {
105
+ throw new Error(
106
+ `Invalid async result file '${resultPath}': ${prefix}success must be a boolean.`,
107
+ );
108
+ }
80
109
  }
81
110
 
82
- function readResultFile(resultPath: string): ParsedAsyncResultFile {
83
- return validateResultFile(readAsyncResultFile(resultPath), resultPath);
111
+ function readResultFile(file: string): ParsedAsyncResultFile {
112
+ const data = readAsyncResultFile(file);
113
+ data.results?.forEach((child, index) => validateResultRecord(child, file, `results[${index}].`));
114
+ validateResultRecord(data, file);
115
+ return data;
84
116
  }
85
117
 
86
- function assertRunId(value: string | undefined, field: "id" | "runId"): string | undefined {
87
- if (value === undefined) return undefined;
88
- if (value.trim() === "") throw new Error(`${field} must not be empty.`);
89
- if (path.isAbsolute(value) || /[\\/]/.test(value) || value.includes("..")) {
90
- throw new Error(`${field} must be an async run id or prefix, not a path.`);
91
- }
92
- return value;
118
+ interface ResumeEvidence {
119
+ readonly location: AsyncRunLocation;
120
+ readonly status: ReadonlyInput<AsyncStatus> | null;
121
+ readonly result?: ReadonlyInput<ParsedAsyncResultFile>;
122
+ readonly runId: string;
123
+ readonly state: AsyncStatus["state"];
124
+ readonly stepCount: number;
125
+ readonly steps: ReadonlyInput<NonNullable<AsyncStatus["steps"]>>;
126
+ readonly resultSteps: ReadonlyInput<NonNullable<ParsedAsyncResultFile["results"]>>;
93
127
  }
94
128
 
95
- function assertInsideRoot(root: string, target: string, label: string): void {
96
- const rootPath = path.resolve(root);
97
- const targetPath = path.resolve(target);
98
- const relative = path.relative(rootPath, targetPath);
99
- if (relative === "" || (!relative.startsWith("..") && !path.isAbsolute(relative))) return;
100
- throw new Error(`${label} must be inside ${rootPath}.`);
129
+ function childEvidence(
130
+ status: ReadonlyInput<AsyncStatus> | null,
131
+ result: ReadonlyInput<ParsedAsyncResultFile> | undefined,
132
+ ): Pick<ResumeEvidence, "steps" | "resultSteps" | "stepCount"> {
133
+ const steps = status?.steps ?? [];
134
+ const resultSteps = result?.results ?? [];
135
+ const count = steps.length > 0 ? steps.length : resultSteps.length;
136
+ return { steps, resultSteps, stepCount: count > 0 ? count : Number(hasText(result?.agent)) };
101
137
  }
102
138
 
103
- function prefixedRunIds(dir: string, prefix: string, suffix = ""): string[] {
104
- if (!fs.existsSync(dir)) return [];
105
- return fs.readdirSync(dir)
106
- .filter((entry) => entry.startsWith(prefix) && (!suffix || entry.endsWith(suffix)))
107
- .map((entry) => suffix ? entry.slice(0, -suffix.length) : entry)
108
- .sort();
139
+ function persistedRunId(
140
+ location: AsyncRunLocation,
141
+ status: ReadonlyInput<AsyncStatus> | null,
142
+ result: ReadonlyInput<ParsedAsyncResultFile> | undefined,
143
+ ): string {
144
+ const fallback = location.asyncDir === null ? "unknown" : path.basename(location.asyncDir);
145
+ return status?.runId ?? result?.runId ?? result?.id ?? location.resolvedId ?? fallback;
109
146
  }
110
147
 
111
- export function asyncRunRoots(asyncDirRoot: string): string[] {
112
- return [...new Set([path.resolve(asyncDirRoot), path.resolve(QUESTIONS_DIR)])];
148
+ function resumeIdentity(
149
+ location: AsyncRunLocation,
150
+ status: ReadonlyInput<AsyncStatus> | null,
151
+ result: ReadonlyInput<ParsedAsyncResultFile> | undefined,
152
+ ): Pick<ResumeEvidence, "runId" | "state"> {
153
+ const runId = persistedRunId(location, status, result);
154
+ const state = status?.state ?? result?.terminalState;
155
+ if (state === undefined) {
156
+ throw new Error(`Status file not found for async run '${runId}'.`);
157
+ }
158
+ return { runId, state };
113
159
  }
114
160
 
115
- export function exactAsyncRunLocation(runId: string, asyncDirRoot: string, resultsDir: string): AsyncRunLocation {
116
- return resolveAsyncRunRecord(runId, asyncDirRoot, resultsDir, false).location;
161
+ function readEvidence(
162
+ params: ReadonlyInput<AsyncResumeParams>,
163
+ deps: AsyncResumeDeps,
164
+ ): ResumeEvidence {
165
+ const resultsDir = deps.resultsDir ?? RESULTS_DIR;
166
+ const location = resolveAsyncRunLocation(params, deps.asyncDirRoot ?? ASYNC_DIR, resultsDir);
167
+ if (location.asyncDir === null && location.resultPath === null) {
168
+ throw new Error("Async run not found. Provide id or dir.");
169
+ }
170
+ const status =
171
+ location.asyncDir === null
172
+ ? null
173
+ : reconcileAsyncRun(location.asyncDir, { resultsDir, kill: deps.kill, now: deps.now }).status;
174
+ validateStatusForResume(
175
+ status,
176
+ location.asyncDir === null ? "status.json" : path.join(location.asyncDir, "status.json"),
177
+ );
178
+ const result = location.resultPath === null ? undefined : readResultFile(location.resultPath);
179
+ return {
180
+ location,
181
+ status,
182
+ result,
183
+ ...resumeIdentity(location, status, result),
184
+ ...childEvidence(status, result),
185
+ };
117
186
  }
118
187
 
119
- /** Resolve canonical precedence and decode each candidate status once for this pass. */
120
- export function readAsyncRunRecord(runId: string, asyncDirRoot: string, resultsDir: string): AsyncRunRecord {
121
- return resolveAsyncRunRecord(runId, asyncDirRoot, resultsDir, true);
188
+ function assertIndex(evidence: ReadonlyInput<ResumeEvidence>, index: number): void {
189
+ if (!Number.isInteger(index)) {
190
+ throw new Error(`Async run '${evidence.runId}' index must be an integer.`);
191
+ }
192
+ if (index < 0 || index >= evidence.stepCount) {
193
+ throw new Error(
194
+ `Async run '${evidence.runId}' has ${evidence.stepCount} children. Index ${index} is out of range.`,
195
+ );
196
+ }
122
197
  }
123
198
 
124
- function resolveAsyncRunRecord(runId: string, asyncDirRoot: string, resultsDir: string, readLegacyStatus: boolean): AsyncRunRecord {
125
- assertRunId(runId, "id");
126
- const durableDir = path.join(QUESTIONS_DIR, runId);
127
- const legacyDir = path.join(asyncDirRoot, runId);
128
- const durableStatus = readStatus(durableDir);
129
- const durableResult = path.join(durableDir, "result.json");
130
- const durable = isDurableRun(durableStatus) || isDurableRun(readRunJson<object>(path.join(durableDir, "launch.json")));
131
- const asyncDir = durable ? durableDir : fs.existsSync(legacyDir) ? legacyDir : durableStatus ? durableDir : null;
132
- const status = asyncDir === durableDir ? durableStatus : asyncDir && readLegacyStatus ? readStatus(asyncDir) : null;
133
- return {
134
- location: { asyncDir, resultPath: fs.existsSync(durableResult) ? durableResult : exactResultPath(resultsDir, runId), resolvedId: runId },
135
- status,
136
- durable: durable || isDurableRun(status),
137
- };
199
+ function baseTarget(
200
+ evidence: ReadonlyInput<ResumeEvidence>,
201
+ agent: string,
202
+ index: number,
203
+ ): Omit<AsyncResumeTarget, "kind"> {
204
+ return {
205
+ runId: evidence.runId,
206
+ asyncDir: evidence.location.asyncDir ?? undefined,
207
+ state: evidence.state,
208
+ agent,
209
+ index,
210
+ intercomTarget: resolveSubagentIntercomTarget(evidence.runId, agent, index),
211
+ cwd: evidence.status?.cwd ?? evidence.result?.cwd,
212
+ };
138
213
  }
139
214
 
140
- function exactResultPath(resultsDir: string, runId: string): string | null {
141
- const resultPath = path.join(resultsDir, `${runId}.json`);
142
- assertInsideRoot(resultsDir, resultPath, "Async result file");
143
- return fs.existsSync(resultPath) ? resultPath : null;
215
+ function liveIndex(evidence: ReadonlyInput<ResumeEvidence>, requested: number | undefined): number {
216
+ if (requested !== undefined) {
217
+ return requested;
218
+ }
219
+ const running = evidence.steps
220
+ .map((step, index) => ({ step, index }))
221
+ .filter(({ step }) => step.status === "running");
222
+ const selected = running.at(0);
223
+ if (running.length !== 1 || selected === undefined) {
224
+ throw new Error(
225
+ `Async run '${evidence.runId}' has ${running.length} running children. Provide index to choose one.`,
226
+ );
227
+ }
228
+ return selected.index;
144
229
  }
145
230
 
146
- export function findAsyncRunPrefixMatches(prefix: string, asyncDirRoot: string, resultsDir: string): Array<{ id: string; location: AsyncRunLocation }> {
147
- const requestedId = assertRunId(prefix, "id");
148
- if (!requestedId) return [];
149
- const asyncRoot = path.resolve(asyncDirRoot);
150
- const resultRoot = path.resolve(resultsDir);
151
- const matchingIds = [...new Set([
152
- ...prefixedRunIds(asyncRoot, requestedId),
153
- ...prefixedRunIds(QUESTIONS_DIR, requestedId).filter((id) => fs.existsSync(path.join(QUESTIONS_DIR, id, "status.json")) || fs.existsSync(path.join(QUESTIONS_DIR, id, "result.json")) || fs.existsSync(path.join(QUESTIONS_DIR, id, "launch.json"))),
154
- ...prefixedRunIds(resultRoot, requestedId, ".json"),
155
- ])].sort();
156
- return matchingIds.map((id) => ({ id, location: exactAsyncRunLocation(id, asyncRoot, resultRoot) }));
231
+ function liveTarget(
232
+ evidence: ReadonlyInput<ResumeEvidence>,
233
+ requestedIndex: number | undefined,
234
+ ): AsyncResumeTarget | undefined {
235
+ if (evidence.state !== "running") {
236
+ return undefined;
237
+ }
238
+ const steps = evidence.steps;
239
+ const index = liveIndex(evidence, requestedIndex);
240
+ assertIndex(evidence, index);
241
+ const step = steps.at(index);
242
+ if (step?.status === "running") {
243
+ return {
244
+ ...baseTarget(evidence, step.agent, index),
245
+ kind: "live",
246
+ sessionFile: childSession(evidence, index),
247
+ };
248
+ }
249
+ if (step?.status === "pending") {
250
+ throw new Error(
251
+ `Async run '${evidence.runId}' child ${index} is pending and has not started yet. Wait for it to run or complete before resuming.`,
252
+ );
253
+ }
254
+ if (step && !["complete", "completed", "failed", "blocked", "paused"].includes(step.status)) {
255
+ throw new Error(
256
+ `Async run '${evidence.runId}' child ${index} is ${step.status} and cannot be revived yet.`,
257
+ );
258
+ }
259
+ return undefined;
157
260
  }
158
261
 
159
- export function resolveAsyncRunLocation(params: AsyncResumeParams, asyncDirRoot: string, resultsDir: string): AsyncRunLocation {
160
- const asyncRoot = path.resolve(asyncDirRoot);
161
- const resultRoot = path.resolve(resultsDir);
162
- const requestedId = assertRunId(params.id, "id") ?? assertRunId(params.runId, "runId");
163
- if (params.dir) {
164
- const asyncDir = path.resolve(params.dir);
165
- if (!asyncRunRoots(asyncRoot).some((root) => {
166
- const relative = path.relative(root, asyncDir);
167
- return relative === "" || (!relative.startsWith("..") && !path.isAbsolute(relative));
168
- })) {
169
- throw new Error(`Async run directory must be inside ${asyncRunRoots(asyncRoot).join(" or ")}.`);
170
- }
171
- const resolvedId = requestedId ?? path.basename(asyncDir);
172
- if (requestedId && requestedId !== path.basename(asyncDir)) {
173
- throw new Error(`Async run id '${requestedId}' does not match directory '${path.basename(asyncDir)}'.`);
174
- }
175
- const location = exactAsyncRunLocation(resolvedId, asyncRoot, resultRoot);
176
- const canonical = location.asyncDir && isDurableRun(readRunJson<object>(path.join(location.asyncDir, "launch.json")));
177
- return { ...location, asyncDir: canonical ? location.asyncDir : asyncDir };
178
- }
179
- if (!requestedId) return { asyncDir: null, resultPath: null };
180
-
181
- const direct = exactAsyncRunLocation(requestedId, asyncRoot, resultRoot);
182
- if (direct.asyncDir || direct.resultPath) return direct;
183
-
184
- const matching = findAsyncRunPrefixMatches(requestedId, asyncRoot, resultRoot);
185
- if (matching.length === 0) return { asyncDir: null, resultPath: null, resolvedId: requestedId };
186
- if (matching.length > 1) {
187
- throw new Error(formatRunIdAmbiguity("async", requestedId, matching.map((match) => match.id)));
188
- }
189
- return matching[0]!.location;
262
+ function validateResumeSessionFile(runId: string, sessionFile: string): string {
263
+ if (path.extname(sessionFile) !== ".jsonl") {
264
+ throw new Error(`Async run '${runId}' session file must be a .jsonl file: ${sessionFile}`);
265
+ }
266
+ const resolved = path.resolve(sessionFile);
267
+ if (!fs.existsSync(resolved)) {
268
+ throw new Error(`Async run '${runId}' session file does not exist: ${sessionFile}`);
269
+ }
270
+ return resolved;
190
271
  }
191
272
 
192
- function validateStatusForResume(status: AsyncStatus | null, source: string): void {
193
- if (!status) return;
194
- if (typeof status.runId !== "string") throw new Error(`Invalid async status '${source}': runId must be a string.`);
195
- if (status.sessionId !== undefined && typeof status.sessionId !== "string") throw new Error(`Invalid async status '${source}': sessionId must be a string.`);
196
- if (status.cwd !== undefined && typeof status.cwd !== "string") throw new Error(`Invalid async status '${source}': cwd must be a string.`);
197
- if (status.sessionFile !== undefined && typeof status.sessionFile !== "string") throw new Error(`Invalid async status '${source}': sessionFile must be a string.`);
198
- if (status.steps !== undefined) {
199
- if (!Array.isArray(status.steps)) throw new Error(`Invalid async status '${source}': steps must be an array.`);
200
- status.steps.forEach((step, index) => {
201
- if (!step || typeof step !== "object" || Array.isArray(step)) throw new Error(`Invalid async status '${source}': steps[${index}] must be an object.`);
202
- if (typeof step.agent !== "string") throw new Error(`Invalid async status '${source}': steps[${index}].agent must be a string.`);
203
- if (step.sessionFile !== undefined && typeof step.sessionFile !== "string") throw new Error(`Invalid async status '${source}': steps[${index}].sessionFile must be a string.`);
204
- });
205
- }
273
+ function childAgent(
274
+ evidence: ReadonlyInput<ResumeEvidence>,
275
+ index: number,
276
+ fallback?: string,
277
+ ): string | undefined {
278
+ return (
279
+ evidence.steps.at(index)?.agent ??
280
+ evidence.resultSteps.at(index)?.agent ??
281
+ evidence.result?.agent ??
282
+ fallback
283
+ );
206
284
  }
207
285
 
208
- function validateResumeSessionFile(runId: string, sessionFile: string): string {
209
- if (path.extname(sessionFile) !== ".jsonl") throw new Error(`Async run '${runId}' session file must be a .jsonl file: ${sessionFile}`);
210
- const resolved = path.resolve(sessionFile);
211
- if (!fs.existsSync(resolved)) throw new Error(`Async run '${runId}' session file does not exist: ${sessionFile}`);
212
- return resolved;
286
+ function childSession(evidence: ReadonlyInput<ResumeEvidence>, index: number): string | undefined {
287
+ const fallback =
288
+ evidence.stepCount === 1
289
+ ? (evidence.status?.sessionFile ?? evidence.result?.sessionFile)
290
+ : undefined;
291
+ return (
292
+ evidence.steps.at(index)?.sessionFile ?? evidence.resultSteps.at(index)?.sessionFile ?? fallback
293
+ );
213
294
  }
214
295
 
215
- export function resolveAsyncResumeTarget(params: AsyncResumeParams, deps: AsyncResumeDeps = {}): AsyncResumeTarget {
216
- const asyncDirRoot = deps.asyncDirRoot ?? ASYNC_DIR;
217
- const resultsDir = deps.resultsDir ?? RESULTS_DIR;
218
- const location = resolveAsyncRunLocation(params, asyncDirRoot, resultsDir);
219
- if (!location.asyncDir && !location.resultPath) {
220
- throw new Error("Async run not found. Provide id or dir.");
221
- }
222
-
223
- const reconciliation = location.asyncDir
224
- ? reconcileAsyncRun(location.asyncDir, { resultsDir, kill: deps.kill, now: deps.now })
225
- : undefined;
226
- const status = reconciliation?.status ?? null;
227
- validateStatusForResume(status, location.asyncDir ? path.join(location.asyncDir, "status.json") : "status.json");
228
- const result = location.resultPath ? readResultFile(location.resultPath) : undefined;
229
- const runId = status?.runId ?? result?.runId ?? result?.id ?? location.resolvedId ?? (location.asyncDir ? path.basename(location.asyncDir) : "unknown");
230
- const state = status?.state ?? result?.terminalState;
231
- if (!state) throw new Error(`Status file not found for async run '${runId}'.`);
232
-
233
- const statusSteps = status?.steps ?? [];
234
- const resultSteps = result?.results ?? [];
235
- const stepCount = statusSteps.length || resultSteps.length || (result?.agent ? 1 : 0);
236
- const requestedIndex = params.index;
237
- if (requestedIndex !== undefined && !Number.isInteger(requestedIndex)) throw new Error(`Async run '${runId}' index must be an integer.`);
238
- const terminalStepStatuses = new Set(["complete", "completed", "failed", "blocked", "paused"]);
296
+ function childAcceptance(
297
+ evidence: ReadonlyInput<ResumeEvidence>,
298
+ index: number,
299
+ ): ResolvedAcceptanceConfig | undefined {
300
+ return (
301
+ evidence.steps.at(index)?.acceptance?.effectiveAcceptance ??
302
+ evidence.resultSteps.at(index)?.acceptance?.effectiveAcceptance
303
+ );
304
+ }
239
305
 
240
- if (state === "running") {
241
- if (requestedIndex !== undefined) {
242
- if (requestedIndex < 0 || requestedIndex >= stepCount) throw new Error(`Async run '${runId}' has ${stepCount} children. Index ${requestedIndex} is out of range.`);
243
- const selectedStep = statusSteps[requestedIndex];
244
- if (selectedStep?.status === "running") {
245
- return {
246
- kind: "live",
247
- runId,
248
- asyncDir: location.asyncDir ?? undefined,
249
- state,
250
- agent: selectedStep.agent,
251
- index: requestedIndex,
252
- intercomTarget: resolveSubagentIntercomTarget(runId, selectedStep.agent, requestedIndex),
253
- cwd: status?.cwd ?? result?.cwd,
254
- sessionFile: selectedStep.sessionFile ?? status?.sessionFile ?? result?.sessionFile,
255
- };
256
- }
257
- if (selectedStep?.status === "pending") throw new Error(`Async run '${runId}' child ${requestedIndex} is pending and has not started yet. Wait for it to run or complete before resuming.`);
258
- if (selectedStep && !terminalStepStatuses.has(selectedStep.status)) throw new Error(`Async run '${runId}' child ${requestedIndex} is ${selectedStep.status} and cannot be revived yet.`);
259
- } else {
260
- const running = statusSteps
261
- .map((step, index) => ({ step, index }))
262
- .filter(({ step }) => step.status === "running");
263
- const selected = running.length === 1 ? running[0] : undefined;
264
- if (!selected) {
265
- throw new Error(`Async run '${runId}' has ${running.length} running children. Provide index to choose one.`);
266
- }
267
- return {
268
- kind: "live",
269
- runId,
270
- asyncDir: location.asyncDir ?? undefined,
271
- state,
272
- agent: selected.step.agent,
273
- index: selected.index,
274
- intercomTarget: resolveSubagentIntercomTarget(runId, selected.step.agent, selected.index),
275
- cwd: status?.cwd ?? result?.cwd,
276
- sessionFile: selected.step.sessionFile ?? status?.sessionFile ?? result?.sessionFile,
277
- };
278
- }
279
- }
306
+ function contractIsLive(
307
+ contract: ReadonlyInput<SupervisorRunContract> | undefined,
308
+ kill: AsyncResumeDeps["kill"],
309
+ ): boolean {
310
+ const pid = contract?.pid;
311
+ return pid !== undefined && pid !== 0 && checkPidLiveness(pid, kill) !== "dead";
312
+ }
280
313
 
281
- if (stepCount > 1 && requestedIndex === undefined) {
282
- throw new Error(`Async run '${runId}' has ${stepCount} children. Provide index to choose one.`);
283
- }
284
- const index = requestedIndex ?? 0;
285
- if (!Number.isInteger(index)) throw new Error(`Async run '${runId}' index must be an integer.`);
286
- if (index < 0 || index >= stepCount) throw new Error(`Async run '${runId}' has ${stepCount} children. Index ${index} is out of range.`);
287
- const contract = readQuestionContract(runId, index);
288
- if (contract?.pid && checkPidLiveness(contract.pid, deps.kill) !== "dead") {
289
- const agent = statusSteps[index]?.agent ?? resultSteps[index]?.agent ?? result?.agent ?? contract.launch?.agent.name;
290
- if (!agent) throw new Error(`Could not determine child agent for async run '${runId}'.`);
291
- return { kind: "live", runId, asyncDir: location.asyncDir ?? undefined, state, agent, index,
292
- intercomTarget: resolveSubagentIntercomTarget(runId, agent, index), cwd: status?.cwd ?? result?.cwd, sessionFile: contract.sessionFile };
293
- }
294
- const agent = statusSteps[index]?.agent ?? resultSteps[index]?.agent ?? result?.agent;
295
- if (!agent) throw new Error(`Could not determine child agent for async run '${runId}'.`);
296
- const sessionFile = statusSteps[index]?.sessionFile
297
- ?? resultSteps[index]?.sessionFile
298
- ?? (stepCount === 1 ? status?.sessionFile ?? result?.sessionFile : undefined);
299
- if (!sessionFile) throw new Error(`Async run '${runId}' child ${index} does not have a persisted session file to resume from.`);
300
- const resolvedSessionFile = validateResumeSessionFile(runId, sessionFile);
301
- const effectiveAcceptance = statusSteps[index]?.acceptance?.effectiveAcceptance
302
- ?? resultSteps[index]?.acceptance?.effectiveAcceptance;
314
+ function revivalTarget(
315
+ evidence: ReadonlyInput<ResumeEvidence>,
316
+ index: number,
317
+ deps: AsyncResumeDeps,
318
+ ): AsyncResumeTarget {
319
+ const contract = readQuestionContract(evidence.runId, index);
320
+ const live = contractIsLive(contract, deps.kill);
321
+ const agent = childAgent(evidence, index, live ? contract?.launch?.agent.name : undefined);
322
+ if (!hasText(agent)) {
323
+ throw new Error(`Could not determine child agent for async run '${evidence.runId}'.`);
324
+ }
325
+ const base = baseTarget(evidence, agent, index);
326
+ if (live) {
327
+ return { ...base, kind: "live", sessionFile: contract?.sessionFile };
328
+ }
329
+ const sessionFile = childSession(evidence, index);
330
+ if (!hasText(sessionFile)) {
331
+ throw new Error(
332
+ `Async run '${evidence.runId}' child ${index} does not have a persisted session file to resume from.`,
333
+ );
334
+ }
335
+ return {
336
+ ...base,
337
+ kind: "revive",
338
+ sessionFile: validateResumeSessionFile(evidence.runId, sessionFile),
339
+ effectiveAcceptance: childAcceptance(evidence, index),
340
+ };
341
+ }
303
342
 
304
- return {
305
- kind: "revive",
306
- runId,
307
- asyncDir: location.asyncDir ?? undefined,
308
- state,
309
- agent,
310
- index,
311
- intercomTarget: resolveSubagentIntercomTarget(runId, agent, index),
312
- cwd: status?.cwd ?? result?.cwd,
313
- sessionFile: resolvedSessionFile,
314
- effectiveAcceptance,
315
- };
343
+ export function resolveAsyncResumeTarget(
344
+ params: ReadonlyInput<AsyncResumeParams>,
345
+ deps: AsyncResumeDeps = {},
346
+ ): AsyncResumeTarget {
347
+ const evidence = readEvidence(params, deps);
348
+ if (params.index !== undefined && !Number.isInteger(params.index)) {
349
+ throw new Error(`Async run '${evidence.runId}' index must be an integer.`);
350
+ }
351
+ const live = liveTarget(evidence, params.index);
352
+ if (live) {
353
+ return live;
354
+ }
355
+ if (evidence.stepCount > 1 && params.index === undefined) {
356
+ throw new Error(
357
+ `Async run '${evidence.runId}' has ${evidence.stepCount} children. Provide index to choose one.`,
358
+ );
359
+ }
360
+ const index = params.index ?? 0;
361
+ assertIndex(evidence, index);
362
+ return revivalTarget(evidence, index, deps);
316
363
  }
317
364
 
318
- export function buildRevivedAsyncTask(target: Pick<AsyncResumeTarget, "runId" | "agent" | "sessionFile">, message: string, origin?: "human"): string {
319
- return [
320
- "You are reviving a previous subagent conversation.",
321
- "",
322
- `Original run: ${target.runId}`,
323
- `Original agent: ${target.agent}`,
324
- target.sessionFile ? `Original session file: ${target.sessionFile}` : undefined,
325
- "",
326
- origin === "human"
327
- ? "Use the stored session context as background. This is a direct user follow-up (human origin); respond in this conversation where the user can see it. Do not relay it to the parent."
328
- : "Use the stored session context as background. Answer the orchestrator's follow-up below. Do not assume the original child process is still alive.",
329
- "",
330
- "Follow-up:",
331
- message,
332
- ].filter((line): line is string => line !== undefined).join("\n");
365
+ export function buildRevivedAsyncTask(
366
+ target: Readonly<Pick<AsyncResumeTarget, "runId" | "agent" | "sessionFile">>,
367
+ message: string,
368
+ origin?: "human",
369
+ ): string {
370
+ return [
371
+ "You are reviving a previous subagent conversation.",
372
+ "",
373
+ `Original run: ${target.runId}`,
374
+ `Original agent: ${target.agent}`,
375
+ hasText(target.sessionFile) ? `Original session file: ${target.sessionFile}` : undefined,
376
+ "",
377
+ origin === "human"
378
+ ? "Use the stored session context as background. This is a direct user follow-up (human origin); respond in this conversation where the user can see it. Do not relay it to the parent."
379
+ : "Use the stored session context as background. Answer the orchestrator's follow-up below. Do not assume the original child process is still alive.",
380
+ "",
381
+ "Follow-up:",
382
+ message,
383
+ ]
384
+ .filter((line) => line !== undefined)
385
+ .join("\n");
333
386
  }