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