@fitchmultz/pi-subagents 0.44.6 → 0.45.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (947) hide show
  1. package/CHANGELOG.md +265 -7
  2. package/LICENSE +1 -0
  3. package/README.md +58 -1483
  4. package/agents/context-builder.md +19 -1
  5. package/agents/debugger.md +10 -3
  6. package/agents/delegate.md +1 -0
  7. package/agents/fixer.md +4 -1
  8. package/agents/oracle.md +13 -2
  9. package/agents/planner.md +14 -3
  10. package/agents/researcher.md +11 -2
  11. package/agents/reviewer-claude.md +11 -2
  12. package/agents/reviewer-gpt.md +12 -2
  13. package/agents/reviewer-ponytail.md +11 -1
  14. package/agents/reviewer-security.md +13 -2
  15. package/agents/reviewer.md +12 -3
  16. package/agents/scout.md +12 -1
  17. package/agents/ui-designer.md +10 -3
  18. package/agents/watcher.md +1 -0
  19. package/agents/worker.md +8 -2
  20. package/agents/writer.md +6 -3
  21. package/dist/agents/agent-defaults.js +9 -0
  22. package/dist/agents/agent-definition.js +196 -0
  23. package/dist/agents/agent-management.js +64 -905
  24. package/dist/agents/agent-scope.js +4 -2
  25. package/dist/agents/agent-selection.js +10 -5
  26. package/dist/agents/agent-serializer.js +55 -67
  27. package/dist/agents/agents.js +75 -716
  28. package/dist/agents/builtin-overrides.js +218 -0
  29. package/dist/agents/chain-serializer.js +3 -367
  30. package/dist/agents/config-values.js +52 -0
  31. package/dist/agents/discovery-paths.js +91 -0
  32. package/dist/agents/frontmatter.js +15 -5
  33. package/dist/agents/identity.js +25 -8
  34. package/dist/agents/json-chain.js +254 -0
  35. package/dist/agents/management-config.js +332 -0
  36. package/dist/agents/management-format.js +231 -0
  37. package/dist/agents/management-persistence.js +287 -0
  38. package/dist/agents/management-targets.js +136 -0
  39. package/dist/agents/management-warnings.js +81 -0
  40. package/dist/agents/markdown-chain.js +210 -0
  41. package/dist/agents/package-agents.js +154 -0
  42. package/dist/agents/skill-files.js +157 -0
  43. package/dist/agents/skill-search-paths.js +246 -0
  44. package/dist/agents/skill-types.js +1 -0
  45. package/dist/agents/skills.js +54 -499
  46. package/dist/extension/acceptance-schema.js +55 -0
  47. package/dist/extension/build-info.js +1 -1
  48. package/dist/extension/chain-schema.js +196 -0
  49. package/dist/extension/child-runtime.js +237 -0
  50. package/dist/extension/compact-tools.js +122 -51
  51. package/dist/extension/config-schema.js +29 -0
  52. package/dist/extension/config.js +27 -11
  53. package/dist/extension/control-notice-schema.js +37 -0
  54. package/dist/extension/control-notices.js +13 -6
  55. package/dist/extension/delegation-bridges.js +43 -0
  56. package/dist/extension/doctor.js +48 -25
  57. package/dist/extension/everyday-schemas.js +207 -0
  58. package/dist/extension/fanout-child.js +18 -319
  59. package/dist/extension/index.js +8 -563
  60. package/dist/extension/message-renderers.js +225 -0
  61. package/dist/extension/nested-control-inbox.js +154 -0
  62. package/dist/extension/parent-runtime.js +339 -0
  63. package/dist/extension/primary-tool.js +69 -0
  64. package/dist/extension/result-snapshot.js +22 -0
  65. package/dist/extension/runtime-reload.js +62 -0
  66. package/dist/extension/runtime-storage.js +43 -0
  67. package/dist/extension/schema-overrides.js +75 -0
  68. package/dist/extension/schemas.js +265 -336
  69. package/dist/extension/tool-input.js +27 -12
  70. package/dist/extension/tool-result.js +19 -4
  71. package/dist/history/answer-texts.js +57 -0
  72. package/dist/history/canonical-result.js +76 -43
  73. package/dist/history/canonical-selection.js +40 -0
  74. package/dist/history/database-generation.js +82 -0
  75. package/dist/history/database.js +57 -33
  76. package/dist/history/entry-ingestion.js +61 -0
  77. package/dist/history/index.js +242 -97
  78. package/dist/history/ingest.js +168 -331
  79. package/dist/history/output-digests.js +40 -0
  80. package/dist/history/preview.js +210 -0
  81. package/dist/history/prune.js +33 -0
  82. package/dist/history/queries.js +60 -349
  83. package/dist/history/query-scope.js +190 -0
  84. package/dist/history/rows.js +77 -0
  85. package/dist/history/run-projection.js +137 -0
  86. package/dist/history/run-queries.js +153 -0
  87. package/dist/history/schema.js +31 -0
  88. package/dist/history/search-queries.js +163 -0
  89. package/dist/history/selected-record.js +108 -0
  90. package/dist/history/source-file.js +45 -0
  91. package/dist/history/source-watches.js +141 -0
  92. package/dist/history/store.js +164 -153
  93. package/dist/history/text-chunks.js +169 -0
  94. package/dist/history/text.js +35 -0
  95. package/dist/history/transcript-queries.js +177 -0
  96. package/dist/history/types.js +5 -1
  97. package/dist/history/values.js +36 -0
  98. package/dist/history/wire-inputs.js +122 -0
  99. package/dist/history/wire-models.js +38 -0
  100. package/dist/history/worker-runtime.js +441 -0
  101. package/dist/history/worker.js +66 -462
  102. package/dist/intercom/intercom-bridge.js +48 -20
  103. package/dist/intercom/live-intercom.js +80 -23
  104. package/dist/intercom/nested-result-tree.js +163 -0
  105. package/dist/intercom/result-delivery.js +40 -0
  106. package/dist/intercom/result-intercom.js +178 -261
  107. package/dist/pi-intercom/agent-dir.js +7 -3
  108. package/dist/pi-intercom/async.js +27 -0
  109. package/dist/pi-intercom/bridge-ask.js +57 -0
  110. package/dist/pi-intercom/bridge-config.js +79 -0
  111. package/dist/pi-intercom/bridge-http.js +86 -0
  112. package/dist/pi-intercom/bridge-protocol.js +106 -0
  113. package/dist/pi-intercom/bridge-routes.js +64 -0
  114. package/dist/pi-intercom/bridge-session.js +416 -0
  115. package/dist/pi-intercom/bridge.js +182 -603
  116. package/dist/pi-intercom/broker/broker.js +236 -244
  117. package/dist/pi-intercom/broker/client.js +189 -304
  118. package/dist/pi-intercom/broker/connection.js +165 -0
  119. package/dist/pi-intercom/broker/framing.js +5 -3
  120. package/dist/pi-intercom/broker/paths.js +4 -1
  121. package/dist/pi-intercom/broker/pid.js +53 -25
  122. package/dist/pi-intercom/broker/snapshot-reader.js +78 -0
  123. package/dist/pi-intercom/broker/snapshots.js +188 -0
  124. package/dist/pi-intercom/broker/spawn.js +36 -25
  125. package/dist/pi-intercom/config.js +85 -71
  126. package/dist/pi-intercom/connection.js +297 -0
  127. package/dist/pi-intercom/identity.js +58 -0
  128. package/dist/pi-intercom/inbound-delivery.js +356 -0
  129. package/dist/pi-intercom/inbound-journal.js +303 -0
  130. package/dist/pi-intercom/inbound-record.js +113 -0
  131. package/dist/pi-intercom/inbound.js +179 -0
  132. package/dist/pi-intercom/index.js +79 -2933
  133. package/dist/pi-intercom/inspection.js +62 -0
  134. package/dist/pi-intercom/interview.js +236 -0
  135. package/dist/pi-intercom/lifecycle.js +168 -0
  136. package/dist/pi-intercom/message-format.js +69 -0
  137. package/dist/pi-intercom/outbound.js +304 -0
  138. package/dist/pi-intercom/peer-awareness.js +66 -0
  139. package/dist/pi-intercom/reply-tracker.js +62 -43
  140. package/dist/pi-intercom/reply-wait.js +201 -0
  141. package/dist/pi-intercom/runtime-types.js +3 -0
  142. package/dist/pi-intercom/session-events.js +180 -0
  143. package/dist/pi-intercom/session-targets.js +42 -34
  144. package/dist/pi-intercom/subagent-events.js +238 -0
  145. package/dist/pi-intercom/subagent-live-events.js +129 -86
  146. package/dist/pi-intercom/supervisor.js +282 -0
  147. package/dist/pi-intercom/tool-arguments.js +74 -0
  148. package/dist/pi-intercom/tool-registration.js +95 -0
  149. package/dist/pi-intercom/tool-results.js +38 -0
  150. package/dist/pi-intercom/tool-schemas.js +82 -0
  151. package/dist/pi-intercom/tools.js +51 -0
  152. package/dist/pi-intercom/topic-actions.js +177 -0
  153. package/dist/pi-intercom/topics.js +177 -92
  154. package/dist/pi-intercom/transport.js +1 -0
  155. package/dist/pi-intercom/types.js +151 -114
  156. package/dist/pi-intercom/ui/compose-paste.js +93 -0
  157. package/dist/pi-intercom/ui/compose.js +121 -143
  158. package/dist/pi-intercom/ui/inline-message.js +59 -59
  159. package/dist/pi-intercom/ui/message-renderers.js +147 -0
  160. package/dist/pi-intercom/ui/overlay.js +181 -0
  161. package/dist/pi-intercom/ui/session-format.js +124 -0
  162. package/dist/pi-intercom/ui/session-list.js +76 -43
  163. package/dist/pi-intercom/ui/tool-renderers.js +110 -0
  164. package/dist/pi-intercom/ui/topic-view.js +88 -0
  165. package/dist/pi-intercom/validation.js +59 -0
  166. package/dist/runs/background/async-chain-plan.js +265 -0
  167. package/dist/runs/background/async-control.js +134 -58
  168. package/dist/runs/background/async-execution.js +136 -633
  169. package/dist/runs/background/async-job-admission.js +40 -0
  170. package/dist/runs/background/async-job-projection.js +169 -0
  171. package/dist/runs/background/async-job-tracker.js +297 -327
  172. package/dist/runs/background/async-launch.js +216 -0
  173. package/dist/runs/background/async-plan.js +116 -0
  174. package/dist/runs/background/async-result-file.js +47 -23
  175. package/dist/runs/background/async-resume.js +195 -253
  176. package/dist/runs/background/async-run-discovery.js +213 -0
  177. package/dist/runs/background/async-run-location.js +135 -0
  178. package/dist/runs/background/async-run-record.js +1 -0
  179. package/dist/runs/background/async-run-repair.js +223 -0
  180. package/dist/runs/background/async-run-summary.js +1 -0
  181. package/dist/runs/background/async-single-plan.js +105 -0
  182. package/dist/runs/background/async-status-projection.js +155 -0
  183. package/dist/runs/background/async-status-render.js +117 -0
  184. package/dist/runs/background/async-status-validation.js +181 -0
  185. package/dist/runs/background/async-status.js +3 -442
  186. package/dist/runs/background/async-value.js +21 -0
  187. package/dist/runs/background/completion-dedupe.js +36 -12
  188. package/dist/runs/background/completion-delivery.js +211 -205
  189. package/dist/runs/background/completion-receipts.js +237 -0
  190. package/dist/runs/background/legacy-status-acceptance.js +34 -0
  191. package/dist/runs/background/notify.js +96 -48
  192. package/dist/runs/background/parallel-groups.js +36 -19
  193. package/dist/runs/background/result-payload.js +178 -0
  194. package/dist/runs/background/result-watcher.js +348 -339
  195. package/dist/runs/background/run-id-resolver.js +53 -33
  196. package/dist/runs/background/run-schemas.js +189 -0
  197. package/dist/runs/background/run-status-contracts.js +14 -0
  198. package/dist/runs/background/run-status-render.js +270 -0
  199. package/dist/runs/background/run-status.js +231 -339
  200. package/dist/runs/background/runner-attempt-output.js +155 -0
  201. package/dist/runs/background/runner-attempt.js +263 -0
  202. package/dist/runs/background/runner-child-executor.js +166 -0
  203. package/dist/runs/background/runner-child-observer.js +192 -0
  204. package/dist/runs/background/runner-completion-summary.js +71 -0
  205. package/dist/runs/background/runner-completion.js +211 -0
  206. package/dist/runs/background/runner-config.js +1 -0
  207. package/dist/runs/background/runner-contract.js +1 -0
  208. package/dist/runs/background/runner-dynamic.js +121 -0
  209. package/dist/runs/background/runner-finalization.js +149 -0
  210. package/dist/runs/background/runner-graph.js +68 -0
  211. package/dist/runs/background/runner-initial-status.js +60 -0
  212. package/dist/runs/background/runner-lifecycle.js +142 -0
  213. package/dist/runs/background/runner-monitor.js +309 -0
  214. package/dist/runs/background/runner-parallel.js +204 -0
  215. package/dist/runs/background/runner-prepare-step.js +86 -0
  216. package/dist/runs/background/runner-reporting.js +153 -0
  217. package/dist/runs/background/runner-status.js +148 -0
  218. package/dist/runs/background/runner-step-output.js +92 -0
  219. package/dist/runs/background/runner-step-record.js +45 -0
  220. package/dist/runs/background/runner-step.js +112 -0
  221. package/dist/runs/background/runner-streaming.js +173 -0
  222. package/dist/runs/background/runner-workflow.js +213 -0
  223. package/dist/runs/background/stale-run-reconciler.js +155 -292
  224. package/dist/runs/background/subagent-runner-launcher.js +33 -13
  225. package/dist/runs/background/subagent-runner.js +51 -1842
  226. package/dist/runs/background/top-level-async.js +2 -1
  227. package/dist/runs/foreground/chain-clarify.js +293 -1017
  228. package/dist/runs/foreground/clarification-draft.js +87 -0
  229. package/dist/runs/foreground/clarify-contracts.js +1 -0
  230. package/dist/runs/foreground/clarify-invocation.js +129 -38
  231. package/dist/runs/foreground/clarify-text-editor.js +210 -0
  232. package/dist/runs/foreground/clarify-view.js +167 -0
  233. package/dist/runs/foreground/execution-input.js +226 -353
  234. package/dist/runs/foreground/execution-routing.js +33 -0
  235. package/dist/runs/foreground/execution-timeout.js +81 -0
  236. package/dist/runs/foreground/foreground-control.js +222 -763
  237. package/dist/runs/foreground/foreground-memory.js +99 -0
  238. package/dist/runs/foreground/invocation-context.js +55 -0
  239. package/dist/runs/foreground/invocation-execution.js +331 -0
  240. package/dist/runs/foreground/invocation-expansion.js +48 -0
  241. package/dist/runs/foreground/management-actions.js +295 -0
  242. package/dist/runs/foreground/nested-control.js +179 -0
  243. package/dist/runs/foreground/question-continuation.js +78 -0
  244. package/dist/runs/foreground/question-control.js +155 -50
  245. package/dist/runs/foreground/resume-target.js +221 -0
  246. package/dist/runs/foreground/revival-launch-policy.js +58 -0
  247. package/dist/runs/foreground/run-async-path.js +190 -178
  248. package/dist/runs/foreground/run-interrupt.js +164 -0
  249. package/dist/runs/foreground/run-nudge.js +278 -0
  250. package/dist/runs/foreground/saved-revival.js +251 -0
  251. package/dist/runs/foreground/subagent-executor.js +135 -424
  252. package/dist/runs/foreground/subagent-params.js +67 -30
  253. package/dist/runs/foreground/wait-observation.js +104 -0
  254. package/dist/runs/foreground/wait-registration.js +17 -0
  255. package/dist/runs/foreground/wait-run.js +283 -123
  256. package/dist/runs/shared/acceptance-contract.js +193 -99
  257. package/dist/runs/shared/acceptance-defaults.js +1 -0
  258. package/dist/runs/shared/acceptance-evaluation.js +201 -181
  259. package/dist/runs/shared/acceptance-finalization.js +256 -180
  260. package/dist/runs/shared/acceptance-outcome.js +53 -0
  261. package/dist/runs/shared/acceptance-reports.js +137 -72
  262. package/dist/runs/shared/acceptance-submission.js +167 -0
  263. package/dist/runs/shared/acceptance-verification.js +100 -0
  264. package/dist/runs/shared/chain-outputs.js +80 -52
  265. package/dist/runs/shared/child-attempt-types.js +1 -0
  266. package/dist/runs/shared/child-attempt.js +314 -667
  267. package/dist/runs/shared/child-boundaries.js +173 -0
  268. package/dist/runs/shared/child-context-filter.js +44 -0
  269. package/dist/runs/shared/child-event-observer.js +390 -0
  270. package/dist/runs/shared/child-execution-cwd.js +73 -43
  271. package/dist/runs/shared/child-execution-outcome.js +72 -0
  272. package/dist/runs/shared/child-invocation.js +54 -0
  273. package/dist/runs/shared/child-message-validation.js +215 -0
  274. package/dist/runs/shared/child-native-accounting.js +106 -0
  275. package/dist/runs/shared/child-native-observation.js +69 -0
  276. package/dist/runs/shared/child-observation-spool.js +164 -0
  277. package/dist/runs/shared/child-observations.js +157 -76
  278. package/dist/runs/shared/child-presence.js +3 -0
  279. package/dist/runs/shared/child-route-env.js +119 -0
  280. package/dist/runs/shared/child-stream-observer.js +221 -0
  281. package/dist/runs/shared/child-stream-projection.js +137 -0
  282. package/dist/runs/shared/child-structured-tool.js +27 -0
  283. package/dist/runs/shared/claude-code.js +121 -158
  284. package/dist/runs/shared/claude-model.js +42 -0
  285. package/dist/runs/shared/claude-session.js +83 -0
  286. package/dist/runs/shared/claude-types.js +1 -0
  287. package/dist/runs/shared/completion-guard.js +18 -18
  288. package/dist/runs/shared/control-event-policy.js +8 -0
  289. package/dist/runs/shared/control-notification-owner.js +13 -0
  290. package/dist/runs/shared/dynamic-fanout.js +188 -173
  291. package/dist/runs/shared/dynamic-item.js +102 -0
  292. package/dist/runs/shared/history-index.js +62 -36
  293. package/dist/runs/shared/legacy-async-recovery.js +114 -0
  294. package/dist/runs/shared/legacy-output-recovery.js +148 -0
  295. package/dist/runs/shared/mcp-config-schema.js +36 -0
  296. package/dist/runs/shared/mcp-direct-tool-allowlist.js +147 -116
  297. package/dist/runs/shared/model-fallback.js +97 -38
  298. package/dist/runs/shared/mutating-tool-guard.js +128 -88
  299. package/dist/runs/shared/native-finalization-types.js +1 -0
  300. package/dist/runs/shared/native-finalization.js +155 -76
  301. package/dist/runs/shared/native-usage.js +238 -98
  302. package/dist/runs/shared/nested-control-records.js +128 -0
  303. package/dist/runs/shared/nested-events.js +8 -700
  304. package/dist/runs/shared/nested-path.js +32 -28
  305. package/dist/runs/shared/nested-projection.js +155 -0
  306. package/dist/runs/shared/nested-protocol.js +18 -0
  307. package/dist/runs/shared/nested-registry.js +191 -0
  308. package/dist/runs/shared/nested-render.js +106 -58
  309. package/dist/runs/shared/nested-route.js +220 -0
  310. package/dist/runs/shared/nested-validation.js +216 -0
  311. package/dist/runs/shared/owned-child-evidence.js +125 -0
  312. package/dist/runs/shared/owned-run-list.js +146 -0
  313. package/dist/runs/shared/owned-run-observation.js +267 -0
  314. package/dist/runs/shared/owned-run-progress.js +109 -0
  315. package/dist/runs/shared/owned-run-read-state.js +1 -0
  316. package/dist/runs/shared/owned-run-results.js +202 -0
  317. package/dist/runs/shared/owned-run-status.js +180 -0
  318. package/dist/runs/shared/owned-run-view.js +51 -0
  319. package/dist/runs/shared/owned-workflow-details.js +17 -0
  320. package/dist/runs/shared/owner-output.js +43 -0
  321. package/dist/runs/shared/parallel-utils.js +36 -28
  322. package/dist/runs/shared/parent-receipts.js +90 -32
  323. package/dist/runs/shared/parent-usage.js +169 -57
  324. package/dist/runs/shared/pi-args.js +108 -201
  325. package/dist/runs/shared/pi-launch-input.js +1 -0
  326. package/dist/runs/shared/pi-session-launch.js +86 -0
  327. package/dist/runs/shared/pi-spawn.js +35 -21
  328. package/dist/runs/shared/run-history-queries.js +126 -35
  329. package/dist/runs/shared/run-history.js +101 -35
  330. package/dist/runs/shared/run-metadata-paths.js +14 -0
  331. package/dist/runs/shared/run-metadata.js +158 -0
  332. package/dist/runs/shared/run-persistence.js +131 -0
  333. package/dist/runs/shared/run-records.js +9 -679
  334. package/dist/runs/shared/run-restoration.js +338 -0
  335. package/dist/runs/shared/run-state-owner.js +26 -0
  336. package/dist/runs/shared/session-cwd-preload.js +27 -18
  337. package/dist/runs/shared/single-output.js +148 -70
  338. package/dist/runs/shared/stable-value.js +15 -0
  339. package/dist/runs/shared/streaming-text.js +23 -12
  340. package/dist/runs/shared/structured-output.js +25 -13
  341. package/dist/runs/shared/subagent-control.js +167 -100
  342. package/dist/runs/shared/subagent-prompt-runtime.js +27 -130
  343. package/dist/runs/shared/subagent-tool-loop-guard.js +81 -52
  344. package/dist/runs/shared/supervisor-question-state.js +145 -0
  345. package/dist/runs/shared/supervisor-questions.js +185 -254
  346. package/dist/runs/shared/workflow-graph.js +259 -167
  347. package/dist/runs/shared/workflow-policy.js +120 -48
  348. package/dist/runs/shared/worktree-contract.js +1 -0
  349. package/dist/runs/shared/worktree-hook.js +138 -0
  350. package/dist/runs/shared/worktree-location.js +47 -0
  351. package/dist/runs/shared/worktree-preservation.js +8 -0
  352. package/dist/runs/shared/worktree-process.js +107 -0
  353. package/dist/runs/shared/worktree.js +183 -322
  354. package/dist/shared/agent-context-policy.js +34 -44
  355. package/dist/shared/agent-dir.js +14 -0
  356. package/dist/shared/artifacts.js +30 -12
  357. package/dist/shared/atomic-json.js +4 -1
  358. package/dist/shared/chain-files.js +72 -0
  359. package/dist/shared/concurrency.js +18 -0
  360. package/dist/shared/content-preview.js +115 -0
  361. package/dist/shared/cooperative.js +5 -2
  362. package/dist/shared/execution-cwd.js +13 -5
  363. package/dist/shared/file-coalescer.js +2 -1
  364. package/dist/shared/fork-context.js +10 -12
  365. package/dist/shared/formatters.js +45 -19
  366. package/dist/shared/journal-frames.js +164 -0
  367. package/dist/shared/journal-projections.js +121 -0
  368. package/dist/shared/journal-reader.js +6 -407
  369. package/dist/shared/json-projection.js +191 -0
  370. package/dist/shared/lazy-tools.js +19 -8
  371. package/dist/shared/message-output.js +116 -0
  372. package/dist/shared/model-info.js +31 -14
  373. package/dist/shared/native-import.js +20 -0
  374. package/dist/shared/native-journal.js +140 -0
  375. package/dist/shared/native-session.js +5 -2
  376. package/dist/shared/native-tui.js +7 -2
  377. package/dist/shared/native-typebox.js +15 -3
  378. package/dist/shared/output-page.js +63 -0
  379. package/dist/shared/post-exit-stdio-guard.js +128 -88
  380. package/dist/shared/prompt-sections.js +2 -0
  381. package/dist/shared/session-entries.js +70 -35
  382. package/dist/shared/session-identity.js +5 -3
  383. package/dist/shared/settings.js +62 -192
  384. package/dist/shared/status-format.js +97 -37
  385. package/dist/shared/task-file-policy.js +24 -0
  386. package/dist/shared/temp-root.js +44 -15
  387. package/dist/shared/types/acceptance.js +1 -0
  388. package/dist/shared/types/async.js +1 -0
  389. package/dist/shared/types/config.js +1 -0
  390. package/dist/shared/types/details.js +1 -0
  391. package/dist/shared/types/history.js +1 -0
  392. package/dist/shared/types/inputs.js +1 -0
  393. package/dist/shared/types/intercom.js +1 -0
  394. package/dist/shared/types/launch.js +1 -0
  395. package/dist/shared/types/messages.js +1 -0
  396. package/dist/shared/types/nested.js +1 -0
  397. package/dist/shared/types/owned-runs.js +1 -0
  398. package/dist/shared/types/progress.js +1 -0
  399. package/dist/shared/types/questions.js +1 -0
  400. package/dist/shared/types/results.js +1 -0
  401. package/dist/shared/types/state.js +1 -0
  402. package/dist/shared/types/usage.js +1 -0
  403. package/dist/shared/types/workflow.js +1 -0
  404. package/dist/shared/types.js +75 -30
  405. package/dist/shared/unknown.js +52 -0
  406. package/dist/shared/utils.js +54 -260
  407. package/dist/slash/command-discovery.js +82 -0
  408. package/dist/slash/command-input.js +190 -0
  409. package/dist/slash/prompt-template-bridge.js +94 -270
  410. package/dist/slash/prompt-template-contract.js +77 -0
  411. package/dist/slash/prompt-template-results.js +125 -0
  412. package/dist/slash/request-protocol.js +68 -0
  413. package/dist/slash/result-delivery.js +237 -0
  414. package/dist/slash/saved-chain.js +78 -0
  415. package/dist/slash/slash-bridge.js +123 -89
  416. package/dist/slash/slash-commands.js +101 -572
  417. package/dist/slash/slash-live-state.js +68 -47
  418. package/dist/tui/action-hints.js +50 -22
  419. package/dist/tui/activity-lines.js +32 -0
  420. package/dist/tui/agent-browser.js +290 -0
  421. package/dist/tui/agent-controls.js +289 -0
  422. package/dist/tui/agent-conversation.js +444 -0
  423. package/dist/tui/agent-dock.js +171 -0
  424. package/dist/tui/agent-history.js +50 -183
  425. package/dist/tui/agent-model.js +62 -0
  426. package/dist/tui/agent-picker.js +262 -0
  427. package/dist/tui/agent-view.js +232 -1537
  428. package/dist/tui/compact-results.js +193 -0
  429. package/dist/tui/conversation-details.js +190 -0
  430. package/dist/tui/conversation-frame.js +135 -0
  431. package/dist/tui/conversation-history.js +201 -0
  432. package/dist/tui/conversation-menu.js +78 -0
  433. package/dist/tui/conversation-notices.js +79 -0
  434. package/dist/tui/conversation-selection.js +58 -0
  435. package/dist/tui/conversation-viewport.js +129 -0
  436. package/dist/tui/direction-message.js +27 -0
  437. package/dist/tui/display.js +282 -0
  438. package/dist/tui/editor-viewport.js +18 -0
  439. package/dist/tui/expanded-content.js +87 -0
  440. package/dist/tui/expanded-multi.js +170 -0
  441. package/dist/tui/expanded-single.js +65 -0
  442. package/dist/tui/history-cards.js +216 -0
  443. package/dist/tui/history-display.js +238 -0
  444. package/dist/tui/history-json.js +16 -0
  445. package/dist/tui/history-metadata.js +152 -0
  446. package/dist/tui/history-record.js +251 -0
  447. package/dist/tui/history-text.js +34 -0
  448. package/dist/tui/indexed-history.js +116 -0
  449. package/dist/tui/nested-widget.js +120 -0
  450. package/dist/tui/picker-page.js +59 -0
  451. package/dist/tui/render.js +58 -1501
  452. package/dist/tui/result-facts.js +64 -0
  453. package/dist/tui/task-observation.js +59 -0
  454. package/dist/tui/task-store.js +366 -0
  455. package/dist/tui/text-values.js +16 -0
  456. package/dist/tui/view-connections.js +47 -0
  457. package/dist/tui/view-model.js +94 -0
  458. package/dist/tui/view-persistence.js +51 -0
  459. package/dist/tui/view-ports.js +1 -0
  460. package/dist/tui/view-session.js +37 -0
  461. package/dist/tui/widget-details.js +144 -0
  462. package/dist/tui/widget-status.js +245 -0
  463. package/dist/tui/widget.js +145 -0
  464. package/dist/tui/workflow-labels.js +223 -0
  465. package/dist/tui/workflow-outcomes.js +124 -0
  466. package/docs/code-quality.md +38 -0
  467. package/docs/development.md +99 -0
  468. package/docs/intercom-bridge.md +23 -18
  469. package/docs/intercom.md +132 -106
  470. package/docs/performance.md +19 -17
  471. package/docs/reference.md +1472 -0
  472. package/generated/RunValidators.d.ts +28 -0
  473. package/generated/RunValidators.js +2 -0
  474. package/package.json +27 -6
  475. package/prompts/parallel-cleanup.md +3 -0
  476. package/prompts/parallel-context-build.md +3 -0
  477. package/prompts/parallel-handoff-plan.md +6 -0
  478. package/prompts/parallel-research.md +4 -0
  479. package/prompts/parallel-review.md +2 -0
  480. package/prompts/review-loop.md +2 -0
  481. package/scripts/build.mjs +129 -85
  482. package/scripts/check-compat.mjs +48 -11
  483. package/scripts/compat-host.mjs +35 -7
  484. package/scripts/generate-run-schemas.mjs +210 -0
  485. package/scripts/intercom-bridge-credentials.mjs +155 -28
  486. package/scripts/intercom-remote.mjs +175 -50
  487. package/scripts/local-install-smoke.mjs +47 -37
  488. package/scripts/native-package-smoke.mjs +135 -25
  489. package/scripts/package-smoke.mjs +360 -140
  490. package/scripts/prepare.mjs +54 -34
  491. package/scripts/real-pi-processes.mjs +261 -0
  492. package/scripts/real-pi-smoke.mjs +432 -351
  493. package/scripts/run-tests.mjs +29 -15
  494. package/skills/pi-intercom/SKILL.md +11 -11
  495. package/skills/pi-intercom/references/peer-sessions.md +7 -2
  496. package/skills/pi-subagents/SKILL.md +1 -1
  497. package/skills/pi-subagents/references/full-orchestration-guide.md +254 -112
  498. package/src/agents/agent-defaults.ts +13 -0
  499. package/src/agents/agent-definition.ts +253 -0
  500. package/src/agents/agent-management.ts +111 -808
  501. package/src/agents/agent-scope.ts +7 -3
  502. package/src/agents/agent-selection.ts +26 -16
  503. package/src/agents/agent-serializer.ts +84 -93
  504. package/src/agents/agents.ts +199 -906
  505. package/src/agents/builtin-overrides.ts +297 -0
  506. package/src/agents/chain-serializer.ts +3 -329
  507. package/src/agents/config-values.ts +57 -0
  508. package/src/agents/discovery-paths.ts +134 -0
  509. package/src/agents/frontmatter.ts +35 -17
  510. package/src/agents/identity.ts +49 -18
  511. package/src/agents/json-chain.ts +305 -0
  512. package/src/agents/management-config.ts +342 -0
  513. package/src/agents/management-format.ts +243 -0
  514. package/src/agents/management-persistence.ts +408 -0
  515. package/src/agents/management-targets.ts +260 -0
  516. package/src/agents/management-warnings.ts +115 -0
  517. package/src/agents/markdown-chain.ts +237 -0
  518. package/src/agents/package-agents.ts +231 -0
  519. package/src/agents/skill-files.ts +182 -0
  520. package/src/agents/skill-search-paths.ts +289 -0
  521. package/src/agents/skill-types.ts +31 -0
  522. package/src/agents/skills.ts +152 -610
  523. package/src/extension/acceptance-schema.ts +88 -0
  524. package/src/extension/chain-schema.ts +276 -0
  525. package/src/extension/child-runtime.ts +302 -0
  526. package/src/extension/compact-tools.ts +259 -102
  527. package/src/extension/config-schema.ts +59 -0
  528. package/src/extension/config.ts +39 -17
  529. package/src/extension/control-notice-schema.ts +55 -0
  530. package/src/extension/control-notices.ts +57 -33
  531. package/src/extension/delegation-bridges.ts +59 -0
  532. package/src/extension/doctor.ts +171 -135
  533. package/src/extension/everyday-schemas.ts +252 -0
  534. package/src/extension/fanout-child.ts +29 -308
  535. package/src/extension/index.ts +17 -642
  536. package/src/extension/message-renderers.ts +334 -0
  537. package/src/extension/nested-control-inbox.ts +196 -0
  538. package/src/extension/parent-runtime.ts +405 -0
  539. package/src/extension/primary-tool.ts +130 -0
  540. package/src/extension/result-snapshot.ts +35 -0
  541. package/src/extension/runtime-reload.ts +72 -0
  542. package/src/extension/runtime-storage.ts +49 -0
  543. package/src/extension/schema-overrides.ts +114 -0
  544. package/src/extension/schemas.ts +451 -418
  545. package/src/extension/tool-input.ts +40 -13
  546. package/src/extension/tool-result.ts +45 -14
  547. package/src/history/answer-texts.ts +74 -0
  548. package/src/history/canonical-result.ts +127 -51
  549. package/src/history/canonical-selection.ts +54 -0
  550. package/src/history/database-generation.ts +86 -0
  551. package/src/history/database.ts +86 -48
  552. package/src/history/entry-ingestion.ts +129 -0
  553. package/src/history/index.ts +426 -148
  554. package/src/history/ingest.ts +372 -342
  555. package/src/history/output-digests.ts +41 -0
  556. package/src/history/preview.ts +235 -0
  557. package/src/history/prune.ts +48 -0
  558. package/src/history/queries.ts +122 -256
  559. package/src/history/query-scope.ts +278 -0
  560. package/src/history/rows.ts +118 -0
  561. package/src/history/run-projection.ts +164 -0
  562. package/src/history/run-queries.ts +199 -0
  563. package/src/history/schema.ts +34 -0
  564. package/src/history/search-queries.ts +216 -0
  565. package/src/history/selected-record.ts +140 -0
  566. package/src/history/source-file.ts +51 -0
  567. package/src/history/source-watches.ts +156 -0
  568. package/src/history/store.ts +310 -197
  569. package/src/history/text-chunks.ts +181 -0
  570. package/src/history/text.ts +43 -0
  571. package/src/history/transcript-queries.ts +251 -0
  572. package/src/history/types.ts +27 -164
  573. package/src/history/values.ts +36 -0
  574. package/src/history/wire-inputs.ts +141 -0
  575. package/src/history/wire-models.ts +51 -0
  576. package/src/history/worker-runtime.ts +502 -0
  577. package/src/history/worker.ts +94 -336
  578. package/src/intercom/intercom-bridge.ts +136 -69
  579. package/src/intercom/live-intercom.ts +197 -92
  580. package/src/intercom/nested-result-tree.ts +213 -0
  581. package/src/intercom/result-delivery.ts +56 -0
  582. package/src/intercom/result-intercom.ts +364 -382
  583. package/src/pi-intercom/agent-dir.ts +9 -3
  584. package/src/pi-intercom/async.ts +33 -0
  585. package/src/pi-intercom/bridge-ask.ts +64 -0
  586. package/src/pi-intercom/bridge-config.ts +101 -0
  587. package/src/pi-intercom/bridge-http.ts +97 -0
  588. package/src/pi-intercom/bridge-protocol.ts +123 -0
  589. package/src/pi-intercom/bridge-routes.ts +90 -0
  590. package/src/pi-intercom/bridge-session.ts +506 -0
  591. package/src/pi-intercom/bridge.ts +258 -547
  592. package/src/pi-intercom/broker/broker.ts +326 -263
  593. package/src/pi-intercom/broker/client.ts +273 -354
  594. package/src/pi-intercom/broker/connection.ts +192 -0
  595. package/src/pi-intercom/broker/framing.ts +11 -6
  596. package/src/pi-intercom/broker/paths.ts +28 -25
  597. package/src/pi-intercom/broker/pid.ts +68 -24
  598. package/src/pi-intercom/broker/snapshot-reader.ts +91 -0
  599. package/src/pi-intercom/broker/snapshots.ts +241 -0
  600. package/src/pi-intercom/broker/spawn.ts +58 -34
  601. package/src/pi-intercom/config.ts +113 -108
  602. package/src/pi-intercom/connection.ts +346 -0
  603. package/src/pi-intercom/identity.ts +71 -0
  604. package/src/pi-intercom/inbound-delivery.ts +450 -0
  605. package/src/pi-intercom/inbound-journal.ts +350 -0
  606. package/src/pi-intercom/inbound-record.ts +141 -0
  607. package/src/pi-intercom/inbound.ts +237 -0
  608. package/src/pi-intercom/index.ts +86 -2923
  609. package/src/pi-intercom/inspection.ts +82 -0
  610. package/src/pi-intercom/interview.ts +295 -0
  611. package/src/pi-intercom/lifecycle.ts +183 -0
  612. package/src/pi-intercom/message-format.ts +77 -0
  613. package/src/pi-intercom/outbound.ts +418 -0
  614. package/src/pi-intercom/peer-awareness.ts +84 -0
  615. package/src/pi-intercom/reply-tracker.ts +121 -59
  616. package/src/pi-intercom/reply-wait.ts +247 -0
  617. package/src/pi-intercom/runtime-types.ts +97 -0
  618. package/src/pi-intercom/session-events.ts +247 -0
  619. package/src/pi-intercom/session-targets.ts +124 -72
  620. package/src/pi-intercom/subagent-events.ts +299 -0
  621. package/src/pi-intercom/subagent-live-events.ts +212 -109
  622. package/src/pi-intercom/supervisor.ts +362 -0
  623. package/src/pi-intercom/tool-arguments.ts +120 -0
  624. package/src/pi-intercom/tool-registration.ts +121 -0
  625. package/src/pi-intercom/tool-results.ts +54 -0
  626. package/src/pi-intercom/tool-schemas.ts +134 -0
  627. package/src/pi-intercom/tools.ts +80 -0
  628. package/src/pi-intercom/topic-actions.ts +243 -0
  629. package/src/pi-intercom/topics.ts +267 -121
  630. package/src/pi-intercom/transport.ts +14 -0
  631. package/src/pi-intercom/types.ts +288 -190
  632. package/src/pi-intercom/ui/compose-paste.ts +109 -0
  633. package/src/pi-intercom/ui/compose.ts +173 -157
  634. package/src/pi-intercom/ui/inline-message.ts +80 -62
  635. package/src/pi-intercom/ui/message-renderers.ts +182 -0
  636. package/src/pi-intercom/ui/overlay.ts +238 -0
  637. package/src/pi-intercom/ui/session-format.ts +146 -0
  638. package/src/pi-intercom/ui/session-list.ts +145 -62
  639. package/src/pi-intercom/ui/tool-renderers.ts +148 -0
  640. package/src/pi-intercom/ui/topic-view.ts +107 -0
  641. package/src/pi-intercom/validation.ts +69 -0
  642. package/src/runs/background/async-chain-plan.ts +451 -0
  643. package/src/runs/background/async-control.ts +201 -71
  644. package/src/runs/background/async-execution.ts +206 -829
  645. package/src/runs/background/async-job-admission.ts +54 -0
  646. package/src/runs/background/async-job-projection.ts +225 -0
  647. package/src/runs/background/async-job-tracker.ts +416 -360
  648. package/src/runs/background/async-launch.ts +319 -0
  649. package/src/runs/background/async-plan.ts +285 -0
  650. package/src/runs/background/async-result-file.ts +79 -37
  651. package/src/runs/background/async-resume.ts +338 -285
  652. package/src/runs/background/async-run-discovery.ts +270 -0
  653. package/src/runs/background/async-run-location.ts +194 -0
  654. package/src/runs/background/async-run-record.ts +14 -0
  655. package/src/runs/background/async-run-repair.ts +307 -0
  656. package/src/runs/background/async-run-summary.ts +71 -0
  657. package/src/runs/background/async-single-plan.ts +168 -0
  658. package/src/runs/background/async-status-projection.ts +188 -0
  659. package/src/runs/background/async-status-render.ts +164 -0
  660. package/src/runs/background/async-status-validation.ts +238 -0
  661. package/src/runs/background/async-status.ts +9 -481
  662. package/src/runs/background/async-value.ts +29 -0
  663. package/src/runs/background/completion-dedupe.ts +103 -54
  664. package/src/runs/background/completion-delivery.ts +313 -187
  665. package/src/runs/background/completion-receipts.ts +309 -0
  666. package/src/runs/background/legacy-status-acceptance.ts +38 -0
  667. package/src/runs/background/notify.ts +167 -106
  668. package/src/runs/background/parallel-groups.ts +95 -46
  669. package/src/runs/background/result-payload.ts +268 -0
  670. package/src/runs/background/result-watcher.ts +484 -387
  671. package/src/runs/background/run-id-resolver.ts +126 -57
  672. package/src/runs/background/run-schemas.ts +240 -0
  673. package/src/runs/background/run-status-contracts.ts +46 -0
  674. package/src/runs/background/run-status-render.ts +364 -0
  675. package/src/runs/background/run-status.ts +338 -356
  676. package/src/runs/background/runner-attempt-output.ts +281 -0
  677. package/src/runs/background/runner-attempt.ts +354 -0
  678. package/src/runs/background/runner-child-executor.ts +232 -0
  679. package/src/runs/background/runner-child-observer.ts +270 -0
  680. package/src/runs/background/runner-completion-summary.ts +106 -0
  681. package/src/runs/background/runner-completion.ts +274 -0
  682. package/src/runs/background/runner-config.ts +52 -0
  683. package/src/runs/background/runner-contract.ts +51 -0
  684. package/src/runs/background/runner-dynamic.ts +185 -0
  685. package/src/runs/background/runner-finalization.ts +203 -0
  686. package/src/runs/background/runner-graph.ts +91 -0
  687. package/src/runs/background/runner-initial-status.ts +72 -0
  688. package/src/runs/background/runner-lifecycle.ts +159 -0
  689. package/src/runs/background/runner-monitor.ts +399 -0
  690. package/src/runs/background/runner-parallel.ts +280 -0
  691. package/src/runs/background/runner-prepare-step.ts +128 -0
  692. package/src/runs/background/runner-reporting.ts +192 -0
  693. package/src/runs/background/runner-status.ts +220 -0
  694. package/src/runs/background/runner-step-output.ts +158 -0
  695. package/src/runs/background/runner-step-record.ts +76 -0
  696. package/src/runs/background/runner-step.ts +150 -0
  697. package/src/runs/background/runner-streaming.ts +220 -0
  698. package/src/runs/background/runner-workflow.ts +284 -0
  699. package/src/runs/background/stale-run-reconciler.ts +279 -336
  700. package/src/runs/background/subagent-runner-launcher.ts +67 -35
  701. package/src/runs/background/subagent-runner.ts +80 -2048
  702. package/src/runs/background/top-level-async.ts +9 -7
  703. package/src/runs/foreground/chain-clarify.ts +499 -1334
  704. package/src/runs/foreground/clarification-draft.ts +92 -0
  705. package/src/runs/foreground/clarify-contracts.ts +33 -0
  706. package/src/runs/foreground/clarify-invocation.ts +192 -65
  707. package/src/runs/foreground/clarify-text-editor.ts +229 -0
  708. package/src/runs/foreground/clarify-view.ts +222 -0
  709. package/src/runs/foreground/execution-input.ts +358 -424
  710. package/src/runs/foreground/execution-routing.ts +41 -0
  711. package/src/runs/foreground/execution-timeout.ts +92 -0
  712. package/src/runs/foreground/foreground-control.ts +333 -812
  713. package/src/runs/foreground/foreground-memory.ts +132 -0
  714. package/src/runs/foreground/invocation-context.ts +88 -0
  715. package/src/runs/foreground/invocation-execution.ts +465 -0
  716. package/src/runs/foreground/invocation-expansion.ts +58 -0
  717. package/src/runs/foreground/management-actions.ts +360 -0
  718. package/src/runs/foreground/nested-control.ts +248 -0
  719. package/src/runs/foreground/question-continuation.ts +112 -0
  720. package/src/runs/foreground/question-control.ts +297 -70
  721. package/src/runs/foreground/resume-target.ts +330 -0
  722. package/src/runs/foreground/revival-launch-policy.ts +112 -0
  723. package/src/runs/foreground/run-async-path.ts +307 -223
  724. package/src/runs/foreground/run-interrupt.ts +202 -0
  725. package/src/runs/foreground/run-nudge.ts +355 -0
  726. package/src/runs/foreground/saved-revival.ts +356 -0
  727. package/src/runs/foreground/subagent-executor.ts +195 -493
  728. package/src/runs/foreground/subagent-params.ts +314 -242
  729. package/src/runs/foreground/wait-observation.ts +160 -0
  730. package/src/runs/foreground/wait-registration.ts +18 -0
  731. package/src/runs/foreground/wait-run.ts +361 -119
  732. package/src/runs/shared/acceptance-contract.ts +410 -209
  733. package/src/runs/shared/acceptance-defaults.ts +1 -0
  734. package/src/runs/shared/acceptance-evaluation.ts +314 -240
  735. package/src/runs/shared/acceptance-finalization.ts +447 -305
  736. package/src/runs/shared/acceptance-outcome.ts +69 -0
  737. package/src/runs/shared/acceptance-reports.ts +220 -126
  738. package/src/runs/shared/acceptance-submission.ts +251 -0
  739. package/src/runs/shared/acceptance-verification.ts +118 -0
  740. package/src/runs/shared/acceptance.ts +25 -25
  741. package/src/runs/shared/chain-outputs.ts +190 -98
  742. package/src/runs/shared/child-attempt-types.ts +118 -0
  743. package/src/runs/shared/child-attempt.ts +372 -608
  744. package/src/runs/shared/child-boundaries.ts +217 -0
  745. package/src/runs/shared/child-context-filter.ts +53 -0
  746. package/src/runs/shared/child-event-observer.ts +496 -0
  747. package/src/runs/shared/child-execution-cwd.ts +139 -68
  748. package/src/runs/shared/child-execution-outcome.ts +103 -0
  749. package/src/runs/shared/child-invocation.ts +74 -0
  750. package/src/runs/shared/child-message-validation.ts +233 -0
  751. package/src/runs/shared/child-native-accounting.ts +154 -0
  752. package/src/runs/shared/child-native-observation.ts +79 -0
  753. package/src/runs/shared/child-observation-spool.ts +188 -0
  754. package/src/runs/shared/child-observations.ts +219 -89
  755. package/src/runs/shared/child-presence.ts +6 -0
  756. package/src/runs/shared/child-route-env.ts +142 -0
  757. package/src/runs/shared/child-stream-observer.ts +302 -0
  758. package/src/runs/shared/child-stream-projection.ts +160 -0
  759. package/src/runs/shared/child-structured-tool.ts +38 -0
  760. package/src/runs/shared/claude-code.ts +201 -228
  761. package/src/runs/shared/claude-model.ts +67 -0
  762. package/src/runs/shared/claude-session.ts +124 -0
  763. package/src/runs/shared/claude-types.ts +31 -0
  764. package/src/runs/shared/completion-guard.ts +35 -26
  765. package/src/runs/shared/control-event-policy.ts +15 -0
  766. package/src/runs/shared/control-notification-owner.ts +20 -0
  767. package/src/runs/shared/dynamic-fanout.ts +402 -238
  768. package/src/runs/shared/dynamic-item.ts +114 -0
  769. package/src/runs/shared/history-index.ts +112 -51
  770. package/src/runs/shared/legacy-async-recovery.ts +153 -0
  771. package/src/runs/shared/legacy-output-recovery.ts +214 -0
  772. package/src/runs/shared/mcp-config-schema.ts +46 -0
  773. package/src/runs/shared/mcp-direct-tool-allowlist.ts +396 -307
  774. package/src/runs/shared/model-fallback.ts +302 -180
  775. package/src/runs/shared/mutating-tool-guard.ts +259 -158
  776. package/src/runs/shared/native-finalization-types.ts +29 -0
  777. package/src/runs/shared/native-finalization.ts +233 -109
  778. package/src/runs/shared/native-usage.ts +379 -96
  779. package/src/runs/shared/nested-control-records.ts +178 -0
  780. package/src/runs/shared/nested-events.ts +45 -752
  781. package/src/runs/shared/nested-path.ts +47 -34
  782. package/src/runs/shared/nested-projection.ts +230 -0
  783. package/src/runs/shared/nested-protocol.ts +67 -0
  784. package/src/runs/shared/nested-registry.ts +273 -0
  785. package/src/runs/shared/nested-render.ts +198 -100
  786. package/src/runs/shared/nested-route.ts +292 -0
  787. package/src/runs/shared/nested-validation.ts +291 -0
  788. package/src/runs/shared/owned-child-evidence.ts +184 -0
  789. package/src/runs/shared/owned-run-list.ts +187 -0
  790. package/src/runs/shared/owned-run-observation.ts +368 -0
  791. package/src/runs/shared/owned-run-progress.ts +172 -0
  792. package/src/runs/shared/owned-run-read-state.ts +7 -0
  793. package/src/runs/shared/owned-run-results.ts +289 -0
  794. package/src/runs/shared/owned-run-status.ts +239 -0
  795. package/src/runs/shared/owned-run-view.ts +65 -0
  796. package/src/runs/shared/owned-workflow-details.ts +24 -0
  797. package/src/runs/shared/owner-output.ts +73 -0
  798. package/src/runs/shared/parallel-utils.ts +93 -129
  799. package/src/runs/shared/parent-receipts.ts +177 -50
  800. package/src/runs/shared/parent-usage.ts +314 -91
  801. package/src/runs/shared/pi-args.ts +241 -311
  802. package/src/runs/shared/pi-launch-input.ts +48 -0
  803. package/src/runs/shared/pi-session-launch.ts +94 -0
  804. package/src/runs/shared/pi-spawn.ts +57 -33
  805. package/src/runs/shared/run-history-queries.ts +189 -38
  806. package/src/runs/shared/run-history.ts +197 -76
  807. package/src/runs/shared/run-id-ambiguity.ts +7 -3
  808. package/src/runs/shared/run-metadata-paths.ts +17 -0
  809. package/src/runs/shared/run-metadata.ts +240 -0
  810. package/src/runs/shared/run-persistence.ts +181 -0
  811. package/src/runs/shared/run-records.ts +19 -607
  812. package/src/runs/shared/run-restoration.ts +455 -0
  813. package/src/runs/shared/run-state-owner.ts +31 -0
  814. package/src/runs/shared/session-cwd-preload.ts +39 -19
  815. package/src/runs/shared/single-output.ts +358 -205
  816. package/src/runs/shared/stable-value.ts +15 -0
  817. package/src/runs/shared/streaming-text.ts +39 -12
  818. package/src/runs/shared/structured-output.ts +76 -46
  819. package/src/runs/shared/subagent-control.ts +330 -197
  820. package/src/runs/shared/subagent-prompt-runtime.ts +92 -174
  821. package/src/runs/shared/subagent-tool-loop-guard.ts +118 -68
  822. package/src/runs/shared/supervisor-question-state.ts +221 -0
  823. package/src/runs/shared/supervisor-questions.ts +396 -401
  824. package/src/runs/shared/workflow-graph.ts +400 -198
  825. package/src/runs/shared/workflow-policy.ts +245 -110
  826. package/src/runs/shared/worktree-contract.ts +29 -0
  827. package/src/runs/shared/worktree-hook.ts +181 -0
  828. package/src/runs/shared/worktree-location.ts +61 -0
  829. package/src/runs/shared/worktree-preservation.ts +10 -0
  830. package/src/runs/shared/worktree-process.ts +132 -0
  831. package/src/runs/shared/worktree.ts +459 -587
  832. package/src/shared/agent-context-policy.ts +176 -145
  833. package/src/shared/agent-dir.ts +15 -0
  834. package/src/shared/artifacts.ts +99 -68
  835. package/src/shared/atomic-json.ts +14 -11
  836. package/src/shared/chain-files.ts +72 -0
  837. package/src/shared/concurrency.ts +27 -0
  838. package/src/shared/content-preview.ts +117 -0
  839. package/src/shared/cooperative.ts +17 -13
  840. package/src/shared/execution-cwd.ts +34 -9
  841. package/src/shared/file-coalescer.ts +24 -22
  842. package/src/shared/fork-context.ts +52 -48
  843. package/src/shared/formatters.ts +88 -47
  844. package/src/shared/journal-frames.ts +197 -0
  845. package/src/shared/journal-projections.ts +133 -0
  846. package/src/shared/journal-reader.ts +18 -333
  847. package/src/shared/json-projection.ts +224 -0
  848. package/src/shared/lazy-tools.ts +76 -27
  849. package/src/shared/message-output.ts +146 -0
  850. package/src/shared/model-info.ts +94 -58
  851. package/src/shared/native-import.ts +25 -0
  852. package/src/shared/native-journal.ts +172 -0
  853. package/src/shared/native-session.ts +8 -3
  854. package/src/shared/native-tui.ts +13 -3
  855. package/src/shared/native-typebox.ts +18 -3
  856. package/src/shared/output-page.ts +76 -0
  857. package/src/shared/post-exit-stdio-guard.ts +232 -172
  858. package/src/shared/prompt-sections.ts +13 -7
  859. package/src/shared/session-entries.ts +103 -44
  860. package/src/shared/session-identity.ts +17 -10
  861. package/src/shared/settings.ts +182 -367
  862. package/src/shared/status-format.ts +207 -98
  863. package/src/shared/stream-json.d.ts +10 -0
  864. package/src/shared/task-file-policy.ts +35 -0
  865. package/src/shared/temp-root.ts +122 -71
  866. package/src/shared/types/acceptance.ts +149 -0
  867. package/src/shared/types/async.ts +247 -0
  868. package/src/shared/types/config.ts +139 -0
  869. package/src/shared/types/details.ts +104 -0
  870. package/src/shared/types/history.ts +217 -0
  871. package/src/shared/types/inputs.ts +4 -0
  872. package/src/shared/types/intercom.ts +57 -0
  873. package/src/shared/types/launch.ts +39 -0
  874. package/src/shared/types/messages.ts +104 -0
  875. package/src/shared/types/nested.ts +153 -0
  876. package/src/shared/types/owned-runs.ts +148 -0
  877. package/src/shared/types/progress.ts +106 -0
  878. package/src/shared/types/questions.ts +103 -0
  879. package/src/shared/types/results.ts +119 -0
  880. package/src/shared/types/state.ts +56 -0
  881. package/src/shared/types/usage.ts +36 -0
  882. package/src/shared/types/workflow.ts +187 -0
  883. package/src/shared/types.ts +222 -1161
  884. package/src/shared/ui-mode.ts +1 -1
  885. package/src/shared/unknown.ts +59 -0
  886. package/src/shared/utils.ts +111 -305
  887. package/src/slash/command-discovery.ts +109 -0
  888. package/src/slash/command-input.ts +232 -0
  889. package/src/slash/prompt-template-bridge.ts +153 -400
  890. package/src/slash/prompt-template-contract.ts +152 -0
  891. package/src/slash/prompt-template-results.ts +189 -0
  892. package/src/slash/request-protocol.ts +87 -0
  893. package/src/slash/result-delivery.ts +312 -0
  894. package/src/slash/saved-chain.ts +115 -0
  895. package/src/slash/slash-bridge.ts +202 -156
  896. package/src/slash/slash-commands.ts +176 -598
  897. package/src/slash/slash-live-state.ts +287 -229
  898. package/src/tui/action-hints.ts +147 -61
  899. package/src/tui/activity-lines.ts +40 -0
  900. package/src/tui/agent-browser.ts +354 -0
  901. package/src/tui/agent-controls.ts +355 -0
  902. package/src/tui/agent-conversation.ts +514 -0
  903. package/src/tui/agent-dock.ts +250 -0
  904. package/src/tui/agent-history.ts +78 -203
  905. package/src/tui/agent-model.ts +78 -0
  906. package/src/tui/agent-picker.ts +325 -0
  907. package/src/tui/agent-view.ts +391 -1310
  908. package/src/tui/compact-results.ts +342 -0
  909. package/src/tui/conversation-details.ts +206 -0
  910. package/src/tui/conversation-frame.ts +184 -0
  911. package/src/tui/conversation-history.ts +246 -0
  912. package/src/tui/conversation-menu.ts +119 -0
  913. package/src/tui/conversation-notices.ts +116 -0
  914. package/src/tui/conversation-selection.ts +66 -0
  915. package/src/tui/conversation-viewport.ts +169 -0
  916. package/src/tui/direction-message.ts +35 -0
  917. package/src/tui/display.ts +409 -0
  918. package/src/tui/editor-viewport.ts +19 -0
  919. package/src/tui/expanded-content.ts +134 -0
  920. package/src/tui/expanded-multi.ts +264 -0
  921. package/src/tui/expanded-single.ts +92 -0
  922. package/src/tui/history-cards.ts +316 -0
  923. package/src/tui/history-display.ts +334 -0
  924. package/src/tui/history-json.ts +17 -0
  925. package/src/tui/history-metadata.ts +177 -0
  926. package/src/tui/history-record.ts +321 -0
  927. package/src/tui/history-text.ts +34 -0
  928. package/src/tui/indexed-history.ts +149 -0
  929. package/src/tui/nested-widget.ts +192 -0
  930. package/src/tui/picker-page.ts +80 -0
  931. package/src/tui/render.ts +100 -1546
  932. package/src/tui/result-facts.ts +99 -0
  933. package/src/tui/task-observation.ts +96 -0
  934. package/src/tui/task-store.ts +432 -0
  935. package/src/tui/text-values.ts +20 -0
  936. package/src/tui/view-connections.ts +64 -0
  937. package/src/tui/view-model.ts +181 -0
  938. package/src/tui/view-persistence.ts +57 -0
  939. package/src/tui/view-ports.ts +55 -0
  940. package/src/tui/view-session.ts +42 -0
  941. package/src/tui/widget-details.ts +220 -0
  942. package/src/tui/widget-status.ts +331 -0
  943. package/src/tui/widget.ts +208 -0
  944. package/src/tui/workflow-labels.ts +340 -0
  945. package/src/tui/workflow-outcomes.ts +150 -0
  946. package/tsconfig.build.json +11 -10
  947. package/tsconfig.json +30 -17
