@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,96 +1,27 @@
1
- import { spawn, spawnSync } from "node:child_process";
2
- import { addAbortListener } from "node:events";
3
1
  import * as fs from "node:fs";
4
- import * as os from "node:os";
5
2
  import * as path from "node:path";
6
- import { TEMP_ROOT_DIR } from "../../shared/types.js";
3
+ import { errorMessage as getErrorMessage, hasErrorCode } from "../../shared/unknown.js";
4
+ import { markWorktreesForPreservation } from "./worktree-preservation.js";
5
+ import { buildWorktreeBranch, buildWorktreePath } from "./worktree-location.js";
6
+ export { findWorktreeTaskCwdConflict, formatWorktreeTaskCwdConflict, resolveExpectedWorktreeAgentCwd, } from "./worktree-location.js";
7
7
  import { ensureTempRoot } from "../../shared/temp-root.js";
8
- import { trySignalChildTree } from "../../shared/post-exit-stdio-guard.js";
8
+ import { runGitChecked, runSetupCommand, runSetupGit } from "./worktree-process.js";
9
+ import { DEFAULT_WORKTREE_SETUP_HOOK_TIMEOUT_MS, resolveWorktreeSetupHook, runWorktreeSetupHook, } from "./worktree-hook.js";
9
10
  export class WorktreeCleanupError extends Error {
10
11
  }
