@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,344 +1,409 @@
1
1
  #!/usr/bin/env node
2
- import { execFile } from "node:child_process";
3
- import { copyFileSync, existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs";
2
+ import {
3
+ copyFileSync,
4
+ existsSync,
5
+ mkdirSync,
6
+ mkdtempSync,
7
+ readFileSync,
8
+ rmSync,
9
+ writeFileSync,
10
+ } from "node:fs";
4
11
  import { tmpdir } from "node:os";
5
- import { basename, dirname, join, resolve } from "node:path";
12
+ import { dirname, join, resolve } from "node:path";
6
13
  import process from "node:process";
7
14
  import { setTimeout as delay } from "node:timers/promises";
8
- import { promisify } from "node:util";
9
- import { attachChildProcessLifecycle, isChildTreeAlive, trySignalChildTree } from "../src/shared/post-exit-stdio-guard.ts";
15
+ import { isChildTreeAlive } from "../src/shared/post-exit-stdio-guard.ts";
16
+ import { SmokeProcesses, filesIn, processRef } from "./real-pi-processes.mjs";
10
17
  import { getBrokerSocketPath } from "../src/pi-intercom/broker/paths.ts";
11
18
 
12
- const execFileAsync = promisify(execFile);
13
19
  const DEFAULT_TIMEOUT_MS = 120_000;
14
- const authAgentDir = process.env.PI_REAL_SMOKE_AUTH_AGENT_DIR
15
- ?? (process.env.HOME ? join(process.env.HOME, ".pi", "agent") : undefined);
20
+ const authAgentDir =
21
+ process.env.PI_REAL_SMOKE_AUTH_AGENT_DIR ??
22
+ (process.env.HOME ? join(process.env.HOME, ".pi", "agent") : undefined);
16
23
 
17
24
  function usage() {
18
- console.log(`Usage: node scripts/real-pi-smoke.mjs [--llm] [--llm-full] [--keep-temp] [--timeout-ms <ms>]\n\nRuns an opt-in real Pi package smoke for this checkout. It uses an isolated\ntemporary Pi home, installs the single pi-subagents package with bundled intercom, verifies pi list,\nand loads both extension entries. It does not install pi-fitch-kit, publish anything,\nor create GitHub Actions.\n\nOptions:\n --llm Also run live model-backed list, foreground, and async-completion smoke prompts\n --llm-full Also run broader live parallel, chain, output, and acceptance prompts\n --keep-temp Keep the isolated temporary home for debugging\n --timeout-ms <ms> Per-command timeout in milliseconds (default: ${DEFAULT_TIMEOUT_MS})\n -h, --help Show this help\n\nEnvironment:\n PI_REAL_SMOKE_AUTH_AGENT_DIR Source Pi agent dir for auth.json/models.json during --llm (default: ~/.pi/agent)\n PI_REAL_SMOKE_MODEL Model passed to live --llm smoke prompts, e.g. openai/gpt-6-astra\n PI_REAL_SMOKE_PROVIDER Provider passed to live --llm smoke prompts\n\nExit codes:\n 0 real Pi smoke passed\n 1 install/list/live smoke failed\n 2 invalid arguments`);
25
+ console.log(
26
+ `Usage: node scripts/real-pi-smoke.mjs [--llm] [--llm-full] [--keep-temp] [--timeout-ms <ms>]\n\nRuns an opt-in real Pi package smoke for this checkout. It uses an isolated\ntemporary Pi home, installs the single pi-subagents package with bundled intercom, verifies pi list,\nand loads both extension entries. It does not install pi-fitch-kit, publish anything,\nor create GitHub Actions.\n\nOptions:\n --llm Also run live model-backed list, foreground, and async-completion smoke prompts\n --llm-full Also run broader live parallel, chain, output, and acceptance prompts\n --keep-temp Keep the isolated temporary home for debugging\n --timeout-ms <ms> Per-command timeout in milliseconds (default: ${DEFAULT_TIMEOUT_MS})\n -h, --help Show this help\n\nEnvironment:\n PI_REAL_SMOKE_AUTH_AGENT_DIR Source Pi agent dir for auth.json/models.json during --llm (default: ~/.pi/agent)\n PI_REAL_SMOKE_MODEL Model passed to live --llm smoke prompts, e.g. openai/gpt-6-astra\n PI_REAL_SMOKE_PROVIDER Provider passed to live --llm smoke prompts\n\nExit codes:\n 0 real Pi smoke passed\n 1 install/list/live smoke failed\n 2 invalid arguments`,
27
+ );
19
28
  }
20
29
 
21
30
  function parsePositiveInteger(value, source) {
22
- if (!/^\d+$/.test(value)) throw new Error(`${source} must be a positive integer, got ${value}`);
23
- const parsed = Number(value);
24
- if (!Number.isSafeInteger(parsed) || parsed <= 0) throw new Error(`${source} must be a positive safe integer, got ${value}`);
25
- return parsed;
31
+ if (!/^\d+$/.test(value)) {
32
+ throw new Error(`${source} must be a positive integer, got ${value}`);
33
+ }
34
+ const parsed = Number(value);
35
+ if (!Number.isSafeInteger(parsed) || parsed <= 0) {
36
+ throw new Error(`${source} must be a positive safe integer, got ${value}`);
37
+ }
38
+ return parsed;
26
39
  }
27
40
 
28
41
  function parseArgs(argv) {
29
- const options = { llm: false, llmFull: false, keepTemp: false, timeoutMs: DEFAULT_TIMEOUT_MS };
30
- for (let index = 0; index < argv.length; index += 1) {
31
- const arg = argv[index];
32
- if (arg === "--help" || arg === "-h") {
33
- usage();
34
- process.exit(0);
35
- }
36
- if (arg === "--llm") {
37
- options.llm = true;
38
- continue;
39
- }
40
- if (arg === "--llm-full") {
41
- options.llm = true;
42
- options.llmFull = true;
43
- continue;
44
- }
45
- if (arg === "--keep-temp") {
46
- options.keepTemp = true;
47
- continue;
48
- }
49
- if (arg === "--timeout-ms") {
50
- const value = argv[index + 1];
51
- if (!value) throw new Error("--timeout-ms requires a value");
52
- options.timeoutMs = parsePositiveInteger(value, "--timeout-ms");
53
- index += 1;
54
- continue;
55
- }
56
- if (arg.startsWith("--timeout-ms=")) {
57
- options.timeoutMs = parsePositiveInteger(arg.slice("--timeout-ms=".length), "--timeout-ms");
58
- continue;
59
- }
60
- throw new Error(`Unknown option: ${arg}`);
61
- }
62
- return options;
42
+ const options = { llm: false, llmFull: false, keepTemp: false, timeoutMs: DEFAULT_TIMEOUT_MS };
43
+ for (let index = 0; index < argv.length; index += 1) {
44
+ const arg = argv[index];
45
+ if (arg === "--help" || arg === "-h") {
46
+ usage();
47
+ process.exit(0);
48
+ }
49
+ if (arg === "--llm") {
50
+ options.llm = true;
51
+ continue;
52
+ }
53
+ if (arg === "--llm-full") {
54
+ options.llm = true;
55
+ options.llmFull = true;
56
+ continue;
57
+ }
58
+ if (arg === "--keep-temp") {
59
+ options.keepTemp = true;
60
+ continue;
61
+ }
62
+ if (arg === "--timeout-ms") {
63
+ const value = argv[index + 1];
64
+ if (!value) {
65
+ throw new Error("--timeout-ms requires a value");
66
+ }
67
+ options.timeoutMs = parsePositiveInteger(value, "--timeout-ms");
68
+ index += 1;
69
+ continue;
70
+ }
71
+ if (arg.startsWith("--timeout-ms=")) {
72
+ options.timeoutMs = parsePositiveInteger(arg.slice("--timeout-ms=".length), "--timeout-ms");
73
+ continue;
74
+ }
75
+ throw new Error(`Unknown option: ${arg}`);
76
+ }
77
+ return options;
63
78
  }
64
79
 
65
80
  function copyLiveAuth(agentDir) {
66
- if (!authAgentDir || !existsSync(authAgentDir)) return [];
67
- mkdirSync(agentDir, { recursive: true });
68
- const copied = [];
69
- for (const filename of ["auth.json", "models.json"]) {
70
- const source = join(authAgentDir, filename);
71
- if (!existsSync(source)) continue;
72
- copyFileSync(source, join(agentDir, filename));
73
- copied.push(filename);
74
- }
75
- return copied;
81
+ if (!authAgentDir || !existsSync(authAgentDir)) {
82
+ return [];
83
+ }
84
+ mkdirSync(agentDir, { recursive: true });
85
+ const copied = [];
86
+ for (const filename of ["auth.json", "models.json"]) {
87
+ const source = join(authAgentDir, filename);
88
+ if (!existsSync(source)) {
89
+ continue;
90
+ }
91
+ copyFileSync(source, join(agentDir, filename));
92
+ copied.push(filename);
93
+ }
94
+ return copied;
76
95
  }
77
96
 
78
97
  function isolatedEnv(root, agentDir) {
79
- const home = join(root, "home");
80
- const env = { ...process.env };
81
- for (const key of Object.keys(env)) if (key.startsWith("PI_SUBAGENT_")) delete env[key];
82
- return {
83
- ...env,
84
- HOME: home,
85
- XDG_CONFIG_HOME: join(home, ".config"),
86
- XDG_CACHE_HOME: join(home, ".cache"),
87
- PI_CODING_AGENT_DIR: agentDir,
88
- PI_SUBAGENT_TEMP_ROOT: join(root, "pi-subagents-runtime"),
89
- PI_OFFLINE: "1",
90
- PATH: process.env.PATH ?? "",
91
- };
98
+ const home = join(root, "home");
99
+ const env = { ...process.env };
100
+ for (const key of Object.keys(env)) {
101
+ if (key.startsWith("PI_SUBAGENT_")) {
102
+ delete env[key];
103
+ }
104
+ }
105
+ return {
106
+ ...env,
107
+ HOME: home,
108
+ XDG_CONFIG_HOME: join(home, ".config"),
109
+ XDG_CACHE_HOME: join(home, ".cache"),
110
+ PI_CODING_AGENT_DIR: agentDir,
111
+ PI_SUBAGENT_TEMP_ROOT: join(root, "pi-subagents-runtime"),
112
+ PI_OFFLINE: "1",
113
+ PATH: process.env.PATH ?? "",
114
+ };
92
115
  }
93
116
 
94
- function run(label, command, args, options) {
95
- const { cwd, env, timeoutMs, input, signal, processes } = options;
96
- signal.throwIfAborted();
97
- return new Promise((resolve, reject) => {
98
- let discovery;
99
- let discoveryError;
100
- const finish = async (error, output) => {
101
- clearTimeout(timer);
102
- clearInterval(watcher);
103
- signal.removeEventListener("abort", cancel);
104
- await discovery;
105
- if (error) reject(error);
106
- else resolve(output);
107
- };
108
- const child = execFile(command, args, { cwd, env, encoding: "utf8", detached: true, maxBuffer: 16 * 1024 * 1024 }, (error, stdout, stderr) => {
109
- const output = `${stdout ?? ""}${stderr ?? ""}`;
110
- void finish(error ? new Error(`${label} failed with ${error.code ?? "spawn error"}\nCommand: ${command} ${args.join(" ")}\n${output}`) : undefined, output);
111
- });
112
- attachChildProcessLifecycle(child);
113
- if (child.pid) {
114
- const entry = { child };
115
- processes.set(child.pid, entry);
116
- child.once("close", () => { entry.exited = !isChildTreeAlive(child); });
117
- }
118
- // Remember detached startup children while their parent is still alive, even if startup fails.
119
- const watcher = setInterval(() => {
120
- discovery ??= collectOwnedProcesses(options).catch((error) => {
121
- if (error.message !== discoveryError) console.error(`[real-pi-smoke] process discovery: ${error.message}`);
122
- discoveryError = error.message;
123
- }).finally(() => { discovery = undefined; });
124
- }, 100);
125
- // Reject without killing the parent first: finally owns cleanup of it AND its detached workers.
126
- const timer = setTimeout(() => { void finish(new Error(`${label} timed out after ${timeoutMs}ms\nCommand: ${command} ${args.join(" ")}`)); }, timeoutMs);
127
- const cancel = () => { void finish(signal.reason); };
128
- signal.addEventListener("abort", cancel, { once: true });
129
- child.stdin.on("error", () => {}); // A command may exit without reading its RPC input.
130
- child.stdin.end(input);
131
- });
117
+ function runPi(label, args, options) {
118
+ return options.processes.run(label, "pi", args, options.input);
132
119
  }
133
120
 
134
- function* filesIn(dir) {
135
- if (!existsSync(dir)) return;
136
- for (const entry of readdirSync(dir, { withFileTypes: true })) {
137
- const file = join(dir, entry.name);
138
- if (entry.isDirectory()) yield* filesIn(file);
139
- else if (entry.isFile()) yield file;
140
- }
121
+ async function verifyBundledResources(options) {
122
+ const output = await runPi(
123
+ "pi load bundled resources",
124
+ ["--mode", "rpc", "--no-session", "--offline", "--approve"],
125
+ {
126
+ ...options,
127
+ input: `${JSON.stringify({ id: "commands", type: "get_commands" })}\n`,
128
+ },
129
+ );
130
+ const response = commandResponse(output);
131
+ const commands = registeredCommands(response);
132
+ for (const name of ["intercom", "subagents-doctor", "skill:pi-intercom", "skill:pi-subagents"]) {
133
+ if (!commands.includes(name)) {
134
+ throw new Error(`bundled Pi resources did not register ${name}:\n${output}`);
135
+ }
136
+ }
141
137
  }
142
138
 
143
- function processRef(pid) {
144
- if (!Number.isSafeInteger(pid) || pid <= 1 || pid === process.pid) throw new Error("Invalid smoke-owned process ID");
145
- return { pid, kill: (signal) => process.kill(pid, signal) };
139
+ function commandResponse(output) {
140
+ let response;
141
+ for (const line of output.split(/\r?\n/)) {
142
+ try {
143
+ const parsed = JSON.parse(line);
144
+ if (parsed?.type === "response" && parsed?.id === "commands") {
145
+ response = parsed;
146
+ }
147
+ } catch {
148
+ // Ignore non-protocol stderr lines.
149
+ }
150
+ }
151
+ return response;
146
152
  }
147
153
 
148
- async function collectOwnedProcesses({ root, env, processes }) {
149
- const remember = (pid, broker = false) => {
150
- if (pid === undefined) return;
151
- if (!processes.has(pid)) processes.set(pid, { child: processRef(pid) });
152
- if (broker) processes.get(pid).broker = true;
153
- };
154
- // Only this attempt's private run files, never the user's shared runtime or process argv.
155
- for (const dir of [env.PI_SUBAGENT_TEMP_ROOT, join(env.PI_CODING_AGENT_DIR, "sessions", "subagent-runs")]) {
156
- for (const file of filesIn(dir)) {
157
- if (basename(file) === "status.json" || (basename(dirname(file)) === "contracts" && file.endsWith(".json"))) {
158
- remember(JSON.parse(readFileSync(file, "utf8")).pid);
159
- }
160
- }
161
- }
162
- // The parent records the detached launcher PID; status.json records its runner, not the launcher.
163
- for (const file of filesIn(join(root, "sessions"))) {
164
- if (!file.endsWith(".jsonl")) continue;
165
- const lines = readFileSync(file, "utf8").split("\n").slice(0, -1); // An active append may have a partial final line.
166
- const header = lines[0] ? JSON.parse(lines[0]) : undefined;
167
- for (const line of lines) {
168
- if (!line.trim()) continue;
169
- const entry = JSON.parse(line);
170
- if (entry.type === "custom" && entry.customType === "subagent-run" && entry.data?.ownerSessionId === header?.id) remember(entry.data.pid);
171
- }
172
- }
173
- const brokerPid = join(env.PI_CODING_AGENT_DIR, "intercom", "broker.pid");
174
- if (existsSync(brokerPid)) remember(Number(readFileSync(brokerPid, "utf8").split("\n")[0]), true);
175
- // Startup can precede PID-file publication. Query only direct children of known owned PIDs,
176
- // including new Map entries (grandchildren), before signalling their parents. No argv/global scan.
177
- for (const entry of processes.values()) {
178
- if (!entry.exited) entry.exited = !isChildTreeAlive(entry.child);
179
- if (entry.exited) continue;
180
- const { child } = entry;
181
- try {
182
- const { stdout } = await execFileAsync("pgrep", ["-P", String(child.pid)], { env, encoding: "utf8", timeout: 1000 });
183
- for (const pid of stdout.trim().split(/\s+/).filter(Boolean)) remember(Number(pid));
184
- } catch (error) {
185
- if (error.code !== 1) throw error; // pgrep's exit 1 means no matching children.
186
- }
187
- }
154
+ function registeredCommands(response) {
155
+ return response?.success === true && Array.isArray(response?.data?.commands)
156
+ ? response.data.commands.map((command) => command?.name)
157
+ : [];
188
158
  }
189
159
 
190
- async function stopOwnedProcesses(options) {
191
- let lastError;
192
- while (true) {
193
- let collected = false;
194
- try {
195
- await collectOwnedProcesses(options);
196
- collected = true;
197
- } catch (error) {
198
- // Keep the controller alive and credentials in place if ownership cannot yet be read.
199
- if (error.message !== lastError) console.error(`[real-pi-smoke] waiting for owned-process cleanup: ${error.message}`);
200
- lastError = error.message;
201
- }
202
- const alive = [...options.processes.values()].filter((entry) => {
203
- if (!entry.exited) entry.exited = !isChildTreeAlive(entry.child);
204
- return !entry.exited;
205
- });
206
- if (collected && alive.length === 0) return;
207
- const workers = alive.filter((entry) => !entry.broker);
208
- // Stop the broker last, so exiting workers cannot restart it during cleanup.
209
- for (const entry of workers.length ? workers : alive) {
210
- if (!entry.stoppedAt) {
211
- entry.stoppedAt = Date.now();
212
- trySignalChildTree(entry.child, "SIGTERM");
213
- } else if (Date.now() - entry.stoppedAt >= 3000) trySignalChildTree(entry.child, "SIGKILL");
214
- }
215
- await delay(50);
216
- }
160
+ async function runLivePrompt(label, prompt, options, expectedTool) {
161
+ const args = [
162
+ "--print",
163
+ "--mode",
164
+ "json",
165
+ "--session-dir",
166
+ join(options.root, "sessions"),
167
+ "--approve",
168
+ ];
169
+ if (process.env.PI_REAL_SMOKE_PROVIDER) {
170
+ args.push("--provider", process.env.PI_REAL_SMOKE_PROVIDER);
171
+ }
172
+ if (process.env.PI_REAL_SMOKE_MODEL) {
173
+ args.push(
174
+ "--model",
175
+ process.env.PI_REAL_SMOKE_MODEL,
176
+ "--models",
177
+ process.env.PI_REAL_SMOKE_MODEL,
178
+ );
179
+ }
180
+ args.push(prompt);
181
+ const output = await runPi(label, args, options);
182
+ writeFileSync(join(options.root, `${label.replace(/ /g, "-")}.jsonl`), output);
183
+ const events = output.split("\n").flatMap((line) => {
184
+ try {
185
+ return [JSON.parse(line)];
186
+ } catch {
187
+ return [];
188
+ }
189
+ });
190
+ if (
191
+ !events.some(
192
+ (event) => event.type === "tool_execution_start" && event.toolName === expectedTool,
193
+ )
194
+ ) {
195
+ throw new Error(
196
+ `${label} never invoked ${expectedTool}; a matching final sentence is not execution evidence.`,
197
+ );
198
+ }
199
+ const errors = events.filter((event) => event.type === "tool_execution_end" && event.isError);
200
+ if (errors.length) {
201
+ throw new Error(
202
+ `${label} had ${errors.length} failed tool call(s); inspect its saved wire log.`,
203
+ );
204
+ }
205
+ if (!events.some((event) => event.type === "agent_settled")) {
206
+ throw new Error(`${label} did not reach agent_settled.`);
207
+ }
208
+ return events
209
+ .filter((event) => event.type === "message_end" && event.message?.role === "assistant")
210
+ .flatMap((event) =>
211
+ event.message.content.filter((part) => part.type === "text").map((part) => part.text),
212
+ )
213
+ .join("\n");
217
214
  }
218
215
 
219
- function runPi(label, args, options) {
220
- return run(label, "pi", args, options);
216
+ function* savedAssistantModels(file) {
217
+ for (const line of readFileSync(file, "utf8").split("\n")) {
218
+ if (!line.trim()) {
219
+ continue;
220
+ }
221
+ const entry = JSON.parse(line);
222
+ if (entry.type === "message" && entry.message?.role === "assistant") {
223
+ yield `${entry.message.provider}/${entry.message.model}`;
224
+ }
225
+ }
221
226
  }
222
227
 
223
- async function verifyBundledResources(options) {
224
- const output = await runPi("pi load bundled resources", ["--mode", "rpc", "--no-session", "--offline", "--approve"], {
225
- ...options,
226
- input: `${JSON.stringify({ id: "commands", type: "get_commands" })}\n`,
227
- });
228
- let response;
229
- for (const line of output.split(/\r?\n/)) {
230
- try {
231
- const parsed = JSON.parse(line);
232
- if (parsed?.type === "response" && parsed?.id === "commands") response = parsed;
233
- } catch {
234
- // Ignore non-protocol stderr lines.
235
- }
236
- }
237
- const commands = response?.success === true && Array.isArray(response?.data?.commands)
238
- ? response.data.commands.map((command) => command?.name)
239
- : [];
240
- for (const name of ["intercom", "subagents-doctor", "skill:pi-intercom", "skill:pi-subagents"]) {
241
- if (!commands.includes(name)) throw new Error(`bundled Pi resources did not register ${name}:\n${output}`);
242
- }
228
+ function auditSavedModels(dir, expectedModel) {
229
+ const models = new Set();
230
+ let responses = 0;
231
+ for (const file of filesIn(dir)) {
232
+ if (!file.endsWith(".jsonl")) {
233
+ continue;
234
+ }
235
+ for (const model of savedAssistantModels(file)) {
236
+ responses++;
237
+ models.add(model);
238
+ }
239
+ }
240
+ if (!responses) {
241
+ throw new Error("No saved assistant messages found for model audit.");
242
+ }
243
+ if (expectedModel?.includes("/") && [...models].some((model) => model !== expectedModel)) {
244
+ throw new Error(`Unexpected model in saved parent/child sessions: ${[...models].join(", ")}`);
245
+ }
246
+ console.log(
247
+ `[real-pi-smoke] audited ${responses} saved parent/child responses: ${[...models].join(", ")}`,
248
+ );
243
249
  }
244
250
 
245
- async function runLivePrompt(label, prompt, options, expectedTool) {
246
- const args = ["--print", "--mode", "json", "--session-dir", join(options.root, "sessions"), "--approve"];
247
- if (process.env.PI_REAL_SMOKE_PROVIDER) args.push("--provider", process.env.PI_REAL_SMOKE_PROVIDER);
248
- if (process.env.PI_REAL_SMOKE_MODEL) args.push("--model", process.env.PI_REAL_SMOKE_MODEL, "--models", process.env.PI_REAL_SMOKE_MODEL);
249
- args.push(prompt);
250
- const output = await runPi(label, args, options);
251
- writeFileSync(join(options.root, `${label.replace(/ /g, "-")}.jsonl`), output);
252
- const events = output.split("\n").flatMap((line) => {
253
- try { return [JSON.parse(line)]; } catch { return []; }
254
- });
255
- if (!events.some((event) => event.type === "tool_execution_start" && event.toolName === expectedTool)) {
256
- throw new Error(`${label} never invoked ${expectedTool}; a matching final sentence is not execution evidence.`);
257
- }
258
- const errors = events.filter((event) => event.type === "tool_execution_end" && event.isError);
259
- if (errors.length) throw new Error(`${label} had ${errors.length} failed tool call(s); inspect its saved wire log.`);
260
- if (!events.some((event) => event.type === "agent_settled")) throw new Error(`${label} did not reach agent_settled.`);
261
- return events.filter((event) => event.type === "message_end" && event.message?.role === "assistant")
262
- .flatMap((event) => event.message.content.filter((part) => part.type === "text").map((part) => part.text)).join("\n");
251
+ function requireOutput(label, output, pattern) {
252
+ if (!pattern.test(output)) {
253
+ throw new Error(`${label} did not include expected evidence ${pattern}.\nOutput:\n${output}`);
254
+ }
255
+ const compact = output.trim().split(/\r?\n/).slice(-8).join("\n");
256
+ console.log(`[real-pi-smoke] ${label} output evidence:\n${compact}`);
263
257
  }
264
258
 
265
- function auditSavedModels(dir, expectedModel) {
266
- const models = new Set();
267
- let responses = 0;
268
- const visit = (directory) => {
269
- for (const entry of readdirSync(directory, { withFileTypes: true })) {
270
- const file = join(directory, entry.name);
271
- if (entry.isDirectory()) visit(file);
272
- else if (entry.name.endsWith(".jsonl")) {
273
- for (const line of readFileSync(file, "utf8").split("\n")) {
274
- if (!line.trim()) continue;
275
- const entry = JSON.parse(line);
276
- if (entry.type !== "message" || entry.message?.role !== "assistant") continue;
277
- responses++;
278
- models.add(`${entry.message.provider}/${entry.message.model}`);
279
- }
280
- }
281
- }
282
- };
283
- visit(dir);
284
- if (!responses) throw new Error("No saved assistant messages found for model audit.");
285
- if (expectedModel?.includes("/") && [...models].some((model) => model !== expectedModel)) {
286
- throw new Error(`Unexpected model in saved parent/child sessions: ${[...models].join(", ")}`);
287
- }
288
- console.log(`[real-pi-smoke] audited ${responses} saved parent/child responses: ${[...models].join(", ")}`);
259
+ async function waitForAsyncCompletion(runId, pattern, { env, timeoutMs, signal }) {
260
+ const dir = join(env.PI_SUBAGENT_TEMP_ROOT, "async-subagent-runs", runId);
261
+ const deadline = Date.now() + timeoutMs;
262
+ let lastState = "missing";
263
+ let lastOutput = "";
264
+ while (Date.now() < deadline) {
265
+ signal.throwIfAborted();
266
+ const statusPath = join(dir, "status.json");
267
+ const outputPath = join(dir, "output-0.log");
268
+ if (existsSync(outputPath)) {
269
+ lastOutput = readFileSync(outputPath, "utf8");
270
+ }
271
+ if (existsSync(statusPath)) {
272
+ const status = JSON.parse(readFileSync(statusPath, "utf8"));
273
+ lastState = String(status.state ?? "unknown");
274
+ if (asyncProcessComplete(status)) {
275
+ requireOutput(`async run ${runId} completed`, lastOutput, pattern);
276
+ return;
277
+ }
278
+ if (lastState === "failed" || lastState === "paused") {
279
+ throw new Error(`async run ${runId} ended ${lastState}.\nOutput:\n${lastOutput}`);
280
+ }
281
+ }
282
+ // Poll only after reading status and process liveness; the runner may still write final artifacts.
283
+ // oxlint-disable-next-line no-await-in-loop
284
+ await delay(500, undefined, { signal });
285
+ }
286
+ throw new Error(
287
+ `async run ${runId} did not complete after ${timeoutMs}ms (last state: ${lastState}).\nOutput:\n${lastOutput}`,
288
+ );
289
289
  }
290
290
 
291
- function requireOutput(label, output, pattern) {
292
- if (!pattern.test(output)) {
293
- throw new Error(`${label} did not include expected evidence ${pattern}.\nOutput:\n${output}`);
294
- }
295
- const compact = output.trim().split(/\r?\n/).slice(-8).join("\n");
296
- console.log(`[real-pi-smoke] ${label} output evidence:\n${compact}`);
291
+ function asyncProcessComplete(status) {
292
+ return status.state === "complete" && status.pid && !isChildTreeAlive(processRef(status.pid));
297
293
  }
298
294
 
299
- async function waitForAsyncCompletion(runId, pattern, { env, timeoutMs, signal }) {
300
- const dir = join(env.PI_SUBAGENT_TEMP_ROOT, "async-subagent-runs", runId);
301
- const deadline = Date.now() + timeoutMs;
302
- let lastState = "missing";
303
- let lastOutput = "";
304
- while (Date.now() < deadline) {
305
- signal.throwIfAborted();
306
- const statusPath = join(dir, "status.json");
307
- const outputPath = join(dir, "output-0.log");
308
- if (existsSync(outputPath)) lastOutput = readFileSync(outputPath, "utf8");
309
- if (existsSync(statusPath)) {
310
- const status = JSON.parse(readFileSync(statusPath, "utf8"));
311
- lastState = String(status.state ?? "unknown");
312
- if (lastState === "complete" && status.pid && !isChildTreeAlive(processRef(status.pid))) {
313
- if (!pattern.test(lastOutput)) throw new Error(`async run ${runId} completed without ${pattern}.\nOutput:\n${lastOutput}`);
314
- const compact = lastOutput.trim().split(/\r?\n/).slice(-8).join("\n");
315
- console.log(`[real-pi-smoke] async run ${runId} completed:\n${compact}`);
316
- return;
317
- }
318
- if (lastState === "failed" || lastState === "paused") throw new Error(`async run ${runId} ended ${lastState}.\nOutput:\n${lastOutput}`);
319
- }
320
- await delay(500, undefined, { signal });
321
- }
322
- throw new Error(`async run ${runId} did not complete after ${timeoutMs}ms (last state: ${lastState}).\nOutput:\n${lastOutput}`);
295
+ async function runLiveSmoke(options, runOptions, agentDir) {
296
+ const { root } = runOptions;
297
+ const copiedAuthFiles = copyLiveAuth(agentDir);
298
+ if (copiedAuthFiles.length > 0) {
299
+ console.log(
300
+ `[real-pi-smoke] copied ${copiedAuthFiles.join(" and ")} into isolated Pi agent dir for live provider auth`,
301
+ );
302
+ }
303
+ const childModelInstruction = process.env.PI_REAL_SMOKE_MODEL
304
+ ? ` Pass model override '${process.env.PI_REAL_SMOKE_MODEL}' to every subagent run.`
305
+ : "";
306
+ await runBasicLiveSmoke(runOptions, childModelInstruction);
307
+ if (options.llmFull) {
308
+ await runFullLiveSmoke(runOptions, childModelInstruction);
309
+ }
310
+ auditSavedModels(join(root, "sessions"), process.env.PI_REAL_SMOKE_MODEL);
323
311
  }
324
312
 
325
- async function main() {
326
- let options;
327
- try {
328
- options = parseArgs(process.argv.slice(2));
329
- } catch (error) {
330
- console.error(`[real-pi-smoke] ${error instanceof Error ? error.message : String(error)}`);
331
- usage();
332
- process.exit(2);
333
- }
313
+ async function runBasicLiveSmoke(runOptions, childModelInstruction) {
314
+ const intercomPrompt =
315
+ "Call the intercom tool with action status. Reply exactly with 'real-pi-smoke intercom ok' if the tool output includes 'Connected: Yes'.";
316
+ const listPrompt =
317
+ "Use the agent_runs tool with action profiles. Reply exactly with 'real-pi-smoke list ok' if reviewer, scout, oracle, and watcher are available.";
318
+ const foregroundPrompt = `Use the delegate tool to run real-smoke with task 'Reply exactly: real-pi-smoke foreground ok', async false and output false.${childModelInstruction} If the tool returns an output artifact path instead of inline output, read that file. Then reply exactly 'real-pi-smoke foreground ok' only if the child result contains it.`;
319
+ const asyncPrompt = `Use the delegate tool to run real-smoke with task 'Reply exactly: real-pi-smoke async ok', output false.${childModelInstruction} Set async true so it launches in the background. Do not call status and do not wait for completion. Reply with 'real-pi-smoke async launched ok' and quote the exact tool result line beginning 'Async:' including the run id.`;
320
+ requireOutput(
321
+ "real Pi intercom prompt",
322
+ await runLivePrompt("real Pi intercom prompt", intercomPrompt, runOptions, "intercom"),
323
+ /real-pi-smoke intercom ok/,
324
+ );
325
+ requireOutput(
326
+ "real Pi subagent list prompt",
327
+ await runLivePrompt("real Pi subagent list prompt", listPrompt, runOptions, "agent_runs"),
328
+ /real-pi-smoke list ok/,
329
+ );
330
+ requireOutput(
331
+ "real Pi foreground subagent prompt",
332
+ await runLivePrompt(
333
+ "real Pi foreground subagent prompt",
334
+ foregroundPrompt,
335
+ runOptions,
336
+ "delegate",
337
+ ),
338
+ /real-pi-smoke foreground ok/,
339
+ );
340
+ const asyncOutput = await runLivePrompt(
341
+ "real Pi async subagent prompt",
342
+ asyncPrompt,
343
+ runOptions,
344
+ "delegate",
345
+ );
346
+ requireOutput(
347
+ "real Pi async subagent prompt",
348
+ asyncOutput,
349
+ /real-pi-smoke async (?:launched )?ok/i,
350
+ );
351
+ const asyncRunId =
352
+ asyncOutput.match(/Async(?: parallel)?:\s+(?:\S+|\[[^\]]+\])\s+\[([0-9a-f-]{36})\]/i)?.[1] ??
353
+ asyncOutput.match(/\[([0-9a-f-]{36})\]/i)?.[1] ??
354
+ asyncOutput.match(/\b([0-9a-f]{8}-[0-9a-f-]{27})\b/i)?.[1];
355
+ if (!asyncRunId) {
356
+ throw new Error(`Could not parse async run id from output:\n${asyncOutput}`);
357
+ }
358
+ await waitForAsyncCompletion(asyncRunId, /^real-pi-smoke async ok$/m, runOptions);
359
+ }
360
+
361
+ async function runFullLiveSmoke(runOptions, childModelInstruction) {
362
+ const outputPath = join(runOptions.root, "live-output-smoke.txt");
363
+ const parallelPrompt = `Use the subagent tool in parallel mode with two delegate tasks and async false. Task 1 replies exactly 'real-pi-smoke parallel A ok'. Task 2 replies exactly 'real-pi-smoke parallel B ok'. Set output false and progress false for both.${childModelInstruction} Reply exactly 'real-pi-smoke parallel ok' only if both child outputs are present.`;
364
+ const chainPrompt = `Use the subagent tool chain mode with two delegate steps and async false.${childModelInstruction} Step 1 task: 'Reply exactly: real-pi-smoke chain step1 ok'. Step 2 task: 'Previous output is {previous}. Reply exactly: real-pi-smoke chain step2 ok'. Reply exactly 'real-pi-smoke chain ok' only if step 2 ran after step 1.`;
365
+ const outputPrompt = `Use the subagent tool to run delegate with task 'Write exactly real-pi-smoke output ok plus newline to the requested output path, then reply exactly wrote output smoke'. Set async false, output to ${JSON.stringify(outputPath)}, and outputMode to file-only.${childModelInstruction} Reply exactly 'real-pi-smoke output ok' only after the tool returns.`;
366
+ const acceptancePrompt = `Use the subagent tool to run delegate with task 'Final answer exactly: real-pi-smoke acceptance ok evidence=manual-notes'. Set async false. Include acceptance criteria requiring the final answer to contain real-pi-smoke acceptance ok and evidence manual-notes, with maxFinalizationTurns 2.${childModelInstruction} Reply exactly 'real-pi-smoke acceptance ok' only if the child completed.`;
367
+ requireOutput(
368
+ "real Pi parallel subagent prompt",
369
+ await runLivePrompt("real Pi parallel subagent prompt", parallelPrompt, runOptions, "subagent"),
370
+ /real-pi-smoke parallel ok/,
371
+ );
372
+ requireOutput(
373
+ "real Pi chain subagent prompt",
374
+ await runLivePrompt("real Pi chain subagent prompt", chainPrompt, runOptions, "subagent"),
375
+ /real-pi-smoke chain ok/,
376
+ );
377
+ requireOutput(
378
+ "real Pi output subagent prompt",
379
+ await runLivePrompt("real Pi output subagent prompt", outputPrompt, runOptions, "subagent"),
380
+ /real-pi-smoke output ok/,
381
+ );
382
+ if (
383
+ !existsSync(outputPath) ||
384
+ !/real-pi-smoke output ok/.test(readFileSync(outputPath, "utf8"))
385
+ ) {
386
+ throw new Error(`output smoke file missing expected content: ${outputPath}`);
387
+ }
388
+ requireOutput(
389
+ "real Pi acceptance subagent prompt",
390
+ await runLivePrompt(
391
+ "real Pi acceptance subagent prompt",
392
+ acceptancePrompt,
393
+ runOptions,
394
+ "subagent",
395
+ ),
396
+ /real-pi-smoke acceptance ok/,
397
+ );
398
+ }
334
399
 
335
- const repoRoot = resolve(process.cwd());
336
- const root = mkdtempSync(join(tmpdir(), "pi-subagents-real-pi-smoke-"));
337
- const agentDir = join(root, "pi-agent");
338
- const projectRoot = join(root, "project");
339
- const projectAgentsDir = join(projectRoot, ".pi", "agents");
340
- mkdirSync(projectAgentsDir, { recursive: true });
341
- writeFileSync(join(projectAgentsDir, "real-smoke.md"), `---
400
+ function createProject(root) {
401
+ const projectRoot = join(root, "project");
402
+ const projectAgentsDir = join(projectRoot, ".pi", "agents");
403
+ mkdirSync(projectAgentsDir, { recursive: true });
404
+ writeFileSync(
405
+ join(projectAgentsDir, "real-smoke.md"),
406
+ `---
342
407
  name: real-smoke
343
408
  description: Isolated live smoke agent
344
409
  systemPromptMode: replace
@@ -349,67 +414,83 @@ extensions:
349
414
  ---
350
415
 
351
416
  Follow the task exactly and return its requested text without using tools.
352
- `, "utf-8");
353
- const env = isolatedEnv(root, agentDir);
354
- const cancellation = new AbortController();
355
- const cancel = (signal) => cancellation.abort(new Error(`Cancelled by ${signal}`));
356
- for (const signal of ["SIGINT", "SIGTERM", "SIGHUP"]) process.on(signal, cancel);
357
- const runOptions = { cwd: projectRoot, env, timeoutMs: options.timeoutMs, root, signal: cancellation.signal, processes: new Map() };
417
+ `,
418
+ "utf-8",
419
+ );
420
+ return projectRoot;
421
+ }
422
+
423
+ async function main() {
424
+ let options;
425
+ try {
426
+ options = parseArgs(process.argv.slice(2));
427
+ } catch (error) {
428
+ console.error(`[real-pi-smoke] ${error instanceof Error ? error.message : String(error)}`);
429
+ usage();
430
+ process.exit(2);
431
+ }
432
+
433
+ const repoRoot = resolve(process.cwd());
434
+ const root = mkdtempSync(join(tmpdir(), "pi-subagents-real-pi-smoke-"));
435
+ const agentDir = join(root, "pi-agent");
436
+ const projectRoot = createProject(root);
437
+ const env = isolatedEnv(root, agentDir);
438
+ const cancellation = new AbortController();
439
+ const cancel = (signal) => cancellation.abort(new Error(`Cancelled by ${signal}`));
440
+ for (const signal of ["SIGINT", "SIGTERM", "SIGHUP"]) {
441
+ process.on(signal, cancel);
442
+ }
443
+ const runOptions = {
444
+ cwd: projectRoot,
445
+ env,
446
+ timeoutMs: options.timeoutMs,
447
+ root,
448
+ signal: cancellation.signal,
449
+ };
358
450
 
359
- try {
360
- await runPi("pi install pi-subagents", ["install", repoRoot, "--approve"], runOptions);
361
- const list = await runPi("pi list", ["list", "--approve"], runOptions);
362
- if (!list.includes(repoRoot)) throw new Error(`pi list did not include ${repoRoot}:\n${list}`);
363
- await verifyBundledResources(runOptions);
364
- console.log(`[real-pi-smoke] active Pi ${(await runPi("pi version", ["--version"], runOptions)).trim()}`);
451
+ runOptions.processes = new SmokeProcesses(runOptions);
365
452
 
366
- if (options.llm) {
367
- const copiedAuthFiles = copyLiveAuth(agentDir);
368
- if (copiedAuthFiles.length > 0) console.log(`[real-pi-smoke] copied ${copiedAuthFiles.join(" and ")} into isolated Pi agent dir for live provider auth`);
369
- const childModelInstruction = process.env.PI_REAL_SMOKE_MODEL ? ` Pass model override '${process.env.PI_REAL_SMOKE_MODEL}' to every subagent run.` : "";
370
- const intercomPrompt = "Call the intercom tool with action status. Reply exactly with 'real-pi-smoke intercom ok' if the tool output includes 'Connected: Yes'.";
371
- const listPrompt = "Use the agent_runs tool with action profiles. Reply exactly with 'real-pi-smoke list ok' if reviewer, scout, oracle, and watcher are available.";
372
- const foregroundPrompt = `Use the delegate tool to run real-smoke with task 'Reply exactly: real-pi-smoke foreground ok', async false and output false.${childModelInstruction} If the tool returns an output artifact path instead of inline output, read that file. Then reply exactly 'real-pi-smoke foreground ok' only if the child result contains it.`;
373
- const asyncPrompt = `Use the delegate tool to run real-smoke with task 'Reply exactly: real-pi-smoke async ok', output false.${childModelInstruction} Set async true so it launches in the background. Do not call status and do not wait for completion. Reply with 'real-pi-smoke async launched ok' and quote the exact tool result line beginning 'Async:' including the run id.`;
374
- requireOutput("real Pi intercom prompt", await runLivePrompt("real Pi intercom prompt", intercomPrompt, runOptions, "intercom"), /real-pi-smoke intercom ok/);
375
- requireOutput("real Pi subagent list prompt", await runLivePrompt("real Pi subagent list prompt", listPrompt, runOptions, "agent_runs"), /real-pi-smoke list ok/);
376
- requireOutput("real Pi foreground subagent prompt", await runLivePrompt("real Pi foreground subagent prompt", foregroundPrompt, runOptions, "delegate"), /real-pi-smoke foreground ok/);
377
- const asyncOutput = await runLivePrompt("real Pi async subagent prompt", asyncPrompt, runOptions, "delegate");
378
- requireOutput("real Pi async subagent prompt", asyncOutput, /real-pi-smoke async (?:launched )?ok/i);
379
- const asyncRunId = asyncOutput.match(/Async(?: parallel)?:\s+(?:\S+|\[[^\]]+\])\s+\[([0-9a-f-]{36})\]/i)?.[1]
380
- ?? asyncOutput.match(/\[([0-9a-f-]{36})\]/i)?.[1]
381
- ?? asyncOutput.match(/\b([0-9a-f]{8}-[0-9a-f-]{27})\b/i)?.[1];
382
- if (!asyncRunId) throw new Error(`Could not parse async run id from output:\n${asyncOutput}`);
383
- await waitForAsyncCompletion(asyncRunId, /^real-pi-smoke async ok$/m, runOptions);
453
+ try {
454
+ await runPi("pi install pi-subagents", ["install", repoRoot, "--approve"], runOptions);
455
+ const list = await runPi("pi list", ["list", "--approve"], runOptions);
456
+ if (!list.includes(repoRoot)) {
457
+ throw new Error(`pi list did not include ${repoRoot}:\n${list}`);
458
+ }
459
+ await verifyBundledResources(runOptions);
460
+ console.log(
461
+ `[real-pi-smoke] active Pi ${(await runPi("pi version", ["--version"], runOptions)).trim()}`,
462
+ );
384
463
 
385
- if (options.llmFull) {
386
- const outputPath = join(root, "live-output-smoke.txt");
387
- const parallelPrompt = `Use the subagent tool in parallel mode with two delegate tasks and async false. Task 1 replies exactly 'real-pi-smoke parallel A ok'. Task 2 replies exactly 'real-pi-smoke parallel B ok'. Set output false and progress false for both.${childModelInstruction} Reply exactly 'real-pi-smoke parallel ok' only if both child outputs are present.`;
388
- const chainPrompt = `Use the subagent tool chain mode with two delegate steps and async false.${childModelInstruction} Step 1 task: 'Reply exactly: real-pi-smoke chain step1 ok'. Step 2 task: 'Previous output is {previous}. Reply exactly: real-pi-smoke chain step2 ok'. Reply exactly 'real-pi-smoke chain ok' only if step 2 ran after step 1.`;
389
- const outputPrompt = `Use the subagent tool to run delegate with task 'Write exactly real-pi-smoke output ok plus newline to the requested output path, then reply exactly wrote output smoke'. Set async false, output to ${JSON.stringify(outputPath)}, and outputMode to file-only.${childModelInstruction} Reply exactly 'real-pi-smoke output ok' only after the tool returns.`;
390
- const acceptancePrompt = `Use the subagent tool to run delegate with task 'Final answer exactly: real-pi-smoke acceptance ok evidence=manual-notes'. Set async false. Include acceptance criteria requiring the final answer to contain real-pi-smoke acceptance ok and evidence manual-notes, with maxFinalizationTurns 2.${childModelInstruction} Reply exactly 'real-pi-smoke acceptance ok' only if the child completed.`;
391
- requireOutput("real Pi parallel subagent prompt", await runLivePrompt("real Pi parallel subagent prompt", parallelPrompt, runOptions, "subagent"), /real-pi-smoke parallel ok/);
392
- requireOutput("real Pi chain subagent prompt", await runLivePrompt("real Pi chain subagent prompt", chainPrompt, runOptions, "subagent"), /real-pi-smoke chain ok/);
393
- requireOutput("real Pi output subagent prompt", await runLivePrompt("real Pi output subagent prompt", outputPrompt, runOptions, "subagent"), /real-pi-smoke output ok/);
394
- if (!existsSync(outputPath) || !/real-pi-smoke output ok/.test(readFileSync(outputPath, "utf8"))) throw new Error(`output smoke file missing expected content: ${outputPath}`);
395
- requireOutput("real Pi acceptance subagent prompt", await runLivePrompt("real Pi acceptance subagent prompt", acceptancePrompt, runOptions, "subagent"), /real-pi-smoke acceptance ok/);
396
- }
397
- auditSavedModels(join(root, "sessions"), process.env.PI_REAL_SMOKE_MODEL);
398
- }
464
+ if (options.llm) {
465
+ await runLiveSmoke(options, runOptions, agentDir);
466
+ }
399
467
 
400
- console.log(`[real-pi-smoke] installed the single pi-subagents package, loaded bundled intercom, and verified pi list in ${agentDir}`);
401
- if (!options.llm) console.log("[real-pi-smoke] live model subagent prompts skipped; pass --llm to exercise foreground/async paths.");
402
- } finally {
403
- await stopOwnedProcesses(runOptions);
404
- rmSync(dirname(getBrokerSocketPath(agentDir)), { recursive: true, force: true });
405
- for (const name of ["auth.json", "models.json"]) rmSync(join(agentDir, name), { force: true });
406
- if (options.keepTemp) console.log(`[real-pi-smoke] kept temp root ${root}`);
407
- else rmSync(root, { recursive: true, force: true });
408
- for (const signal of ["SIGINT", "SIGTERM", "SIGHUP"]) process.off(signal, cancel);
409
- }
468
+ console.log(
469
+ `[real-pi-smoke] installed the single pi-subagents package, loaded bundled intercom, and verified pi list in ${agentDir}`,
470
+ );
471
+ if (!options.llm) {
472
+ console.log(
473
+ "[real-pi-smoke] live model subagent prompts skipped; pass --llm to exercise foreground/async paths.",
474
+ );
475
+ }
476
+ } finally {
477
+ await runOptions.processes.stop();
478
+ rmSync(dirname(getBrokerSocketPath(agentDir)), { recursive: true, force: true });
479
+ for (const name of ["auth.json", "models.json"]) {
480
+ rmSync(join(agentDir, name), { force: true });
481
+ }
482
+ if (options.keepTemp) {
483
+ console.log(`[real-pi-smoke] kept temp root ${root}`);
484
+ } else {
485
+ rmSync(root, { recursive: true, force: true });
486
+ }
487
+ for (const signal of ["SIGINT", "SIGTERM", "SIGHUP"]) {
488
+ process.off(signal, cancel);
489
+ }
490
+ }
410
491
  }
411
492
 
412
493
  main().catch((error) => {
413
- console.error(`[real-pi-smoke] ${error instanceof Error ? error.message : String(error)}`);
414
- process.exitCode = 1;
494
+ console.error(`[real-pi-smoke] ${error instanceof Error ? error.message : String(error)}`);
495
+ process.exitCode = 1;
415
496
  });