@@ -1,295 +1,459 @@
1
- import type { DynamicParallelStep, ParallelTaskItem } from "../../shared/settings.ts";
2
- import type { ArtifactPaths, ChainOutputMap, JsonSchemaObject, SingleResult } from "../../shared/types.ts";
1
+ import { isRecord, isUnknownArray, recordAt, type UnknownRecord } from "../../shared/unknown.ts";
2
+ import type { DynamicParallelStep, ParallelTaskItem } from "../../shared/types/workflow.ts";
3
+ import type {
4
+ ReadonlyInput,
5
+ ArtifactPaths,
6
+ ChainOutputMap,
7
+ JsonSchemaObject,
8
+ SingleResult,
9
+ } from "../../shared/types.ts";
3
10
  import { getSingleResultOutput } from "../../shared/utils.ts";
4
11
  import { validateStructuredOutputValue } from "./structured-output.ts";
5
12
 
6
- export class DynamicFanoutError extends Error {}
13
+ import {
14
+ DynamicFanoutError,
15
+ assertJsonPointer,
16
+ resolveJsonPointer,
17
+ scalarToKey,
18
+ normalizeItemKeyForId,
19
+ resolveItemTemplate,
20
+ } from "./dynamic-item.ts";
21
+ export {
22
+ DynamicFanoutError,
23
+ assertJsonPointer,
24
+ resolveJsonPointer,
25
+ normalizeItemKeyForId,
26
+ resolveItemTemplate,
27
+ } from "./dynamic-item.ts";
7
28
 