11
- const DEFAULT_WORKTREE_SETUP_HOOK_TIMEOUT_MS = 30000;
12
- function runGit(cwd, args) {
13
- const result = spawnSync("git", ["-C", cwd, ...args], { encoding: "utf-8" });
14
- return {
15
- stdout: result.stdout ?? "",
16
- stderr: result.stderr ?? "",
17
- status: result.status,
18
- };
19
- }
20
- function runGitChecked(cwd, args) {
21
- const result = runGit(cwd, args);
22
- if (result.status !== 0) {
23
- const command = `git -C ${cwd} ${args.join(" ")}`;
24
- const message = result.stderr.trim() || result.stdout.trim() || `${command} failed`;
25
- throw new Error(message);
26
- }
27
- return result.stdout;
28
- }
29
- function runSetupCommand(command, args, cwd, signal, input, timeoutMs) {
30
- signal?.throwIfAborted();
31
- return new Promise((resolve, reject) => {
32
- let stdout = "";
33
- let stderr = "";
34
- let outputBytes = 0;
35
- let failure;
36
- const child = spawn(command, args, { cwd, detached: true, stdio: "pipe" });
37
- const terminate = () => { trySignalChildTree(child, "SIGKILL"); };
38
- const abortListener = signal && addAbortListener(signal, terminate);
39
- const timer = timeoutMs === undefined ? undefined : setTimeout(() => {
40
- failure = new Error(`worktree setup hook timed out after ${timeoutMs}ms`);
41
- terminate();
42
- }, timeoutMs);
43
- timer?.unref();
44
- for (const stream of [child.stdout, child.stderr]) {
45
- stream.setEncoding("utf8");
46
- stream.on("data", (chunk) => {
47
- outputBytes += Buffer.byteLength(chunk);
48
- // Keep the previous spawnSync output bound.
49
- if (outputBytes > 1024 * 1024) {
50
- failure ??= new Error(`${command} output exceeded 1048576 bytes`);
51
- terminate();
52
- }
53
- else if (stream === child.stdout)
54
- stdout += chunk;
55
- else
56
- stderr += chunk;
57
- });
58
- }
59
- child.on("error", (error) => { failure = error; terminate(); });
60
- child.on("exit", (status) => { if (status !== 0)
61
- terminate(); });
62
- child.on("close", (status) => {
63
- clearTimeout(timer);
64
- abortListener?.[Symbol.dispose]();
65
- if (signal?.aborted)
66
- reject(signal.reason);
67
- else if (failure)
68
- reject(failure);
69
- else
70
- resolve({ stdout, stderr, status });
71
- });
72
- child.stdin.on("error", (error) => {
73
- if (error.code === "EPIPE")
74
- return; // The hook can exit without reading its payload.
75
- failure = error;
76
- terminate();
77
- });
78
- child.stdin.end(input);
79
- });
80
- }
81
- async function runSetupGit(cwd, args, signal) {
82
- const result = await runSetupCommand("git", ["-C", cwd, ...args], cwd, signal);
83
- if (result.status !== 0) {
84
- throw new Error(result.stderr.trim() || result.stdout.trim() || `git -C ${cwd} ${args.join(" ")} failed`);
85
- }
86
- return result.stdout;
87
- }
88
12
  async function resolveRepoState(cwd, signal) {
89
- const repoCheck = await runSetupCommand("git", ["-C", cwd, "rev-parse", "--is-inside-work-tree"], cwd, signal);
13
+ const repoCheck = await runSetupCommand({
14
+ command: "git",
15
+ args: ["-C", cwd, "rev-parse", "--is-inside-work-tree"],
16
+ cwd,
17
+ signal,
18
+ });
90
19
  if (repoCheck.status !== 0 || repoCheck.stdout.trim() !== "true") {
91
20
  throw new Error("worktree isolation requires a git repository");
92
21
  }
93
- const cwdRelative = (await runSetupGit(cwd, ["rev-parse", "--show-prefix"], signal)).trim().replace(/[\\/]+$/, "");
22
+ const cwdRelative = (await runSetupGit(cwd, ["rev-parse", "--show-prefix"], signal))
23
+ .trim()
24
+ .replace(/[\\/]+$/, "");
94
25
  const toplevel = (await runSetupGit(cwd, ["rev-parse", "--show-toplevel"], signal)).trim();
95
26
  const status = await runSetupGit(toplevel, ["status", "--porcelain"], signal);
96
27
  if (status.trim().length > 0) {
@@ -99,184 +30,37 @@ async function resolveRepoState(cwd, signal) {
99
30
  const baseCommit = (await runSetupGit(toplevel, ["rev-parse", "HEAD"], signal)).trim();
100
31
  return { toplevel, cwdRelative, baseCommit };
101
32
  }
102
- function normalizeComparableCwd(cwd) {
103
- const resolved = path.resolve(cwd);
104
- try {
105
- return fs.realpathSync(resolved);
106
- }
107
- catch {
108
- // Use the unresolved absolute path when realpath resolution is unavailable.
109
- return resolved;
110
- }
111
- }
112
- export function findWorktreeTaskCwdConflict(tasks, sharedCwd) {
113
- const normalizedSharedCwd = normalizeComparableCwd(sharedCwd);
114
- for (let index = 0; index < tasks.length; index++) {
115
- const task = tasks[index];
116
- if (!task.cwd)
117
- continue;
118
- const taskCwd = path.isAbsolute(task.cwd) ? task.cwd : path.resolve(sharedCwd, task.cwd);
119
- if (normalizeComparableCwd(taskCwd) === normalizedSharedCwd)
120
- continue;
121
- return { index, agent: task.agent, cwd: task.cwd };
122
- }
123
- return undefined;
124
- }
125
- export function formatWorktreeTaskCwdConflict(conflict, sharedCwd) {
126
- return `worktree isolation uses the shared cwd (${sharedCwd}); task ${conflict.index + 1} (${conflict.agent}) sets cwd to ${conflict.cwd}. Remove task-level cwd overrides or disable worktree.`;
127
- }
128
33
  function safePatchAgentName(agent) {
129
34
  return agent.replace(/[^\w.-]/g, "_");
130
35
  }
131
- function buildWorktreeBranch(runId, index) {
132
- return `pi-parallel-${runId}-${index}`;
133
- }
134
- function buildWorktreePath(runId, index) {
135
- return path.join(TEMP_ROOT_DIR, "worktrees", `pi-worktree-${runId}-${index}`);
36
+ function escapesRoot(relative) {
37
+ return relative === ".." || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative);
136
38
  }
137
- function resolveRepoCwdRelative(cwd) {
138
- const repoCheck = runGit(cwd, ["rev-parse", "--is-inside-work-tree"]);
139
- if (repoCheck.status !== 0 || repoCheck.stdout.trim() !== "true") {
140
- throw new Error("worktree isolation requires a git repository");
141
- }
142
- const rawPrefix = runGitChecked(cwd, ["rev-parse", "--show-prefix"]).trim();
143
- const normalizedPrefix = rawPrefix
144
- ? path.normalize(rawPrefix.replace(/[\\/]+$/, ""))
145
- : "";
146
- return normalizedPrefix === "." ? "" : normalizedPrefix;
147
- }
148
- export function resolveExpectedWorktreeAgentCwd(cwd, runId, index) {
149
- const cwdRelative = resolveRepoCwdRelative(cwd);
150
- const worktreePath = buildWorktreePath(runId, index);
151
- return cwdRelative ? path.join(worktreePath, cwdRelative) : worktreePath;
152
- }
153
- function parseHookTimeout(timeoutMs) {
154
- if (timeoutMs === undefined)
155
- return DEFAULT_WORKTREE_SETUP_HOOK_TIMEOUT_MS;
156
- if (!Number.isInteger(timeoutMs) || timeoutMs <= 0) {
157
- throw new Error("worktree setup hook timeout must be an integer greater than 0");
158
- }
159
- return timeoutMs;
160
- }
161
- function resolveWorktreeSetupHook(repoRoot, config) {
162
- if (!config)
163
- return undefined;
164
- const hookPath = config.hookPath.trim();
165
- if (!hookPath) {
166
- throw new Error("worktree setup hook path cannot be empty");
167
- }
168
- const expandedHookPath = hookPath.startsWith("~/") ? path.join(os.homedir(), hookPath.slice(2)) : hookPath;
169
- let resolvedPath;
170
- if (path.isAbsolute(expandedHookPath)) {
171
- resolvedPath = expandedHookPath;
172
- }
173
- else if (expandedHookPath.includes("/") || expandedHookPath.includes("\\")) {
174
- resolvedPath = path.resolve(repoRoot, expandedHookPath);
175
- }
176
- else {
177
- throw new Error("worktree setup hook must be an absolute path or a repo-relative path");
178
- }
179
- if (!fs.existsSync(resolvedPath)) {
180
- throw new Error(`worktree setup hook not found: ${resolvedPath}`);
181
- }
182
- if (fs.statSync(resolvedPath).isDirectory()) {
183
- throw new Error(`worktree setup hook must be a file, got directory: ${resolvedPath}`);
184
- }
185
- return {
186
- hookPath: resolvedPath,
187
- timeoutMs: parseHookTimeout(config.timeoutMs),
188
- };
189
- }
190
- function normalizeSyntheticPath(worktreePath, rawPath) {
191
- const trimmed = rawPath.trim();
192
- if (!trimmed)
193
- throw new Error("synthetic path cannot be empty");
194
- if (path.isAbsolute(trimmed))
195
- throw new Error(`synthetic path must be relative: ${rawPath}`);
196
- const resolved = path.resolve(worktreePath, trimmed);
197
- const relative = path.relative(worktreePath, resolved);
198
- if (!relative || relative === ".") {
199
- throw new Error(`synthetic path cannot target the worktree root: ${rawPath}`);
200
- }
201
- if (relative === ".." || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative)) {
202
- throw new Error(`synthetic path escapes the worktree root: ${rawPath}`);
203
- }
204
- return path.normalize(relative);
205
- }
206
- async function hasTrackedEntries(worktreePath, relativePath, signal) {
207
- const result = await runSetupCommand("git", ["-C", worktreePath, "ls-files", "--", relativePath], worktreePath, signal);
208
- return result.status === 0 && result.stdout.trim().length > 0;
209
- }
210
- function parseWorktreeSetupHookOutput(rawStdout) {
211
- const trimmed = rawStdout.trim();
212
- if (!trimmed) {
213
- throw new Error("worktree setup hook returned empty stdout; expected JSON object");
214
- }
215
- let parsed;
39
+ function readSyntheticStat(resolved) {
216
40
  try {
217
- parsed = JSON.parse(trimmed);
41
+ return fs.lstatSync(resolved);
218
42
  }
219
43
  catch (error) {
220
- const message = error instanceof Error ? error.message : String(error);
221
- throw new Error(`worktree setup hook returned invalid JSON: ${message}`);
222
- }
223
- if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
224
- throw new Error("worktree setup hook stdout must be a JSON object");
225
- }
226
- return parsed;
227
- }
228
- async function runWorktreeSetupHook(hook, input, signal) {
229
- let result;
230
- try {
231
- result = await runSetupCommand(hook.hookPath, [], input.worktreePath, signal, JSON.stringify(input), hook.timeoutMs);
232
- }
233
- catch (error) {
234
- signal?.throwIfAborted();
235
- throw new Error(`worktree setup hook failed: ${getErrorMessage(error)}`);
236
- }
237
- if (result.status !== 0) {
238
- const details = result.stderr.trim() || result.stdout.trim() || "no output";
239
- throw new Error(`worktree setup hook failed with exit code ${result.status}: ${details}`);
240
- }
241
- const output = parseWorktreeSetupHookOutput(result.stdout);
242
- if (output.syntheticPaths === undefined)
243
- return [];
244
- if (!Array.isArray(output.syntheticPaths)) {
245
- throw new Error("worktree setup hook output field 'syntheticPaths' must be an array of relative paths");
246
- }
247
- const uniquePaths = new Set();
248
- for (const candidate of output.syntheticPaths) {
249
- if (typeof candidate !== "string") {
250
- throw new Error("worktree setup hook output field 'syntheticPaths' must contain only strings");
44
+ if (hasErrorCode(error, "ENOENT")) {
45
+ return undefined;
251
46
  }
252
- const normalizedPath = normalizeSyntheticPath(input.worktreePath, candidate);
253
- if (await hasTrackedEntries(input.worktreePath, normalizedPath, signal)) {
254
- throw new Error(`worktree setup hook cannot mark tracked paths as synthetic: ${normalizedPath}`);
255
- }
256
- uniquePaths.add(normalizedPath);
47
+ throw error;
257
48
  }
258
- return [...uniquePaths];
259
49
  }
260
50
  function removeSyntheticPath(worktree, syntheticPath) {
261
51
  const resolved = path.resolve(worktree.path, syntheticPath);
262
52
  const relative = path.relative(worktree.path, resolved);
263
- if (!relative || relative === "." || relative === ".." || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative)) {
53
+ if (relative.length === 0 || relative === "." || escapesRoot(relative)) {
264
54
  return;
265
55
  }
266
- let stat;
267
- try {
268
- stat = fs.lstatSync(resolved);
269
- }
270
- catch (error) {
271
- const code = error && typeof error === "object" && "code" in error ? error.code : undefined;
272
- if (code === "ENOENT")
273
- return;
274
- throw error;
56
+ const stat = readSyntheticStat(resolved);
57
+ if (!stat) {
58
+ return;
275
59
  }
276
60
  const realRoot = fs.realpathSync(worktree.path);
277
61
  const realParent = fs.realpathSync(path.dirname(resolved));
278
62
  const parentRelative = path.relative(realRoot, realParent);
279
- if (parentRelative === ".." || parentRelative.startsWith(`..${path.sep}`) || path.isAbsolute(parentRelative)) {
63
+ if (escapesRoot(parentRelative)) {
280
64
  throw new Error(`synthetic path resolves outside the worktree: ${syntheticPath}`);
281
65
  }
282
66
  if (stat.isSymbolicLink()) {
@@ -290,28 +74,25 @@ function removeSyntheticPath(worktree, syntheticPath) {
290
74
  fs.rmSync(resolved, { force: true });
291
75
  }
292
76
  function removeSyntheticPathsBeforeDiff(worktree) {
293
- if (worktree.syntheticPaths.length === 0)
77
+ if (worktree.syntheticPaths.length === 0) {
294
78
  return;
79
+ }
295
80
  const seen = new Set();
296
81
  for (const syntheticPath of worktree.syntheticPaths) {
297
- if (seen.has(syntheticPath))
82
+ if (seen.has(syntheticPath)) {
298
83
  continue;
84
+ }
299
85
  seen.add(syntheticPath);
300
86
  removeSyntheticPath(worktree, syntheticPath);
301
87
  }
302
88
  }
303
- function emptyDiff(index, agent, branch, patchPath, worktreePath, captureError) {
89
+ function emptyDiff(input) {
304
90
  return {
305
- index,
306
- agent,
307
- branch,
91
+ ...input,
308
92
  diffStat: "",
309
93
  filesChanged: 0,
310
94
  insertions: 0,
311
95
  deletions: 0,
312
- patchPath,
313
- ...(worktreePath ? { worktreePath } : {}),
314
- ...(captureError ? { captureError } : {}),
315
96
  };
316
97
  }
317
98
  function parseNumstat(numstat) {
@@ -323,26 +104,48 @@ function parseNumstat(numstat) {
323
104
  let insertions = 0;
324
105
  let deletions = 0;
325
106
  for (const line of lines) {
326
- const [rawInsertions, rawDeletions] = line.split("\t");
327
- if (rawInsertions === undefined || rawDeletions === undefined)
107
+ const columns = line.split("\t");
108
+ if (columns.length < 2) {
328
109
  continue;
110
+ }
111
+ const [rawInsertions, rawDeletions] = columns;
329
112
  filesChanged++;
330
- if (/^\d+$/.test(rawInsertions))
113
+ if (/^\d+$/.test(rawInsertions)) {
331
114
  insertions += parseInt(rawInsertions, 10);
332
- if (/^\d+$/.test(rawDeletions))
115
+ }
116
+ if (/^\d+$/.test(rawDeletions)) {
333
117
  deletions += parseInt(rawDeletions, 10);
118
+ }
334
119
  }
335
120
  return { filesChanged, insertions, deletions };
336
121
  }
337
122
  function captureWorktreeDiff(setup, worktree, agent, patchPath) {
338
123
  removeSyntheticPathsBeforeDiff(worktree);
339
124
  runGitChecked(worktree.path, ["add", "-A"]);
340
- const diffStat = runGitChecked(worktree.path, ["diff", "--cached", "--stat", setup.baseCommit]).trim();
341
- const patch = runGitChecked(worktree.path, ["diff", "--cached", "--binary", "--no-textconv", "--no-ext-diff", setup.baseCommit]);
125
+ const diffStat = runGitChecked(worktree.path, [
126
+ "diff",
127
+ "--cached",
128
+ "--stat",
129
+ setup.baseCommit,
130
+ ]).trim();
131
+ const patch = runGitChecked(worktree.path, [
132
+ "diff",
133
+ "--cached",
134
+ "--binary",
135
+ "--no-textconv",
136
+ "--no-ext-diff",
137
+ setup.baseCommit,
138
+ ]);
342
139
  const numstat = runGitChecked(worktree.path, ["diff", "--cached", "--numstat", setup.baseCommit]);
343
140
  fs.writeFileSync(patchPath, patch, "utf-8");
344
- if (!patch.trim()) {
345
- return emptyDiff(worktree.index, agent, worktree.branch, patchPath, worktree.path);
141
+ if (patch.trim().length === 0) {
142
+ return emptyDiff({
143
+ index: worktree.index,
144
+ agent,
145
+ branch: worktree.branch,
146
+ patchPath,
147
+ worktreePath: worktree.path,
148
+ });
346
149
  }
347
150
  const parsed = parseNumstat(numstat);
348
151
  return {
@@ -380,67 +183,102 @@ function cleanupSingleWorktree(repoCwd, worktree) {
380
183
  }
381
184
  }
382
185
  function hasWorktreeChanges(diff) {
383
- return Boolean(diff.captureError) || diff.filesChanged > 0 || diff.insertions > 0 || diff.deletions > 0 || diff.diffStat.trim().length > 0;
384
- }
385
- function getErrorMessage(error) {
386
- return error instanceof Error ? error.message : String(error);
186
+ return (Boolean(diff.captureError) ||
187
+ diff.filesChanged > 0 ||
188
+ diff.insertions > 0 ||
189
+ diff.deletions > 0 ||
190
+ diff.diffStat.trim().length > 0);
191
+ }
192
+ async function reserveWorktree(plan, index) {
193
+ const { repo, signal } = plan;
194
+ const branch = buildWorktreeBranch(plan.runId, index);
195
+ const worktreePath = buildWorktreePath(plan.runId, index);
196
+ ensureTempRoot();
197
+ const pathExisted = fs.existsSync(worktreePath);
198
+ const branchExisted = (await runSetupGit(repo.toplevel, ["branch", "--list", branch], signal)).trim().length > 0;
199
+ // Reserve only resources this attempt can create, before Git can partially initialize them.
200
+ const agentCwd = repo.cwdRelative.length > 0 ? path.join(worktreePath, repo.cwdRelative) : worktreePath;
201
+ return {
202
+ worktree: { path: worktreePath, agentCwd, branch, index, syntheticPaths: [] },
203
+ reservation: {
204
+ path: pathExisted ? undefined : worktreePath,
205
+ branch: branchExisted ? undefined : branch,
206
+ },
207
+ };
387
208
  }
388
- function markWorktreesForPreservation(setup, reason) {
389
- setup.preserveOnCleanup = true;
390
- setup.preservationReason = setup.preservationReason
391
- ? `${setup.preservationReason}; ${reason}`
392
- : reason;
209
+ async function initializeWorktree(plan, worktree) {
210
+ const { repo, signal } = plan;
211
+ const { path: worktreePath, agentCwd, branch, index } = worktree;
212
+ await runSetupGit(repo.toplevel, ["worktree", "add", worktreePath, "-b", branch, "HEAD"], signal);
213
+ const syntheticPaths = plan.hook
214
+ ? await runWorktreeSetupHook(plan.hook, {
215
+ version: 1,
216
+ repoRoot: repo.toplevel,
217
+ worktreePath,
218
+ agentCwd,
219
+ branch,
220
+ index,
221
+ runId: plan.runId,
222
+ baseCommit: repo.baseCommit,
223
+ agent: plan.agents?.[index],
224
+ }, signal)
225
+ : [];
226
+ return { path: worktreePath, agentCwd, branch, index, syntheticPaths };
227
+ }
228
+ async function rollbackWorktree(repoCwd, entry, signal) {
229
+ const failures = [];
230
+ if (entry.path !== undefined && fs.existsSync(entry.path)) {
231
+ try {
232
+ // An interrupted checkout can leave Git's initializing lock on this newly owned path.
233
+ await runSetupGit(repoCwd, ["worktree", "remove", "--force", "--force", entry.path], signal);
234
+ }
235
+ catch (error) {
236
+ failures.push(`Could not remove worktree '${entry.path}': ${getErrorMessage(error)}`);
237
+ }
238
+ }
239
+ if (entry.branch !== undefined) {
240
+ try {
241
+ const exists = (await runSetupGit(repoCwd, ["branch", "--list", entry.branch], signal)).trim();
242
+ if (exists.length > 0) {
243
+ await runSetupGit(repoCwd, ["branch", "-D", entry.branch], signal);
244
+ }
245
+ }
246
+ catch (error) {
247
+ failures.push(`Could not delete worktree branch '${entry.branch}': ${getErrorMessage(error)}`);
248
+ }
249
+ }
250
+ return failures;
393
251
  }
394
252
  export async function createWorktrees(cwd, runId, count, options) {
395
253
  const signal = options?.signal;
396
254
  const repo = await resolveRepoState(cwd, signal);
397
- const setupHook = resolveWorktreeSetupHook(repo.toplevel, options?.setupHook);
255
+ const hook = resolveWorktreeSetupHook(repo.toplevel, options?.setupHook);
256
+ const plan = { repo, runId, hook, signal, agents: options?.agents };
398
257
  const worktrees = [];
399
- const rollback = [];
258
+ const reservations = [];
400
259
  try {
401
260
  for (let index = 0; index < count; index++) {
402
- const branch = buildWorktreeBranch(runId, index);
403
- const worktreePath = buildWorktreePath(runId, index);
404
- ensureTempRoot();
405
- const pathExisted = fs.existsSync(worktreePath);
406
- const branchExisted = (await runSetupGit(repo.toplevel, ["branch", "--list", branch], signal)).trim().length > 0;
407
- rollback.push({ path: pathExisted ? undefined : worktreePath, branch: branchExisted ? undefined : branch });
408
- await runSetupGit(repo.toplevel, ["worktree", "add", worktreePath, "-b", branch, "HEAD"], signal);
409
- const agentCwd = repo.cwdRelative ? path.join(worktreePath, repo.cwdRelative) : worktreePath;
410
- const syntheticPaths = setupHook ? await runWorktreeSetupHook(setupHook, {
411
- version: 1, repoRoot: repo.toplevel, worktreePath, agentCwd, branch, index, runId,
412
- baseCommit: repo.baseCommit, agent: options?.agents?.[index],
413
- }, signal) : [];
414
- worktrees.push({ path: worktreePath, agentCwd, branch, index, syntheticPaths });
261
+ // Git modifies a shared repository; finish setup before reserving the next worktree.
262
+ // oxlint-disable-next-line no-await-in-loop
263
+ const { worktree, reservation } = await reserveWorktree(plan, index);
264
+ reservations.push(reservation);
265
+ // Register rollback authority before Git can partially initialize this worktree.
266
+ // oxlint-disable-next-line no-await-in-loop
267
+ worktrees.push(await initializeWorktree(plan, worktree));
415
268
  }
416
269
  }
417
270
  catch (error) {
418
- // Rollback still runs after Stop, but its own Git hooks must not hang the owner.
419
- const cleanupSignal = AbortSignal.timeout(setupHook?.timeoutMs ?? DEFAULT_WORKTREE_SETUP_HOOK_TIMEOUT_MS);
271
+ // Rollback remains owned after cancellation and has its own bounded lifetime.
272
+ const cleanupSignal = AbortSignal.timeout(hook?.timeoutMs ?? DEFAULT_WORKTREE_SETUP_HOOK_TIMEOUT_MS);
420
273
  const failures = [];
421
- for (const entry of rollback.reverse()) {
422
- if (entry.path && fs.existsSync(entry.path)) {
423
- try {
424
- // Interrupted checkout can leave Git's "initializing" lock on this new worktree.
425
- await runSetupGit(repo.toplevel, ["worktree", "remove", "--force", "--force", entry.path], cleanupSignal);
426
- }
427
- catch (cleanupError) {
428
- failures.push(`Could not remove worktree '${entry.path}': ${getErrorMessage(cleanupError)}`);
429
- }
430
- }
431
- if (entry.branch) {
432
- try {
433
- const exists = (await runSetupGit(repo.toplevel, ["branch", "--list", entry.branch], cleanupSignal)).trim();
434
- if (exists)
435
- await runSetupGit(repo.toplevel, ["branch", "-D", entry.branch], cleanupSignal);
436
- }
437
- catch (cleanupError) {
438
- failures.push(`Could not delete worktree branch '${entry.branch}': ${getErrorMessage(cleanupError)}`);
439
- }
440
- }
274
+ for (const entry of reservations.reverse()) {
275
+ // Reverse-order resource release must finish before removing the preceding reservation.
276
+ // oxlint-disable-next-line no-await-in-loop
277
+ failures.push(...(await rollbackWorktree(repo.toplevel, entry, cleanupSignal)));
278
+ }
279
+ if (failures.length > 0) {
280
+ throw new WorktreeCleanupError(`${getErrorMessage(error)}\n\nWorktree rollback incomplete:\n${failures.join("\n")}`, { cause: error });
441
281
  }
442
- if (failures.length)
443
- throw new WorktreeCleanupError(`${getErrorMessage(error)}\n\nWorktree rollback incomplete:\n${failures.join("\n")}`);
444
282
  throw error;
445
283
  }
446
284
  return { cwd: repo.toplevel, worktrees, baseCommit: repo.baseCommit };
@@ -455,7 +293,14 @@ export function diffWorktrees(setup, agents, diffsDir) {
455
293
  return setup.worktrees.map((worktree, index) => {
456
294
  const agent = agents[index] ?? `task-${index + 1}`;
457
295
  const patchPath = path.join(diffsDir, `task-${index}-${safePatchAgentName(agent)}.patch`);
458
- return emptyDiff(index, agent, worktree.branch, patchPath, worktree.path, message);
296
+ return emptyDiff({
297
+ index,
298
+ agent,
299
+ branch: worktree.branch,
300
+ patchPath,
301
+ worktreePath: worktree.path,
302
+ captureError: message,
303
+ });
459
304
  });
460
305
  }
461
306
  const diffs = [];
@@ -470,14 +315,22 @@ export function diffWorktrees(setup, agents, diffsDir) {
470
315
  const message = `failed to capture worktree diff for task ${index + 1} (${agent}) at '${worktree.path}': ${getErrorMessage(error)}`;
471
316
  markWorktreesForPreservation(setup, message);
472
317
  writeEmptyPatch(patchPath);
473
- diffs.push(emptyDiff(index, agent, worktree.branch, patchPath, worktree.path, message));
318
+ diffs.push(emptyDiff({
319
+ index,
320
+ agent,
321
+ branch: worktree.branch,
322
+ patchPath,
323
+ worktreePath: worktree.path,
324
+ captureError: message,
325
+ }));
474
326
  }
475
327
  }
476
328
  return diffs;
477
329
  }
478
330
  export function cleanupWorktrees(setup) {
479
- if (setup.preserveOnCleanup)
331
+ if (setup.preserveOnCleanup === true) {
480
332
  return;
333
+ }
481
334
  for (let index = setup.worktrees.length - 1; index >= 0; index--) {
482
335
  cleanupSingleWorktree(setup.cwd, setup.worktrees[index]);
483
336
  }
@@ -488,26 +341,33 @@ export function cleanupWorktrees(setup) {
488
341
  console.error(`Failed to prune worktrees in '${setup.cwd}': ${getErrorMessage(error)}`);
489
342
  }
490
343
  }
344
+ function worktreeRecoveryLines(diff) {
345
+ if (diff.captureError === undefined || diff.captureError.length === 0) {
346
+ return [];
347
+ }
348
+ const lines = [`Diff capture failed: ${diff.captureError}`];
349
+ if (diff.worktreePath !== undefined && diff.worktreePath.length > 0) {
350
+ lines.push(`Preserved worktree: ${diff.worktreePath}`);
351
+ }
352
+ lines.push(`Preserved branch: ${diff.branch}`);
353
+ return lines;
354
+ }
491
355
  export function formatWorktreeDiffSummary(diffs) {
492
356
  const changed = diffs.filter(hasWorktreeChanges);
493
- if (changed.length === 0)
357
+ if (changed.length === 0) {
494
358
  return "";
359
+ }
495
360
  const lines = ["=== Worktree Changes ===", ""];
496
361
  for (const diff of changed) {
497
362
  lines.push(`--- Task ${diff.index + 1} (${diff.agent}): ${diff.filesChanged} files changed, +${diff.insertions} -${diff.deletions} ---`);
498
- if (diff.captureError) {
499
- lines.push(`Diff capture failed: ${diff.captureError}`);
500
- if (diff.worktreePath)
501
- lines.push(`Preserved worktree: ${diff.worktreePath}`);
502
- lines.push(`Preserved branch: ${diff.branch}`);
503
- }
363
+ lines.push(...worktreeRecoveryLines(diff));
504
364
  if (diff.diffStat.trim().length > 0) {
505
365
  lines.push(diff.diffStat);
506
366
  }
507
367
  lines.push("");
508
368
  }
509
- const patchesDir = path.dirname(changed[0].patchPath);
510
- if (changed.some((diff) => !diff.captureError)) {
369
+ const patchesDir = path.dirname(changed[0]?.patchPath ?? "");
370
+ if (changed.some((diff) => (diff.captureError ?? "").length === 0)) {
511
371
  lines.push(`Full patches: ${patchesDir}`);
512
372
  }
513
373
  else {
@@ -516,10 +376,11 @@ export function formatWorktreeDiffSummary(diffs) {
516
376
  return lines.join("\n").trimEnd();
517
377
  }
518
378
  export function formatParallelWorktreeSummary(worktreeSetup, diffsDir, agents) {
519
- if (!worktreeSetup)
379
+ if (!worktreeSetup) {
520
380
  return "";
381
+ }
521
382
  return formatWorktreeDiffSummary(diffWorktrees(worktreeSetup, agents, diffsDir));
522
383
  }
523
384
  export function appendWorktreeSummary(output, worktreeSummary) {
524
- return worktreeSummary ? `${output}\n\n${worktreeSummary}` : output;
385
+ return worktreeSummary.length > 0 ? `${output}\n\n${worktreeSummary}` : output;
525
386
  }