8
29
  export interface DynamicFanoutConfig {
9
- maxItems?: number;
10
- allowRunnerFields?: boolean;
30
+ readonly maxItems?: number;
31
+ readonly allowRunnerFields?: boolean;
11
32
  }
12
33
 
13
34
  export interface DynamicMaterializedItem {
14
- index: number;
15
- key: string;
16
- idKey: string;
17
- item: unknown;
35
+ readonly index: number;
36
+ readonly key: string;
37
+ readonly idKey: string;
38
+ readonly item: unknown;
18
39
  }
19
40
 
20
41
  export interface DynamicCollectedResult {
21
- key: string;
22
- index: number;
23
- item: unknown;
24
- agent: string;
25
- exitCode: number | null;
26
- text: string;
27
- structured?: unknown;
28
- error?: string;
29
- outputPath?: string;
30
- artifactPaths?: ArtifactPaths;
42
+ key: string;
43
+ index: number;
44
+ item: unknown;
45
+ agent: string;
46
+ exitCode: number | null;
47
+ text: string;
48
+ structured?: unknown;
49
+ error?: string;
50
+ outputPath?: string;
51
+ artifactPaths?: ArtifactPaths;
31
52
  }
32
53
 
33
54
  export interface DynamicMaterializedGroup {
34
- items: DynamicMaterializedItem[];
35
- parallel: ParallelTaskItem[];
55
+ items: DynamicMaterializedItem[];
56
+ parallel: ParallelTaskItem[];
36
57
  }
37
58
 
38
59
  const SAFE_OUTPUT_NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
39
60
  const ITEM_NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
40
61
  const ITEM_REF_PATTERN = /\{([A-Za-z_][A-Za-z0-9_]*)(?:\.([^{}]+))?\}/g;
41
62
  const RESERVED_TEMPLATE_NAMES = new Set(["task", "previous", "chain_dir", "outputs"]);
42
- const DYNAMIC_STEP_KEYS = new Set(["expand", "parallel", "collect", "concurrency", "failFast", "phase", "label", "acceptance"]);
43
- const RUNNER_DYNAMIC_STEP_KEYS = new Set([...DYNAMIC_STEP_KEYS, "effectiveAcceptance", "sessionFiles"]);
44
- const DYNAMIC_EXPAND_KEYS = new Set(["from", "item", "key", "maxItems", "onEmpty"]);
45
- const DYNAMIC_EXPAND_FROM_KEYS = new Set(["output", "path"]);
46
- const DYNAMIC_PARALLEL_KEYS = new Set(["agent", "task", "phase", "label", "outputSchema", "cwd", "output", "outputMode", "reads", "progress", "skill", "model", "acceptance"]);
47
- const RUNNER_DYNAMIC_PARALLEL_KEYS = new Set([
48
- ...DYNAMIC_PARALLEL_KEYS,
49
- "outputName", "structured", "inheritProjectContext", "inheritSkills", "skills", "outputPath", "outputPathFromAgentDefault", "allowSubagents", "maxSubagentDepth",
50
- "structuredOutput", "structuredOutputSchema", "tools", "extensions", "mcpDirectTools", "completionGuard", "systemPrompt",
51
- "systemPromptMode", "thinking", "modelCandidates", "sessionFile", "effectiveAcceptance", "maxExecutionTimeMs", "maxTokens", "launch",
52
- ]);
53
- const DYNAMIC_COLLECT_KEYS = new Set(["as", "outputSchema"]);
63
+ const DYNAMIC_STEP_KEYS = [
64
+ "expand",
65
+ "parallel",
66
+ "collect",
67
+ "concurrency",
68
+ "failFast",
69
+ "phase",
70
+ "label",
71
+ "acceptance",
72
+ ];
73
+ const RUNNER_DYNAMIC_STEP_KEYS = [...DYNAMIC_STEP_KEYS, "effectiveAcceptance", "sessionFiles"];
74
+ const DYNAMIC_EXPAND_KEYS = ["from", "item", "key", "maxItems", "onEmpty"];
75
+ const DYNAMIC_EXPAND_FROM_KEYS = ["output", "path"];
76
+ const DYNAMIC_PARALLEL_KEYS = [
77
+ "agent",
78
+ "task",
79
+ "phase",
80
+ "label",
81
+ "outputSchema",
82
+ "cwd",
83
+ "output",
84
+ "outputMode",
85
+ "reads",
86
+ "progress",
87
+ "skill",
88
+ "model",
89
+ "acceptance",
90
+ ];
91
+ const RUNNER_DYNAMIC_PARALLEL_KEYS = [
92
+ ...DYNAMIC_PARALLEL_KEYS,
93
+ "outputName",
94
+ "structured",
95
+ "inheritProjectContext",
96
+ "inheritSkills",
97
+ "skills",
98
+ "outputPath",
99
+ "outputPathFromAgentDefault",
100
+ "allowSubagents",
101
+ "maxSubagentDepth",
102
+ "structuredOutput",
103
+ "structuredOutputSchema",
104
+ "tools",
105
+ "extensions",
106
+ "mcpDirectTools",
107
+ "completionGuard",
108
+ "systemPrompt",
109
+ "systemPromptMode",
110
+ "thinking",
111
+ "modelCandidates",
112
+ "sessionFile",
113
+ "effectiveAcceptance",
114
+ "maxExecutionTimeMs",
115
+ "maxTokens",
116
+ "launch",
117
+ ];
118
+ const DYNAMIC_COLLECT_KEYS = ["as", "outputSchema"];
54
119
 
55
120
  export function isSafeOutputName(name: string): boolean {
56
- return SAFE_OUTPUT_NAME_PATTERN.test(name);
121
+ return SAFE_OUTPUT_NAME_PATTERN.test(name);
57
122
  }
58
123
 
59
- export function assertJsonPointer(pointer: string, label: string): void {
60
- if (pointer === "") return;
61
- if (!pointer.startsWith("/")) {
62
- throw new DynamicFanoutError(`${label} must be a JSON Pointer starting with '/'.`);
63
- }
64
- for (const segment of pointer.slice(1).split("/")) {
65
- if (/~(?![01])/.test(segment)) {
66
- throw new DynamicFanoutError(`${label} contains invalid JSON Pointer escape.`);
67
- }
68
- }
124
+ function validateObjectKeys(
125
+ value: unknown,
126
+ allowed: readonly string[],
127
+ label: string,
128
+ ): UnknownRecord {
129
+ if (!isRecord(value)) {
130
+ throw new DynamicFanoutError(`${label} must be an object.`);
131
+ }
132
+ for (const key of Object.keys(value)) {
133
+ if (!allowed.includes(key)) {
134
+ throw new DynamicFanoutError(`${label} does not support field '${key}'.`);
135
+ }
136
+ }
137
+ return value;
69
138
  }
70
139
 
71
- function decodePointerSegment(segment: string): string {
72
- return segment.replace(/~1/g, "/").replace(/~0/g, "~");
140
+ const VALID_ITEM_REF_PATTERN = new RegExp(ITEM_REF_PATTERN.source);
141
+
142
+ function validateTemplateReference(
143
+ raw: string,
144
+ reference: string,
145
+ itemName: string,
146
+ label: string,
147
+ ): void {
148
+ if (reference === itemName || reference.startsWith(`${itemName}.`)) {
149
+ if (
150
+ !VALID_ITEM_REF_PATTERN.test(raw) ||
151
+ reference === `${itemName}.` ||
152
+ reference.includes("..")
153
+ ) {
154
+ throw new DynamicFanoutError(`Invalid item reference '${raw}' in ${label}.`);
155
+ }
156
+ return;
157
+ }
158
+ const name = reference.match(/^[A-Za-z_][A-Za-z0-9_]*/)?.[0];
159
+ if (name === itemName) {
160
+ throw new DynamicFanoutError(`Invalid item reference '${raw}' in ${label}.`);
161
+ }
162
+ if (name === undefined || RESERVED_TEMPLATE_NAMES.has(name)) {
163
+ return;
164
+ }
165
+ throw new DynamicFanoutError(`Unsupported template reference '${raw}' in ${label}.`);
73
166
  }
74
167
 
75
- export function resolveJsonPointer(value: unknown, pointer: string, label: string): unknown {
76
- assertJsonPointer(pointer, label);
77
- if (pointer === "") return value;
78
- let current = value;
79
- for (const rawSegment of pointer.slice(1).split("/")) {
80
- const segment = decodePointerSegment(rawSegment);
81
- if (Array.isArray(current)) {
82
- if (!/^(0|[1-9][0-9]*)$/.test(segment)) {
83
- throw new DynamicFanoutError(`${label} segment '${segment}' does not address an array index.`);
84
- }
85
- const index = Number(segment);
86
- if (index >= current.length) throw new DynamicFanoutError(`${label} does not exist.`);
87
- current = current[index];
88
- continue;
89
- }
90
- if (!current || typeof current !== "object") {
91
- throw new DynamicFanoutError(`${label} does not exist.`);
92
- }
93
- const record = current as Record<string, unknown>;
94
- if (!Object.prototype.hasOwnProperty.call(record, segment)) {
95
- throw new DynamicFanoutError(`${label} does not exist.`);
96
- }
97
- current = record[segment];
98
- }
99
- return current;
168
+ export function assertNoUnresolvedItemReferences(
169
+ template: string,
170
+ itemName: string,
171
+ label: string,
172
+ ): void {
173
+ for (const match of template.matchAll(/\{([^{}]*)\}/g)) {
174
+ validateTemplateReference(match[0], match[1], itemName, label);
175
+ }
176
+ if (
177
+ template.includes(`{${itemName}.}`) ||
178
+ new RegExp(`\\{${itemName}(?:\\.|$)[^}]*$`).test(template)
179
+ ) {
180
+ throw new DynamicFanoutError(`Invalid item reference in ${label}.`);
181
+ }
100
182
  }
101
183
 
102
- function scalarToKey(value: unknown, label: string): string {
103
- if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
104
- const key = String(value);
105
- if (!key.trim()) throw new DynamicFanoutError(`${label} resolved to an empty key.`);
106
- if (/[\u0000-\u001F\u007F]/.test(key)) throw new DynamicFanoutError(`${label} resolved to an unsafe key.`);
107
- if (key.length > 200) throw new DynamicFanoutError(`${label} resolved to a key longer than 200 characters.`);
108
- return key;
109
- }
110
- throw new DynamicFanoutError(`${label} must resolve to a string, number, or boolean.`);
184
+ export function hasDynamicFanoutFields(step: unknown): boolean {
185
+ return (
186
+ isRecord(step) &&
187
+ (Object.prototype.hasOwnProperty.call(step, "expand") ||
188
+ Object.prototype.hasOwnProperty.call(step, "collect"))
189
+ );
111
190
  }
112
191
 
113
- export function normalizeItemKeyForId(key: string): string {
114
- const normalized = key
115
- .toLowerCase()
116
- .replace(/[^a-z0-9]+/g, "-")
117
- .replace(/^-+|-+$/g, "")
118
- .slice(0, 80);
119
- return normalized || "item";
192
+ function requireString(value: unknown, label: string): string {
193
+ if (typeof value !== "string") {
194
+ throw new DynamicFanoutError(`${label} must be a string.`);
195
+ }
196
+ return value;
120
197
  }
121
198
 
122
- function valueToTemplateText(value: unknown, reference: string): string {
123
- if (value === undefined) throw new DynamicFanoutError(`Unresolved item reference '${reference}'.`);
124
- if (typeof value === "string") return value;
125
- if (typeof value === "number" || typeof value === "boolean" || value === null) return String(value);
126
- return JSON.stringify(value);
199
+ function validateItemLimit(value: unknown, label: string): void {
200
+ if (value !== undefined && (typeof value !== "number" || !Number.isInteger(value) || value < 0)) {
201
+ throw new DynamicFanoutError(`${label} must be an integer >= 0.`);
202
+ }
127
203
  }
128
204
 
129
- function resolveItemPath(item: unknown, pathText: string | undefined, reference: string): unknown {
130
- if (!pathText) return item;
131
- const pointer = `/${pathText.split(".").map((segment) => segment.replace(/~/g, "~0").replace(/\//g, "~1")).join("/")}`;
132
- return resolveJsonPointer(item, pointer, reference);
205
+ function validateExpandFrom(from: UnknownRecord, prefix: string): void {
206
+ validateObjectKeys(from, DYNAMIC_EXPAND_FROM_KEYS, `${prefix} expand.from`);
207
+ const output = requireString(from.output, `${prefix} expand.from.output`);
208
+ if (!isSafeOutputName(output)) {
209
+ throw new DynamicFanoutError(`${prefix} has invalid expand.from.output '${output}'.`);
210
+ }
211
+ assertJsonPointer(
212
+ requireString(from.path, `${prefix} expand.from.path`),
213
+ `${prefix} expand.from.path`,
214
+ );
133
215
  }
134
216
 
135
- export function resolveItemTemplate(template: string, itemName: string, item: unknown): string {
136
- return template.replace(ITEM_REF_PATTERN, (raw, name: string, pathText: string | undefined) => {
137
- if (name !== itemName) return raw;
138
- if (pathText !== undefined && (!pathText.trim() || pathText.includes(".."))) {
139
- throw new DynamicFanoutError(`Invalid item reference '${raw}'.`);
140
- }
141
- return valueToTemplateText(resolveItemPath(item, pathText, raw), raw);
142
- });
217
+ function validateExpansion(expand: unknown, prefix: string, config: DynamicFanoutConfig): string {
218
+ const from = recordAt(expand, "from");
219
+ if (!isRecord(expand) || !from) {
220
+ throw new DynamicFanoutError(`${prefix} requires expand.from.`);
221
+ }
222
+ validateObjectKeys(expand, DYNAMIC_EXPAND_KEYS, `${prefix} expand`);
223
+ validateExpandFrom(from, prefix);
224
+ if (expand.key !== undefined) {
225
+ assertJsonPointer(requireString(expand.key, `${prefix} expand.key`), `${prefix} expand.key`);
226
+ }
227
+ const itemName = requireString(expand.item ?? "item", `${prefix} expand.item`);
228
+ if (!ITEM_NAME_PATTERN.test(itemName)) {
229
+ throw new DynamicFanoutError(`${prefix} has invalid expand.item '${itemName}'.`);
230
+ }
231
+ if (expand.maxItems === undefined && config.maxItems === undefined) {
232
+ throw new DynamicFanoutError(
233
+ `${prefix} requires expand.maxItems or config.chain.dynamicFanout.maxItems.`,
234
+ );
235
+ }
236
+ validateItemLimit(expand.maxItems, `${prefix} expand.maxItems`);
237
+ validateItemLimit(config.maxItems, "config.chain.dynamicFanout.maxItems");
238
+ return itemName;
143
239
  }
144
240
 
145
- function assertOnlyKeys(value: unknown, allowed: Set<string>, label: string): void {
146
- if (!value || typeof value !== "object" || Array.isArray(value)) throw new DynamicFanoutError(`${label} must be an object.`);
147
- for (const key of Object.keys(value)) {
148
- if (!allowed.has(key)) throw new DynamicFanoutError(`${label} does not support field '${key}'.`);
149
- }
241
+ function validateParallelTemplate(
242
+ parallel: unknown,
243
+ prefix: string,
244
+ itemName: string,
245
+ runnerFields: boolean,
246
+ ): void {
247
+ if (!isRecord(parallel)) {
248
+ throw new DynamicFanoutError(
249
+ `${prefix} requires a single parallel template object and cannot mix dynamic expand/collect with static parallel arrays.`,
250
+ );
251
+ }
252
+ validateObjectKeys(
253
+ parallel,
254
+ runnerFields ? RUNNER_DYNAMIC_PARALLEL_KEYS : DYNAMIC_PARALLEL_KEYS,
255
+ `${prefix} parallel`,
256
+ );
257
+ if ("expand" in parallel) {
258
+ throw new DynamicFanoutError(`${prefix} does not support nested dynamic fanout.`);
259
+ }
260
+ if (typeof parallel.agent !== "string" || parallel.agent.length === 0) {
261
+ throw new DynamicFanoutError(`${prefix} parallel.agent is required.`);
262
+ }
263
+ for (const [label, value] of [
264
+ ["parallel.task", parallel.task],
265
+ ["parallel.label", parallel.label],
266
+ ] as const) {
267
+ if (value === undefined) {
268
+ continue;
269
+ }
270
+ const template = requireString(value, `${prefix} ${label}`);
271
+ if (template.length > 0) {
272
+ assertNoUnresolvedItemReferences(template, itemName, `${prefix} ${label}`);
273
+ }
274
+ }
150
275
  }
151
276
 
152
- export function assertNoUnresolvedItemReferences(template: string, itemName: string, label: string): void {
153
- for (const match of template.matchAll(/\{([^{}]*)\}/g)) {
154
- const raw = match[0]!;
155
- const reference = match[1]!;
156
- if (reference === itemName || reference.startsWith(`${itemName}.`)) {
157
- if (!ITEM_REF_PATTERN.test(raw) || reference === `${itemName}.` || reference.includes("..")) {
158
- throw new DynamicFanoutError(`Invalid item reference '${raw}' in ${label}.`);
159
- }
160
- ITEM_REF_PATTERN.lastIndex = 0;
161
- continue;
162
- }
163
- ITEM_REF_PATTERN.lastIndex = 0;
164
- const name = reference.match(/^[A-Za-z_][A-Za-z0-9_]*/)?.[0];
165
- if (name === itemName) throw new DynamicFanoutError(`Invalid item reference '${raw}' in ${label}.`);
166
- if (name && RESERVED_TEMPLATE_NAMES.has(name)) continue;
167
- if (name) throw new DynamicFanoutError(`Unsupported template reference '${raw}' in ${label}.`);
168
- }
169
- ITEM_REF_PATTERN.lastIndex = 0;
170
- if (template.includes(`{${itemName}.}`) || new RegExp(`\\{${itemName}(?:\\.|$)[^}]*$`).test(template)) {
171
- throw new DynamicFanoutError(`Invalid item reference in ${label}.`);
172
- }
277
+ function validateCollection(collect: unknown, prefix: string): void {
278
+ if (!isRecord(collect) || typeof collect.as !== "string" || !isSafeOutputName(collect.as)) {
279
+ throw new DynamicFanoutError(`${prefix} requires collect.as with a safe output name.`);
280
+ }
281
+ validateObjectKeys(collect, DYNAMIC_COLLECT_KEYS, `${prefix} collect`);
173
282
  }
174
283
 
175
- export function hasDynamicFanoutFields(step: unknown): boolean {
176
- return !!step && typeof step === "object" && !Array.isArray(step)
177
- && (Object.prototype.hasOwnProperty.call(step, "expand") || Object.prototype.hasOwnProperty.call(step, "collect"));
284
+ /** Validates dynamic vocabulary and expansion semantics, not the entire child execution schema. */
285
+ export function validateDynamicStepShape(
286
+ step: unknown,
287
+ stepIndex: number,
288
+ config: DynamicFanoutConfig = {},
289
+ ): void {
290
+ const prefix = `Dynamic chain step ${stepIndex + 1}`;
291
+ if (
292
+ isRecord(step) &&
293
+ (Object.hasOwn(step, "acceptance") || Object.hasOwn(step, "effectiveAcceptance"))
294
+ ) {
295
+ throw new DynamicFanoutError(
296
+ `Dynamic fanout step ${stepIndex + 1} does not support group-level acceptance; set acceptance on the child template instead.`,
297
+ );
298
+ }
299
+ const record = validateObjectKeys(
300
+ step,
301
+ config.allowRunnerFields === true ? RUNNER_DYNAMIC_STEP_KEYS : DYNAMIC_STEP_KEYS,
302
+ prefix,
303
+ );
304
+ const itemName = validateExpansion(record.expand, prefix, config);
305
+ validateParallelTemplate(record.parallel, prefix, itemName, config.allowRunnerFields === true);
306
+ validateCollection(record.collect, prefix);
178
307
  }
179
308
 
180
- export function validateDynamicStepShape(step: DynamicParallelStep, stepIndex: number, config: DynamicFanoutConfig = {}): void {
181
- const prefix = `Dynamic chain step ${stepIndex + 1}`;
182
- if (Object.hasOwn(step, "acceptance") || Object.hasOwn(step, "effectiveAcceptance")) {
183
- throw new DynamicFanoutError(`Dynamic fanout step ${stepIndex + 1} does not support group-level acceptance; set acceptance on the child template instead.`);
184
- }
185
- assertOnlyKeys(step, config.allowRunnerFields ? RUNNER_DYNAMIC_STEP_KEYS : DYNAMIC_STEP_KEYS, prefix);
186
- if (!step.expand || !step.expand.from) throw new DynamicFanoutError(`${prefix} requires expand.from.`);
187
- assertOnlyKeys(step.expand, DYNAMIC_EXPAND_KEYS, `${prefix} expand`);
188
- assertOnlyKeys(step.expand.from, DYNAMIC_EXPAND_FROM_KEYS, `${prefix} expand.from`);
189
- if (!isSafeOutputName(step.expand.from.output)) throw new DynamicFanoutError(`${prefix} has invalid expand.from.output '${step.expand.from.output}'.`);
190
- assertJsonPointer(step.expand.from.path, `${prefix} expand.from.path`);
191
- if (step.expand.key !== undefined) assertJsonPointer(step.expand.key, `${prefix} expand.key`);
192
- const itemName = step.expand.item ?? "item";
193
- if (!ITEM_NAME_PATTERN.test(itemName)) throw new DynamicFanoutError(`${prefix} has invalid expand.item '${itemName}'.`);
194
- if (step.expand.maxItems === undefined && config.maxItems === undefined) {
195
- throw new DynamicFanoutError(`${prefix} requires expand.maxItems or config.chain.dynamicFanout.maxItems.`);
196
- }
197
- if (step.expand.maxItems !== undefined && (!Number.isInteger(step.expand.maxItems) || step.expand.maxItems < 0)) {
198
- throw new DynamicFanoutError(`${prefix} expand.maxItems must be an integer >= 0.`);
199
- }
200
- if (config.maxItems !== undefined && (!Number.isInteger(config.maxItems) || config.maxItems < 0)) {
201
- throw new DynamicFanoutError("config.chain.dynamicFanout.maxItems must be an integer >= 0.");
202
- }
203
- if (!step.parallel || Array.isArray(step.parallel)) throw new DynamicFanoutError(`${prefix} requires a single parallel template object and cannot mix dynamic expand/collect with static parallel arrays.`);
204
- assertOnlyKeys(step.parallel, config.allowRunnerFields ? RUNNER_DYNAMIC_PARALLEL_KEYS : DYNAMIC_PARALLEL_KEYS, `${prefix} parallel`);
205
- if ("expand" in (step.parallel as object)) throw new DynamicFanoutError(`${prefix} does not support nested dynamic fanout.`);
206
- if (!step.parallel.agent) throw new DynamicFanoutError(`${prefix} parallel.agent is required.`);
207
- if (!step.collect?.as || !isSafeOutputName(step.collect.as)) throw new DynamicFanoutError(`${prefix} requires collect.as with a safe output name.`);
208
- assertOnlyKeys(step.collect, DYNAMIC_COLLECT_KEYS, `${prefix} collect`);
209
- for (const [label, template] of [
210
- ["parallel.task", step.parallel.task],
211
- ["parallel.label", step.parallel.label],
212
- ] as const) {
213
- if (template) assertNoUnresolvedItemReferences(template, itemName, `${prefix} ${label}`);
214
- }
309
+ export function resolveDynamicFanoutItems(
310
+ step: ReadonlyInput<DynamicParallelStep>,
311
+ outputs: ReadonlyInput<ChainOutputMap>,
312
+ stepIndex: number,
313
+ config: DynamicFanoutConfig = {},
314
+ ): DynamicMaterializedItem[] {
315
+ validateDynamicStepShape(step, stepIndex, config);
316
+ const sourceName = step.expand.from.output;
317
+ const source = outputs[sourceName];
318
+ if (!Object.hasOwn(outputs, sourceName)) {
319
+ throw new DynamicFanoutError(
320
+ `Dynamic chain step ${stepIndex + 1} references unknown output '${sourceName}'.`,
321
+ );
322
+ }
323
+ if (source.structured === undefined) {
324
+ throw new DynamicFanoutError(
325
+ `Dynamic chain step ${stepIndex + 1} requires structured output '${sourceName}'.`,
326
+ );
327
+ }
328
+ const value = resolveJsonPointer(
329
+ source.structured,
330
+ step.expand.from.path,
331
+ `Dynamic chain step ${stepIndex + 1} expand.from.path`,
332
+ );
333
+ if (!isUnknownArray(value)) {
334
+ throw new DynamicFanoutError(
335
+ `Dynamic chain step ${stepIndex + 1} expand.from.path must resolve to an array.`,
336
+ );
337
+ }
338
+ const maxItems = step.expand.maxItems ?? config.maxItems;
339
+ if (maxItems === undefined) {
340
+ throw new DynamicFanoutError(
341
+ `Dynamic chain step ${stepIndex + 1} requires an effective maxItems.`,
342
+ );
343
+ }
344
+ if (value.length > maxItems) {
345
+ throw new DynamicFanoutError(
346
+ `Dynamic chain step ${stepIndex + 1} resolved ${value.length} items, exceeding maxItems ${maxItems}.`,
347
+ );
348
+ }
349
+ const seen = new Set<string>();
350
+ const seenIds = new Set<string>();
351
+ return value.map((item: unknown, index) => {
352
+ const key =
353
+ step.expand.key === undefined
354
+ ? String(index)
355
+ : scalarToKey(
356
+ resolveJsonPointer(
357
+ item,
358
+ step.expand.key,
359
+ `Dynamic chain step ${stepIndex + 1} expand.key`,
360
+ ),
361
+ `Dynamic chain step ${stepIndex + 1} expand.key`,
362
+ );
363
+ if (seen.has(key)) {
364
+ throw new DynamicFanoutError(
365
+ `Dynamic chain step ${stepIndex + 1} produced duplicate item key '${key}'.`,
366
+ );
367
+ }
368
+ seen.add(key);
369
+ const idKey = normalizeItemKeyForId(key);
370
+ if (seenIds.has(idKey)) {
371
+ throw new DynamicFanoutError(
372
+ `Dynamic chain step ${stepIndex + 1} produced colliding item id '${idKey}'.`,
373
+ );
374
+ }
375
+ seenIds.add(idKey);
376
+ return { index, key, idKey, item };
377
+ });
215
378
  }
216
379
 
217
- export function resolveDynamicFanoutItems(step: DynamicParallelStep, outputs: ChainOutputMap, stepIndex: number, config: DynamicFanoutConfig = {}): DynamicMaterializedItem[] {
218
- validateDynamicStepShape(step, stepIndex, config);
219
- const sourceName = step.expand.from.output;
220
- const source = outputs[sourceName];
221
- if (!source) throw new DynamicFanoutError(`Dynamic chain step ${stepIndex + 1} references unknown output '${sourceName}'.`);
222
- if (source.structured === undefined) throw new DynamicFanoutError(`Dynamic chain step ${stepIndex + 1} requires structured output '${sourceName}'.`);
223
- const value = resolveJsonPointer(source.structured, step.expand.from.path, `Dynamic chain step ${stepIndex + 1} expand.from.path`);
224
- if (!Array.isArray(value)) throw new DynamicFanoutError(`Dynamic chain step ${stepIndex + 1} expand.from.path must resolve to an array.`);
225
- const maxItems = step.expand.maxItems ?? config.maxItems;
226
- if (maxItems === undefined) throw new DynamicFanoutError(`Dynamic chain step ${stepIndex + 1} requires an effective maxItems.`);
227
- if (value.length > maxItems) throw new DynamicFanoutError(`Dynamic chain step ${stepIndex + 1} resolved ${value.length} items, exceeding maxItems ${maxItems}.`);
228
- const seen = new Set<string>();
229
- const seenIds = new Set<string>();
230
- return value.map((item, index) => {
231
- const key = step.expand.key === undefined
232
- ? String(index)
233
- : scalarToKey(resolveJsonPointer(item, step.expand.key, `Dynamic chain step ${stepIndex + 1} expand.key`), `Dynamic chain step ${stepIndex + 1} expand.key`);
234
- if (seen.has(key)) throw new DynamicFanoutError(`Dynamic chain step ${stepIndex + 1} produced duplicate item key '${key}'.`);
235
- seen.add(key);
236
- const idKey = normalizeItemKeyForId(key);
237
- if (seenIds.has(idKey)) throw new DynamicFanoutError(`Dynamic chain step ${stepIndex + 1} produced colliding item id '${idKey}'.`);
238
- seenIds.add(idKey);
239
- return { index, key, idKey, item };
240
- });
380
+ export function materializeDynamicParallelStep(
381
+ step: ReadonlyInput<DynamicParallelStep>,
382
+ outputs: ReadonlyInput<ChainOutputMap>,
383
+ stepIndex: number,
384
+ config: DynamicFanoutConfig = {},
385
+ ): DynamicMaterializedGroup {
386
+ const items = resolveDynamicFanoutItems(step, outputs, stepIndex, config);
387
+ if (items.length === 0) {
388
+ if ((step.expand.onEmpty ?? "skip") === "fail") {
389
+ throw new DynamicFanoutError(`Dynamic chain step ${stepIndex + 1} source array is empty.`);
390
+ }
391
+ return { items, parallel: [] };
392
+ }
393
+ const itemName = step.expand.item ?? "item";
394
+ const parallel = items.map((entry) => {
395
+ const task = resolveItemTemplate(step.parallel.task ?? "{previous}", itemName, entry.item);
396
+ const label =
397
+ (step.parallel.label ?? "").length > 0
398
+ ? resolveItemTemplate(step.parallel.label ?? "", itemName, entry.item)
399
+ : undefined;
400
+ return {
401
+ ...step.parallel,
402
+ task,
403
+ ...(label !== undefined ? { label } : {}),
404
+ };
405
+ });
406
+ return { items, parallel };
407
+ }
408
+
409
+ type CollectionChild = ReadonlyInput<
410
+ Pick<
411
+ SingleResult,
412
+ "agent" | "error" | "structuredOutput" | "artifactPaths" | "savedOutputPath" | "messages"
413
+ > & { exitCode: number | null; output?: string; finalOutput?: string }
414
+ >;
415
+
416
+ function collectionText(result: CollectionChild): string {
417
+ return typeof result.output === "string" ? result.output : getSingleResultOutput(result);
241
418
  }
242
419
 
243
- export function materializeDynamicParallelStep(step: DynamicParallelStep, outputs: ChainOutputMap, stepIndex: number, config: DynamicFanoutConfig = {}): DynamicMaterializedGroup {
244
- const items = resolveDynamicFanoutItems(step, outputs, stepIndex, config);
245
- if (items.length === 0) {
246
- if ((step.expand.onEmpty ?? "skip") === "fail") {
247
- throw new DynamicFanoutError(`Dynamic chain step ${stepIndex + 1} source array is empty.`);
248
- }
249
- return { items, parallel: [] };
250
- }
251
- const itemName = step.expand.item ?? "item";
252
- const parallel = items.map((entry) => {
253
- const task = resolveItemTemplate(step.parallel.task ?? "{previous}", itemName, entry.item);
254
- const label = step.parallel.label ? resolveItemTemplate(step.parallel.label, itemName, entry.item) : undefined;
255
- return {
256
- ...step.parallel,
257
- task,
258
- ...(label !== undefined ? { label } : {}),
259
- };
260
- });
261
- return { items, parallel };
420
+ function collectionMetadata(result: CollectionChild): Partial<DynamicCollectedResult> {
421
+ return {
422
+ ...(result.structuredOutput !== undefined ? { structured: result.structuredOutput } : {}),
423
+ ...((result.error ?? "").length > 0 ? { error: result.error } : {}),
424
+ ...((result.savedOutputPath ?? "").length > 0 ? { outputPath: result.savedOutputPath } : {}),
425
+ ...(result.artifactPaths ? { artifactPaths: result.artifactPaths } : {}),
426
+ };
262
427
  }
263
428
 
264
429
  export function collectDynamicResults(
265
- step: DynamicParallelStep,
266
- items: DynamicMaterializedItem[],
267
- results: Array<Pick<SingleResult, "agent" | "error" | "structuredOutput" | "artifactPaths" | "savedOutputPath"> & { exitCode: number | null; output?: string; finalOutput?: string }>,
430
+ step: ReadonlyInput<DynamicParallelStep>,
431
+ items: readonly DynamicMaterializedItem[],
432
+ results: readonly CollectionChild[],
268
433
  ): DynamicCollectedResult[] {
269
- return items.map((entry, index) => {
270
- const result = results[index];
271
- const text = result
272
- ? ("output" in result && typeof result.output === "string" ? result.output : getSingleResultOutput(result as SingleResult))
273
- : "";
274
- return {
275
- key: entry.key,
276
- index: entry.index,
277
- item: entry.item,
278
- agent: result?.agent ?? step.parallel.agent,
279
- exitCode: result?.exitCode ?? null,
280
- text,
281
- ...(result?.structuredOutput !== undefined ? { structured: result.structuredOutput } : {}),
282
- ...(result?.error ? { error: result.error } : {}),
283
- ...(result?.savedOutputPath ? { outputPath: result.savedOutputPath } : {}),
284
- ...(result?.artifactPaths ? { artifactPaths: result.artifactPaths } : {}),
285
- };
286
- });
434
+ return items.map((entry, index) => {
435
+ const result = Object.hasOwn(results, index) ? results[index] : undefined;
436
+ return {
437
+ key: entry.key,
438
+ index: entry.index,
439
+ item: entry.item,
440
+ agent: result?.agent ?? step.parallel.agent,
441
+ exitCode: result?.exitCode ?? null,
442
+ text: result ? collectionText(result) : "",
443
+ ...(result ? collectionMetadata(result) : {}),
444
+ };
445
+ });
287
446
  }
288
447
 
289
- export function validateDynamicCollection(schema: JsonSchemaObject | undefined, value: DynamicCollectedResult[]): void {
290
- if (!schema) return;
291
- const validation = validateStructuredOutputValue(schema, value);
292
- if (validation.status === "invalid") {
293
- throw new DynamicFanoutError(`Collected output validation failed: ${validation.message}`);
294
- }
448
+ export function validateDynamicCollection(
449
+ schema: ReadonlyInput<JsonSchemaObject> | undefined,
450
+ value: readonly ReadonlyInput<DynamicCollectedResult>[],
451
+ ): void {
452
+ if (!schema) {
453
+ return;
454
+ }
455
+ const validation = validateStructuredOutputValue(schema, value);
456
+ if (validation.status === "invalid") {
457
+ throw new DynamicFanoutError(`Collected output validation failed: ${validation.message}`);
458
+ }
295
459
  }