@selesai/code 0.8.3 → 0.8.4

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 (493) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/dist/extensions/handoff-new.ts +1 -1
  3. package/dist/extensions/inline-skills.test.ts +1 -0
  4. package/dist/extensions/inline-skills.ts +1 -1
  5. package/dist/extensions/pi-intercom/CHANGELOG.md +25 -3
  6. package/dist/extensions/pi-intercom/README.md +34 -15
  7. package/dist/extensions/pi-intercom/broker/broker.ts +38 -141
  8. package/dist/extensions/pi-intercom/broker/client-liveness.test.ts +173 -0
  9. package/dist/extensions/pi-intercom/broker/client.ts +78 -150
  10. package/dist/extensions/pi-intercom/broker/extension-state.ts +18 -7
  11. package/dist/extensions/pi-intercom/broker/framing.ts +1 -1
  12. package/dist/extensions/pi-intercom/broker/protocol.ts +182 -0
  13. package/dist/extensions/pi-intercom/broker/spawn.test.ts +106 -7
  14. package/dist/extensions/pi-intercom/broker/spawn.ts +37 -11
  15. package/dist/extensions/pi-intercom/config.test.ts +8 -10
  16. package/dist/extensions/pi-intercom/config.ts +3 -3
  17. package/dist/extensions/pi-intercom/index.ts +218 -147
  18. package/dist/extensions/pi-intercom/intercom.integration.test.ts +891 -103
  19. package/dist/extensions/pi-intercom/package.json +3 -2
  20. package/dist/extensions/pi-intercom/project-agent.test.ts +145 -0
  21. package/dist/extensions/pi-intercom/project-agent.ts +324 -0
  22. package/dist/extensions/pi-intercom/reply-tracker.test.ts +86 -1
  23. package/dist/extensions/pi-intercom/reply-tracker.ts +41 -9
  24. package/dist/extensions/pi-intercom/skills/pi-intercom/SKILL.md +49 -9
  25. package/dist/extensions/pi-intercom/test/inline-message.test.ts +9 -9
  26. package/dist/extensions/pi-intercom/types.ts +3 -1
  27. package/dist/extensions/pi-intercom/ui/inline-message.ts +7 -7
  28. package/dist/extensions/pi-powerline-footer/.github/workflows/test.yml +2 -2
  29. package/dist/extensions/pi-powerline-footer/CHANGELOG.md +14 -1
  30. package/dist/extensions/pi-powerline-footer/README.md +20 -37
  31. package/dist/extensions/pi-powerline-footer/bash-mode/completion.ts +40 -25
  32. package/dist/extensions/pi-powerline-footer/bash-mode/editor.ts +149 -18
  33. package/dist/extensions/pi-powerline-footer/bash-mode/types.ts +1 -0
  34. package/dist/extensions/pi-powerline-footer/editor-performance.ts +99 -0
  35. package/dist/extensions/pi-powerline-footer/git-status.ts +15 -0
  36. package/dist/extensions/pi-powerline-footer/index.ts +394 -317
  37. package/dist/extensions/pi-powerline-footer/package.json +1 -1
  38. package/dist/extensions/pi-powerline-footer/powerline-config.ts +0 -12
  39. package/dist/extensions/pi-powerline-footer/queue/store.ts +8 -56
  40. package/dist/extensions/pi-powerline-footer/queue/types.ts +1 -2
  41. package/dist/extensions/pi-powerline-footer/segments.ts +0 -3
  42. package/dist/extensions/pi-powerline-footer/tests/bash-mode.test.ts +231 -1
  43. package/dist/extensions/pi-powerline-footer/tests/custom-items.test.ts +5 -19
  44. package/dist/extensions/pi-powerline-footer/tests/editor-performance.test.ts +43 -0
  45. package/dist/extensions/pi-powerline-footer/tests/git-optional-locks.test.ts +64 -0
  46. package/dist/extensions/pi-powerline-footer/tests/jump-shortcuts.test.ts +116 -0
  47. package/dist/extensions/pi-powerline-footer/tests/queue-store.test.ts +19 -149
  48. package/dist/extensions/pi-powerline-footer/tests/remaining-regressions.test.ts +6 -0
  49. package/dist/extensions/pi-powerline-footer/tests/usage-display.test.ts +5 -5
  50. package/dist/extensions/pi-powerline-footer/types.ts +1 -2
  51. package/dist/extensions/pi-subagents/CHANGELOG.md +202 -14
  52. package/dist/extensions/pi-subagents/README.md +65 -1614
  53. package/dist/extensions/pi-subagents/agents/builder.md +0 -1
  54. package/dist/extensions/pi-subagents/agents/delegate.md +14 -0
  55. package/dist/extensions/pi-subagents/agents/oracle.md +74 -0
  56. package/dist/extensions/pi-subagents/agents/reviewer.md +78 -0
  57. package/dist/extensions/pi-subagents/agents/scout.md +50 -0
  58. package/dist/extensions/pi-subagents/agents/worker.md +58 -0
  59. package/dist/extensions/pi-subagents/docs/configuration.md +328 -0
  60. package/dist/extensions/pi-subagents/docs/extension-api.md +308 -0
  61. package/dist/extensions/pi-subagents/docs/missions.md +119 -0
  62. package/dist/extensions/pi-subagents/docs/models.md +192 -0
  63. package/dist/extensions/pi-subagents/docs/observability.md +174 -0
  64. package/dist/extensions/pi-subagents/docs/tool-reference.md +343 -0
  65. package/dist/extensions/pi-subagents/docs/watchdog.md +176 -0
  66. package/dist/extensions/pi-subagents/docs/workflows.md +163 -0
  67. package/dist/extensions/pi-subagents/inspector-runner.mjs +11 -0
  68. package/dist/extensions/pi-subagents/package-lock.json +152 -194
  69. package/dist/extensions/pi-subagents/package.json +9 -10
  70. package/dist/extensions/pi-subagents/prompts/gather-context-and-clarify.md +1 -1
  71. package/dist/extensions/pi-subagents/prompts/parallel-cleanup.md +9 -9
  72. package/dist/extensions/pi-subagents/prompts/parallel-research.md +6 -6
  73. package/dist/extensions/pi-subagents/prompts/parallel-review.md +8 -8
  74. package/dist/extensions/pi-subagents/prompts/review-loop.md +12 -12
  75. package/dist/extensions/pi-subagents/skills/pi-subagents/SKILL.md +22 -17
  76. package/dist/extensions/pi-subagents/skills/pi-subagents/references/constraints-and-recipes.md +77 -72
  77. package/dist/extensions/pi-subagents/skills/pi-subagents/references/execution-controls.md +177 -69
  78. package/dist/extensions/pi-subagents/skills/pi-subagents/references/management-authoring-rpc.md +28 -8
  79. package/dist/extensions/pi-subagents/skills/pi-subagents/references/prompting-and-roles.md +88 -66
  80. package/dist/extensions/pi-subagents/src/agents/agent-management.ts +3 -3
  81. package/dist/extensions/pi-subagents/src/agents/agent-refinements.ts +624 -0
  82. package/dist/extensions/pi-subagents/src/agents/agents.ts +29 -16
  83. package/dist/extensions/pi-subagents/src/agents/frontmatter.ts +7 -3
  84. package/dist/extensions/pi-subagents/src/agents/proactive-skills.ts +2 -2
  85. package/dist/extensions/pi-subagents/src/agents/skills.ts +2 -9
  86. package/dist/extensions/pi-subagents/src/api/delegation.ts +1 -2
  87. package/dist/extensions/pi-subagents/src/api/project-panes.ts +30 -0
  88. package/dist/extensions/pi-subagents/src/extension/config.ts +56 -8
  89. package/dist/extensions/pi-subagents/src/extension/control-notices.ts +2 -2
  90. package/dist/extensions/pi-subagents/src/extension/fanout-child.ts +51 -26
  91. package/dist/extensions/pi-subagents/src/extension/index.ts +119 -50
  92. package/dist/extensions/pi-subagents/src/extension/public-execution.ts +72 -0
  93. package/dist/extensions/pi-subagents/src/extension/rpc.ts +15 -15
  94. package/dist/extensions/pi-subagents/src/extension/schemas.ts +58 -21
  95. package/dist/extensions/pi-subagents/src/extension/subagent-guide.ts +39 -0
  96. package/dist/extensions/pi-subagents/src/extension/tool-description.ts +47 -25
  97. package/dist/extensions/pi-subagents/src/inspectors/herdr/actions.ts +3 -3
  98. package/dist/extensions/pi-subagents/src/inspectors/herdr/project-panes.ts +460 -64
  99. package/dist/extensions/pi-subagents/src/intercom/native-supervisor-channel.ts +102 -4
  100. package/dist/extensions/pi-subagents/src/missions/actions.ts +77 -16
  101. package/dist/extensions/pi-subagents/src/missions/goal-driver.ts +162 -0
  102. package/dist/extensions/pi-subagents/src/missions/lifecycle.ts +65 -14
  103. package/dist/extensions/pi-subagents/src/missions/store.ts +147 -5
  104. package/dist/extensions/pi-subagents/src/missions/types.ts +58 -3
  105. package/dist/extensions/pi-subagents/src/missions/workflow-state.ts +256 -0
  106. package/dist/extensions/pi-subagents/src/profiles/profiles.ts +8 -8
  107. package/dist/extensions/pi-subagents/src/runs/background/active-run-index.ts +42 -0
  108. package/dist/extensions/pi-subagents/src/runs/background/async-execution.ts +41 -7
  109. package/dist/extensions/pi-subagents/src/runs/background/async-job-tracker.ts +294 -134
  110. package/dist/extensions/pi-subagents/src/runs/background/async-resume.ts +19 -3
  111. package/dist/extensions/pi-subagents/src/runs/background/async-status.ts +39 -6
  112. package/dist/extensions/pi-subagents/src/runs/background/completion-replay.ts +267 -0
  113. package/dist/extensions/pi-subagents/src/runs/background/control-channel.ts +145 -60
  114. package/dist/extensions/pi-subagents/src/runs/background/result-watcher.ts +114 -6
  115. package/dist/extensions/pi-subagents/src/runs/background/resume-guidance.ts +33 -0
  116. package/dist/extensions/pi-subagents/src/runs/background/retained-children.ts +68 -0
  117. package/dist/extensions/pi-subagents/src/runs/background/run-id-resolver.ts +71 -0
  118. package/dist/extensions/pi-subagents/src/runs/background/run-status.ts +21 -2
  119. package/dist/extensions/pi-subagents/src/runs/background/scheduled-runs.ts +42 -14
  120. package/dist/extensions/pi-subagents/src/runs/background/stale-run-reconciler.ts +12 -24
  121. package/dist/extensions/pi-subagents/src/runs/background/steering.ts +7 -5
  122. package/dist/extensions/pi-subagents/src/runs/background/subagent-runner.ts +152 -68
  123. package/dist/extensions/pi-subagents/src/runs/background/subagent-wait.ts +17 -4
  124. package/dist/extensions/pi-subagents/src/runs/background/wait-completions.ts +146 -0
  125. package/dist/extensions/pi-subagents/src/runs/background/wait-subscriptions.ts +21 -5
  126. package/dist/extensions/pi-subagents/src/runs/foreground/async-dismiss-action.ts +85 -0
  127. package/dist/extensions/pi-subagents/src/runs/foreground/async-steering-action.ts +43 -18
  128. package/dist/extensions/pi-subagents/src/runs/foreground/chain-clarify.ts +20 -19
  129. package/dist/extensions/pi-subagents/src/runs/foreground/chain-execution.ts +3 -0
  130. package/dist/extensions/pi-subagents/src/runs/foreground/execution.ts +55 -26
  131. package/dist/extensions/pi-subagents/src/runs/foreground/foreground-history.ts +137 -0
  132. package/dist/extensions/pi-subagents/src/runs/foreground/subagent-executor.ts +798 -112
  133. package/dist/extensions/pi-subagents/src/runs/foreground/workflow-foreground-steering.ts +187 -0
  134. package/dist/extensions/pi-subagents/src/runs/shared/acceptance.ts +165 -22
  135. package/dist/extensions/pi-subagents/src/runs/shared/dynamic-fanout.ts +1 -1
  136. package/dist/extensions/pi-subagents/src/runs/shared/mcp-direct-tool-allowlist.ts +2 -0
  137. package/dist/extensions/pi-subagents/src/runs/shared/model-fallback.ts +9 -5
  138. package/dist/extensions/pi-subagents/src/runs/shared/model-scope.ts +12 -2
  139. package/dist/extensions/pi-subagents/src/runs/shared/parallel-utils.ts +1 -0
  140. package/dist/extensions/pi-subagents/src/runs/shared/pi-args.ts +465 -116
  141. package/dist/extensions/pi-subagents/src/runs/shared/pi-spawn.ts +10 -10
  142. package/dist/extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.ts +189 -32
  143. package/dist/extensions/pi-subagents/src/runs/shared/task-intent.ts +2 -2
  144. package/dist/extensions/pi-subagents/src/runs/shared/worktree.ts +3 -3
  145. package/dist/extensions/pi-subagents/src/shared/artifacts.ts +128 -3
  146. package/dist/extensions/pi-subagents/src/shared/display-text.ts +100 -0
  147. package/dist/extensions/pi-subagents/src/shared/file-coalescer.ts +9 -0
  148. package/dist/extensions/pi-subagents/src/shared/fork-context.ts +13 -0
  149. package/dist/extensions/pi-subagents/src/shared/formatters.ts +4 -6
  150. package/dist/extensions/pi-subagents/src/shared/prompt-resources.ts +51 -0
  151. package/dist/extensions/pi-subagents/src/shared/settings.ts +41 -11
  152. package/dist/extensions/pi-subagents/src/shared/types.ts +100 -3
  153. package/dist/extensions/pi-subagents/src/shared/utf8.ts +11 -0
  154. package/dist/extensions/pi-subagents/src/shared/utils.ts +43 -33
  155. package/dist/extensions/pi-subagents/src/slash/delegation-adapters.ts +1 -14
  156. package/dist/extensions/pi-subagents/src/slash/inline-subagents.ts +1 -1
  157. package/dist/extensions/pi-subagents/src/slash/prompt-template-bridge.ts +14 -12
  158. package/dist/extensions/pi-subagents/src/slash/prompt-workflows.ts +176 -21
  159. package/dist/extensions/pi-subagents/src/slash/slash-bridge.ts +12 -6
  160. package/dist/extensions/pi-subagents/src/slash/slash-commands.ts +52 -18
  161. package/dist/extensions/pi-subagents/src/slash/slash-live-state.ts +36 -5
  162. package/dist/extensions/pi-subagents/src/tui/fleet-status.ts +30 -16
  163. package/dist/extensions/pi-subagents/src/tui/fleet.ts +151 -31
  164. package/dist/extensions/pi-subagents/src/tui/render.ts +201 -68
  165. package/dist/extensions/pi-subagents/src/types/pi-runtime-compat.d.ts +0 -6
  166. package/dist/extensions/pi-subagents/src/watchdog/change-signature.ts +5 -4
  167. package/dist/extensions/pi-subagents/src/watchdog/lsp-diagnostics.ts +0 -1
  168. package/dist/extensions/pi-subagents/src/workflows/scripted-workflow.ts +313 -25
  169. package/dist/extensions/pi-subagents/test/e2e/real-session-subagent.test.ts +15 -15
  170. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/bun/cli.d.ts +3 -0
  171. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/bun/register-bedrock.d.ts +2 -0
  172. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/bun/restore-sandbox-env.d.ts +17 -0
  173. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/args.d.ts +57 -0
  174. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/config-selector.d.ts +16 -0
  175. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/file-processor.d.ts +15 -0
  176. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/initial-message.d.ts +18 -0
  177. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/list-models.d.ts +9 -0
  178. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/project-trust.d.ts +10 -0
  179. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/session-picker.d.ts +10 -0
  180. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/startup-ui.d.ts +20 -0
  181. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli.d.ts +3 -0
  182. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/config.d.ts +96 -0
  183. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/agent-session-runtime.d.ts +119 -0
  184. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/agent-session-services.d.ts +85 -0
  185. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/agent-session.d.ts +620 -0
  186. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/auth-guidance.d.ts +5 -0
  187. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/auth-storage.d.ts +56 -0
  188. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/bash-executor.d.ts +32 -0
  189. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/cache-stats.d.ts +49 -0
  190. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/compaction/branch-summarization.d.ts +93 -0
  191. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/compaction/compaction.d.ts +128 -0
  192. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/compaction/index.d.ts +7 -0
  193. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/compaction/utils.d.ts +38 -0
  194. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/defaults.d.ts +3 -0
  195. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/diagnostics.d.ts +15 -0
  196. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/event-bus.d.ts +9 -0
  197. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/exec.d.ts +29 -0
  198. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/experimental.d.ts +2 -0
  199. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/export-html/ansi-to-html.d.ts +22 -0
  200. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/export-html/index.d.ts +37 -0
  201. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/export-html/tool-renderer.d.ts +34 -0
  202. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/extensions/index.d.ts +12 -0
  203. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/extensions/loader.d.ts +23 -0
  204. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/extensions/runner.d.ts +171 -0
  205. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/extensions/types.d.ts +1261 -0
  206. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/extensions/wrapper.d.ts +20 -0
  207. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/footer-data-provider.d.ts +54 -0
  208. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/http-dispatcher.d.ts +22 -0
  209. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/index.d.ts +13 -0
  210. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/keybindings.d.ts +358 -0
  211. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/messages.d.ts +77 -0
  212. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/model-config.d.ts +512 -0
  213. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/model-registry.d.ts +43 -0
  214. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/model-resolver.d.ts +121 -0
  215. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/model-runtime.d.ts +82 -0
  216. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/models-store.d.ts +17 -0
  217. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/output-guard.d.ts +7 -0
  218. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/package-manager.d.ts +210 -0
  219. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/project-trust.d.ts +15 -0
  220. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/prompt-templates.d.ts +54 -0
  221. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/provider-attribution.d.ts +4 -0
  222. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/provider-composer.d.ts +55 -0
  223. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/radius.d.ts +2 -0
  224. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/remote-catalog-provider.d.ts +5 -0
  225. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/resolve-config-value.d.ts +30 -0
  226. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/resource-loader.d.ts +206 -0
  227. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/runtime-credentials.d.ts +15 -0
  228. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/sdk.d.ts +106 -0
  229. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/session-cwd.d.ts +19 -0
  230. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/session-manager.d.ts +356 -0
  231. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/settings-manager.d.ts +297 -0
  232. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/skills.d.ts +60 -0
  233. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/slash-commands.d.ts +15 -0
  234. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/source-info.d.ts +18 -0
  235. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/system-prompt.d.ts +28 -0
  236. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/telemetry.d.ts +3 -0
  237. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/timings.d.ts +10 -0
  238. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/bash.d.ts +68 -0
  239. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/edit-diff.d.ts +106 -0
  240. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/edit.d.ts +51 -0
  241. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/file-mutation-queue.d.ts +6 -0
  242. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/find.d.ts +35 -0
  243. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/grep.d.ts +37 -0
  244. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/index.d.ts +40 -0
  245. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/ls.d.ts +37 -0
  246. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/output-accumulator.d.ts +52 -0
  247. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/path-utils.d.ts +10 -0
  248. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/read.d.ts +35 -0
  249. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/render-utils.d.ts +24 -0
  250. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/tool-definition-wrapper.d.ts +14 -0
  251. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/truncate.d.ts +70 -0
  252. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/write.d.ts +26 -0
  253. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/trust-manager.d.ts +36 -0
  254. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/usage-totals.d.ts +19 -0
  255. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/index.d.ts +3 -0
  256. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/llama/client.d.ts +61 -0
  257. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/llama/huggingface.d.ts +23 -0
  258. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/llama/index.d.ts +3 -0
  259. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/llama/provider.d.ts +10 -0
  260. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/llama/ui.d.ts +42 -0
  261. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/index.d.ts +35 -0
  262. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/main.d.ts +12 -0
  263. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/migrations.d.ts +33 -0
  264. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/index.d.ts +9 -0
  265. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/armin.d.ts +34 -0
  266. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/assistant-message.d.ts +22 -0
  267. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/bash-execution.d.ts +34 -0
  268. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/bordered-loader.d.ts +16 -0
  269. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/branch-summary-message.d.ts +16 -0
  270. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/compaction-summary-message.d.ts +16 -0
  271. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/config-selector.d.ts +102 -0
  272. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/countdown-timer.d.ts +14 -0
  273. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/custom-editor.d.ts +21 -0
  274. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/custom-entry.d.ts +19 -0
  275. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/custom-message.d.ts +20 -0
  276. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/daxnuts.d.ts +23 -0
  277. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/diff.d.ts +12 -0
  278. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/dynamic-border.d.ts +15 -0
  279. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/earendil-announcement.d.ts +5 -0
  280. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/extension-editor.d.ts +22 -0
  281. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/extension-input.d.ts +23 -0
  282. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/extension-selector.d.ts +26 -0
  283. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/first-time-setup.d.ts +25 -0
  284. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/footer.d.ts +32 -0
  285. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/index.d.ts +34 -0
  286. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/keybinding-hints.d.ts +13 -0
  287. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/login-dialog.d.ts +52 -0
  288. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/model-selector.d.ts +54 -0
  289. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/oauth-selector.d.ts +33 -0
  290. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/scoped-models-selector.d.ts +42 -0
  291. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/session-selector-search.d.ts +23 -0
  292. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/session-selector.d.ts +95 -0
  293. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/settings-selector.d.ts +77 -0
  294. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/show-images-selector.d.ts +10 -0
  295. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/skill-invocation-message.d.ts +17 -0
  296. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/status-indicator.d.ts +28 -0
  297. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/theme-selector.d.ts +11 -0
  298. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/thinking-selector.d.ts +11 -0
  299. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/tool-execution.d.ts +63 -0
  300. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/tree-selector.d.ts +94 -0
  301. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/trust-selector.d.ts +23 -0
  302. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/user-message-selector.d.ts +30 -0
  303. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/user-message.d.ts +14 -0
  304. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/visual-truncate.d.ts +24 -0
  305. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/interactive-mode.d.ts +394 -0
  306. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/model-search.d.ts +12 -0
  307. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/theme/theme-controller.d.ts +29 -0
  308. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/theme/theme.d.ts +120 -0
  309. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/print-mode.d.ts +28 -0
  310. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/rpc/jsonl.d.ts +17 -0
  311. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/rpc/rpc-client.d.ts +246 -0
  312. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/rpc/rpc-mode.d.ts +20 -0
  313. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/rpc/rpc-types.d.ts +457 -0
  314. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/package-manager-cli.d.ts +8 -0
  315. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/rpc-entry.d.ts +3 -0
  316. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/ansi.d.ts +2 -0
  317. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/changelog.d.ts +22 -0
  318. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/child-process.d.ts +18 -0
  319. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/clipboard-image.d.ts +11 -0
  320. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/clipboard-native.d.ts +11 -0
  321. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/clipboard.d.ts +4 -0
  322. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/deprecation.d.ts +4 -0
  323. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/exif-orientation.d.ts +5 -0
  324. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/frontmatter.d.ts +8 -0
  325. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/fs-watch.d.ts +5 -0
  326. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/git.d.ts +26 -0
  327. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/html.d.ts +7 -0
  328. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/image-convert.d.ts +10 -0
  329. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/image-process.d.ts +18 -0
  330. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/image-resize-core.d.ts +30 -0
  331. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/image-resize-worker.d.ts +2 -0
  332. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/image-resize.d.ts +16 -0
  333. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/json.d.ts +3 -0
  334. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/mime.d.ts +3 -0
  335. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/open-browser.d.ts +9 -0
  336. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/paths.d.ts +31 -0
  337. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/photon.d.ts +21 -0
  338. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/pi-user-agent.d.ts +2 -0
  339. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/shell.d.ts +31 -0
  340. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/sleep.d.ts +5 -0
  341. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/syntax-highlight.d.ts +12 -0
  342. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/tools-manager.d.ts +3 -0
  343. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/version-check.d.ts +15 -0
  344. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/windows-self-update.d.ts +3 -0
  345. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/index.mjs +84 -0
  346. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/package.json +14 -0
  347. package/dist/extensions/pi-subagents/test/integration/acceptance-file-report.test.ts +15 -15
  348. package/dist/extensions/pi-subagents/test/integration/async-execution.test.ts +411 -300
  349. package/dist/extensions/pi-subagents/test/integration/async-job-tracker.test.ts +309 -123
  350. package/dist/extensions/pi-subagents/test/integration/async-status.test.ts +99 -56
  351. package/dist/extensions/pi-subagents/test/integration/chain-clarify.test.ts +62 -16
  352. package/dist/extensions/pi-subagents/test/integration/chain-execution.test.ts +159 -108
  353. package/dist/extensions/pi-subagents/test/integration/detect-error.test.ts +1 -1
  354. package/dist/extensions/pi-subagents/test/integration/external-cli-runner.test.ts +4 -2
  355. package/dist/extensions/pi-subagents/test/integration/fork-context-execution.test.ts +56 -56
  356. package/dist/extensions/pi-subagents/test/integration/intercom-result-delivery.test.ts +114 -45
  357. package/dist/extensions/pi-subagents/test/integration/parallel-execution.test.ts +57 -19
  358. package/dist/extensions/pi-subagents/test/integration/render-fork-badge.test.ts +106 -106
  359. package/dist/extensions/pi-subagents/test/integration/render-widget.test.ts +416 -106
  360. package/dist/extensions/pi-subagents/test/integration/result-watcher.test.ts +287 -17
  361. package/dist/extensions/pi-subagents/test/integration/single-execution.test.ts +809 -87
  362. package/dist/extensions/pi-subagents/test/integration/slash-commands.test.ts +107 -20
  363. package/dist/extensions/pi-subagents/test/integration/slash-live-state.test.ts +9 -9
  364. package/dist/extensions/pi-subagents/test/integration/template-resolution.test.ts +26 -6
  365. package/dist/extensions/pi-subagents/test/integration/top-level-async.test.ts +2 -2
  366. package/dist/extensions/pi-subagents/test/support/helpers.ts +2 -0
  367. package/dist/extensions/pi-subagents/test/support/mock-pi-script.mjs +1 -1
  368. package/dist/extensions/pi-subagents/test/support/ts-loader.mjs +0 -8
  369. package/dist/extensions/pi-subagents/test/unit/acceptance.test.ts +163 -58
  370. package/dist/extensions/pi-subagents/test/unit/agent-disabled.test.ts +15 -15
  371. package/dist/extensions/pi-subagents/test/unit/agent-eject-disable.test.ts +66 -66
  372. package/dist/extensions/pi-subagents/test/unit/agent-frontmatter.test.ts +334 -248
  373. package/dist/extensions/pi-subagents/test/unit/agent-management.test.ts +52 -52
  374. package/dist/extensions/pi-subagents/test/unit/agent-memory.test.ts +26 -26
  375. package/dist/extensions/pi-subagents/test/unit/agent-overrides.test.ts +99 -99
  376. package/dist/extensions/pi-subagents/test/unit/agent-refinements.test.ts +160 -0
  377. package/dist/extensions/pi-subagents/test/unit/agent-selection.test.ts +9 -9
  378. package/dist/extensions/pi-subagents/test/unit/artifacts.test.ts +43 -1
  379. package/dist/extensions/pi-subagents/test/unit/async-execution.test.ts +36 -10
  380. package/dist/extensions/pi-subagents/test/unit/async-interrupt-action.test.ts +387 -30
  381. package/dist/extensions/pi-subagents/test/unit/async-permission-session.test.ts +9 -9
  382. package/dist/extensions/pi-subagents/test/unit/async-recovery-descriptor.test.ts +2 -2
  383. package/dist/extensions/pi-subagents/test/unit/async-resume.test.ts +94 -40
  384. package/dist/extensions/pi-subagents/test/unit/background-work.test.ts +5 -3
  385. package/dist/extensions/pi-subagents/test/unit/builtin-agent-documentation.test.ts +7 -7
  386. package/dist/extensions/pi-subagents/test/unit/capability-ceiling-agent-allowlist.test.ts +19 -19
  387. package/dist/extensions/pi-subagents/test/unit/chain-append.test.ts +19 -19
  388. package/dist/extensions/pi-subagents/test/unit/chain-root-attachment.test.ts +9 -9
  389. package/dist/extensions/pi-subagents/test/unit/chain-serializer.test.ts +20 -20
  390. package/dist/extensions/pi-subagents/test/unit/child-transcript.test.ts +9 -9
  391. package/dist/extensions/pi-subagents/test/unit/compaction-resume.test.ts +35 -5
  392. package/dist/extensions/pi-subagents/test/unit/completion-dedupe.test.ts +2 -2
  393. package/dist/extensions/pi-subagents/test/unit/completion-guard.test.ts +52 -52
  394. package/dist/extensions/pi-subagents/test/unit/completion-replay.test.ts +187 -0
  395. package/dist/extensions/pi-subagents/test/unit/control-channel.test.ts +125 -71
  396. package/dist/extensions/pi-subagents/test/unit/control-notices.test.ts +18 -3
  397. package/dist/extensions/pi-subagents/test/unit/default-extensions.test.ts +12 -12
  398. package/dist/extensions/pi-subagents/test/unit/delegation-api.test.ts +17 -23
  399. package/dist/extensions/pi-subagents/test/unit/doctor.test.ts +1 -1
  400. package/dist/extensions/pi-subagents/test/unit/dynamic-fanout.test.ts +25 -25
  401. package/dist/extensions/pi-subagents/test/unit/extra-agent-dirs.test.ts +3 -3
  402. package/dist/extensions/pi-subagents/test/unit/file-coalescer.test.ts +15 -0
  403. package/dist/extensions/pi-subagents/test/unit/fleet-status.test.ts +62 -44
  404. package/dist/extensions/pi-subagents/test/unit/fleet.test.ts +329 -37
  405. package/dist/extensions/pi-subagents/test/unit/foreground-control.test.ts +4 -4
  406. package/dist/extensions/pi-subagents/test/unit/foreground-tool-call-compaction.test.ts +37 -0
  407. package/dist/extensions/pi-subagents/test/unit/herdr-inspector-bootstrap.test.ts +69 -0
  408. package/dist/extensions/pi-subagents/test/unit/herdr-inspector.test.ts +79 -2
  409. package/dist/extensions/pi-subagents/test/unit/herdr-status-bridge.test.ts +102 -49
  410. package/dist/extensions/pi-subagents/test/unit/index-child-registration.test.ts +98 -32
  411. package/dist/extensions/pi-subagents/test/unit/intercom-bridge.test.ts +5 -5
  412. package/dist/extensions/pi-subagents/test/unit/mission-goal-driver.test.ts +116 -0
  413. package/dist/extensions/pi-subagents/test/unit/mission-lifecycle.test.ts +55 -7
  414. package/dist/extensions/pi-subagents/test/unit/mission-store.test.ts +289 -13
  415. package/dist/extensions/pi-subagents/test/unit/model-fallback.test.ts +28 -1
  416. package/dist/extensions/pi-subagents/test/unit/model-scope-settings.test.ts +2 -2
  417. package/dist/extensions/pi-subagents/test/unit/model-scope.test.ts +11 -2
  418. package/dist/extensions/pi-subagents/test/unit/native-supervisor-channel.test.ts +84 -10
  419. package/dist/extensions/pi-subagents/test/unit/nested-control.test.ts +122 -8
  420. package/dist/extensions/pi-subagents/test/unit/nested-events.test.ts +8 -8
  421. package/dist/extensions/pi-subagents/test/unit/notify.test.ts +24 -24
  422. package/dist/extensions/pi-subagents/test/unit/package-manifest.test.ts +16 -2
  423. package/dist/extensions/pi-subagents/test/unit/parallel-handoff.test.ts +7 -7
  424. package/dist/extensions/pi-subagents/test/unit/parallel-utils.test.ts +10 -10
  425. package/dist/extensions/pi-subagents/test/unit/path-handling.test.ts +3 -3
  426. package/dist/extensions/pi-subagents/test/unit/path-resolution.test.ts +26 -17
  427. package/dist/extensions/pi-subagents/test/unit/pi-args-permission-system.test.ts +405 -0
  428. package/dist/extensions/pi-subagents/test/unit/pi-args.test.ts +357 -92
  429. package/dist/extensions/pi-subagents/test/unit/pi-coding-agent-dir.test.ts +22 -6
  430. package/dist/extensions/pi-subagents/test/unit/pi-spawn.test.ts +6 -6
  431. package/dist/extensions/pi-subagents/test/unit/preflight.test.ts +43 -43
  432. package/dist/extensions/pi-subagents/test/unit/proactive-skills.test.ts +13 -13
  433. package/dist/extensions/pi-subagents/test/unit/process-terminal.test.ts +4 -4
  434. package/dist/extensions/pi-subagents/test/unit/profiles.test.ts +19 -19
  435. package/dist/extensions/pi-subagents/test/unit/project-panes-public-api.test.ts +243 -0
  436. package/dist/extensions/pi-subagents/test/unit/prompt-template-bridge.test.ts +68 -168
  437. package/dist/extensions/pi-subagents/test/unit/prompt-workflows.test.ts +58 -15
  438. package/dist/extensions/pi-subagents/test/unit/public-execution.test.ts +40 -0
  439. package/dist/extensions/pi-subagents/test/unit/reads-resolution.test.ts +66 -0
  440. package/dist/extensions/pi-subagents/test/unit/render-helpers.test.ts +47 -28
  441. package/dist/extensions/pi-subagents/test/unit/result-intercom.test.ts +12 -12
  442. package/dist/extensions/pi-subagents/test/unit/retained-children.test.ts +57 -0
  443. package/dist/extensions/pi-subagents/test/unit/rpc.test.ts +107 -27
  444. package/dist/extensions/pi-subagents/test/unit/run-id-resolver.test.ts +1 -1
  445. package/dist/extensions/pi-subagents/test/unit/run-status.test.ts +56 -50
  446. package/dist/extensions/pi-subagents/test/unit/scheduled-runs.test.ts +69 -28
  447. package/dist/extensions/pi-subagents/test/unit/scheduled-store-root.test.ts +67 -0
  448. package/dist/extensions/pi-subagents/test/unit/schemas.test.ts +59 -44
  449. package/dist/extensions/pi-subagents/test/unit/scripted-workflow.test.ts +424 -49
  450. package/dist/extensions/pi-subagents/test/unit/skills-fallback.test.ts +23 -1
  451. package/dist/extensions/pi-subagents/test/unit/slash-bridge.test.ts +32 -5
  452. package/dist/extensions/pi-subagents/test/unit/stale-run-reconciler.test.ts +13 -13
  453. package/dist/extensions/pi-subagents/test/unit/steering-action.test.ts +120 -91
  454. package/dist/extensions/pi-subagents/test/unit/steering.test.ts +2 -2
  455. package/dist/extensions/pi-subagents/test/unit/subagent-action-recovery.test.ts +85 -0
  456. package/dist/extensions/pi-subagents/test/unit/subagent-control.test.ts +35 -35
  457. package/dist/extensions/pi-subagents/test/unit/subagent-guide.test.ts +24 -0
  458. package/dist/extensions/pi-subagents/test/unit/subagent-prompt-runtime.test.ts +312 -22
  459. package/dist/extensions/pi-subagents/test/unit/subagent-wait.test.ts +150 -15
  460. package/dist/extensions/pi-subagents/test/unit/task-intent.test.ts +26 -26
  461. package/dist/extensions/pi-subagents/test/unit/timeout-defaults.test.ts +73 -0
  462. package/dist/extensions/pi-subagents/test/unit/tool-description.test.ts +76 -25
  463. package/dist/extensions/pi-subagents/test/unit/turn-budget.test.ts +5 -5
  464. package/dist/extensions/pi-subagents/test/unit/wait-subscriptions.test.ts +55 -6
  465. package/dist/extensions/pi-subagents/test/unit/watchdog-child-status.test.ts +13 -13
  466. package/dist/extensions/pi-subagents/test/unit/watchdog-lsp-diagnostics.test.ts +1 -1
  467. package/dist/extensions/pi-subagents/test/unit/watchdog-runtime.test.ts +1 -1
  468. package/dist/extensions/pi-subagents/test/unit/watchdog-settings.test.ts +8 -8
  469. package/dist/extensions/pi-subagents/test/unit/widget-nested-render.test.ts +6 -6
  470. package/dist/extensions/pi-subagents/test/unit/workflow-chat-progress.test.ts +138 -11
  471. package/dist/extensions/pi-subagents/test/unit/workflow-graph.test.ts +8 -8
  472. package/dist/extensions/pi-subagents/test/unit/workflow-launch-params.test.ts +113 -0
  473. package/dist/extensions/pi-subagents/test/unit/worktree.test.ts +7 -7
  474. package/dist/extensions/pi-subagents/test/unit/writer-budget-guidance.test.ts +6 -6
  475. package/dist/extensions/workflow/extension.ts +21 -19
  476. package/dist/extensions/workflow/modes.ts +65 -0
  477. package/dist/skills/pi-subagents/SKILL.md +20 -15
  478. package/dist/skills/pi-subagents/references/constraints-and-recipes.md +77 -83
  479. package/dist/skills/pi-subagents/references/execution-controls.md +215 -106
  480. package/dist/skills/pi-subagents/references/management-authoring-rpc.md +29 -9
  481. package/dist/skills/pi-subagents/references/prompting-and-roles.md +58 -43
  482. package/docs/plans/workflow-autoloop-reference.md +192 -0
  483. package/docs/plans/workflow-subagent-consolidation-planb.md +374 -0
  484. package/docs/plans/workflow-subagent-scripted-merge.md +406 -0
  485. package/package.json +1 -1
  486. package/dist/extensions/workflow/adapter.ts +0 -949
  487. package/dist/extensions/workflow/modes/loop.ts +0 -74
  488. package/dist/extensions/workflow/modes/prototype.ts +0 -170
  489. package/dist/extensions/workflow/modes/quicktype.ts +0 -150
  490. package/dist/extensions/workflow/modes/task.ts +0 -105
  491. package/dist/extensions/workflow/run-state.ts +0 -124
  492. package/dist/extensions/workflow/state-machine.ts +0 -484
  493. package/dist/extensions/workflow/validators.ts +0 -42
@@ -1,8 +1,10 @@
1
1
  import assert from "node:assert/strict";
2
2
  import { describe, it } from "node:test";
3
+ import { visibleWidth } from "@earendil-works/pi-tui";
4
+ import { extractToolArgsPreview } from "../../src/shared/utils.ts";
3
5
 
4
6
  const { buildWidgetLines, clearLegacyResultAnimationTimer, renderWidget } = await import("../../src/tui/render.ts") as {
5
- buildWidgetLines: (jobs: Array<Record<string, unknown>>, theme: { fg(name: string, text: string): string; bold(text: string): string }, width?: number, expanded?: boolean) => string[];
7
+ buildWidgetLines: (jobs: Array<Record<string, unknown>>, theme: { fg(name: string, text: string): string; bold(text: string): string }, width?: number, expanded?: boolean, frame?: number) => string[];
6
8
  clearLegacyResultAnimationTimer: (context: { state: { subagentResultAnimationTimer?: ReturnType<typeof setInterval> } }) => void;
7
9
  renderWidget: (ctx: Record<string, unknown>, jobs: Array<Record<string, unknown>>) => void;
8
10
  };
@@ -13,6 +15,7 @@ const theme = {
13
15
  };
14
16
 
15
17
  const runningGlyphPattern = "[⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏●]";
18
+ const malformedSurrogate = /[\ud800-\udbff](?![\udc00-\udfff])|(?<![\ud800-\udbff])[\udc00-\udfff]/u;
16
19
 
17
20
  function escapeRegExp(value: string): string {
18
21
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
@@ -55,7 +58,7 @@ function createUiContext() {
55
58
  }
56
59
 
57
60
  function renderWidgetLines(widget: unknown, width = 180): string[] {
58
- return (widget as (_tui: unknown, widgetTheme: typeof theme) => { render(width: number): string[] })(undefined, theme).render(width);
61
+ return (widget as (_tui: { requestRender(): void }, widgetTheme: typeof theme) => { render(width: number): string[] })({ requestRender() {} }, theme).render(width);
59
62
  }
60
63
 
61
64
  function restoreDescriptor(target: object, key: string, descriptor: PropertyDescriptor | undefined): void {
@@ -87,39 +90,90 @@ function resetWidgetLayout(): void {
87
90
  describe("subagent async widget rendering", () => {
88
91
  it("orders running jobs before queued summaries and completions", () => {
89
92
  const lines = buildWidgetLines([
90
- { asyncId: "done-1", asyncDir: "/tmp/done", status: "complete", agents: ["commentator"], startedAt: 0, updatedAt: 1000 },
91
- { asyncId: "queued-1", asyncDir: "/tmp/queued", status: "queued", agents: ["architect"], startedAt: 0, updatedAt: 1000 },
92
- { asyncId: "run-1", asyncDir: "/tmp/run", status: "running", agents: ["explorer"], currentStep: 0, stepsTotal: 2, startedAt: Date.now() - 1000, updatedAt: Date.now(), currentTool: "read", currentToolStartedAt: Date.now() - 500 },
93
+ { asyncId: "done-1", asyncDir: "/tmp/done", status: "complete", agents: ["reviewer"], startedAt: 0, updatedAt: 1000 },
94
+ { asyncId: "queued-1", asyncDir: "/tmp/queued", status: "queued", agents: ["planner"], startedAt: 0, updatedAt: 1000 },
95
+ { asyncId: "run-1", asyncDir: "/tmp/run", status: "running", agents: ["scout"], currentStep: 0, stepsTotal: 2, startedAt: Date.now() - 1000, updatedAt: Date.now(), currentTool: "read", currentToolStartedAt: Date.now() - 500 },
93
96
  ], theme, 120);
94
97
 
95
98
  const text = lines.join("\n");
96
99
  assert.match(text, new RegExp(`^${runningGlyphPattern} Async agents · background`));
97
- assert.ok(text.indexOf("explorer") < text.indexOf("queued"), "running row should precede queued summary");
98
- assert.ok(text.indexOf("queued") < text.indexOf("commentator"), "queued summary should precede completions");
100
+ assert.ok(text.indexOf("scout") < text.indexOf("queued"), "running row should precede queued summary");
101
+ assert.ok(text.indexOf("queued") < text.indexOf("reviewer"), "queued summary should precede completions");
99
102
  assert.match(text, /⎿ read/);
100
103
  });
101
104
 
105
+ it("returns one physical terminal line per widget line for tool previews", () => {
106
+ const preview = extractToolArgsPreview({ command: "first\r\n\t\x1b[31msecond\x1b[0m" });
107
+ const lines = buildWidgetLines([{
108
+ asyncId: "run-1",
109
+ asyncDir: "/tmp/run",
110
+ status: "running",
111
+ mode: "parallel",
112
+ agents: ["worker"],
113
+ activeParallelGroup: true,
114
+ runningSteps: 1,
115
+ completedSteps: 0,
116
+ stepsTotal: 1,
117
+ steps: [{
118
+ index: 0,
119
+ agent: "worker",
120
+ status: "running",
121
+ currentTool: "bash",
122
+ currentToolArgs: preview,
123
+ recentTools: [{ tool: "bash", args: preview, endMs: 1 }],
124
+ }],
125
+ }], theme, 120, true);
126
+
127
+ assert.match(lines.join("\n"), /first second/);
128
+ for (const line of lines) assert.doesNotMatch(line, /[\r\n]/);
129
+ });
130
+
131
+ it("does not split surrogate pairs when widget rows shorten previews again", () => {
132
+ const preview = `a${"😀".repeat(30)}`;
133
+ const lines = buildWidgetLines([{
134
+ asyncId: "run-1",
135
+ asyncDir: "/tmp/run",
136
+ status: "running",
137
+ mode: "parallel",
138
+ agents: ["worker"],
139
+ activeParallelGroup: true,
140
+ runningSteps: 1,
141
+ completedSteps: 0,
142
+ stepsTotal: 1,
143
+ steps: [{
144
+ index: 0,
145
+ agent: "worker",
146
+ status: "running",
147
+ currentTool: "bash",
148
+ currentToolArgs: preview,
149
+ recentTools: [{ tool: "bash", args: preview, endMs: 1 }],
150
+ }],
151
+ }], theme, 60, true);
152
+
153
+ for (const line of lines) assert.doesNotMatch(line, malformedSurrogate);
154
+ });
155
+
102
156
  it("uses parallel running/done wording for async jobs with parallel groups", () => {
103
157
  const lines = buildWidgetLines([
104
- { asyncId: "run-1", asyncDir: "/tmp/1", status: "running", mode: "parallel", agents: ["explorer", "commentator", "builder"], hasParallelGroups: true, activeParallelGroup: true, runningSteps: 3, completedSteps: 0, stepsTotal: 3 },
158
+ { asyncId: "run-1", asyncDir: "/tmp/1", status: "running", mode: "parallel", agents: ["scout", "reviewer", "worker"], hasParallelGroups: true, activeParallelGroup: true, runningSteps: 3, completedSteps: 0, stepsTotal: 3 },
105
159
  ], theme, 120);
106
160
 
107
161
  const text = lines.join("\n");
108
162
  assert.match(text, /parallel · 3 agents running · 0\/3 done/);
109
163
  assert.match(text, /⎿ thinking…/);
110
- assert.doesNotMatch(text, /parallel · explorer, commentator, builder/);
164
+ assert.doesNotMatch(text, /parallel · scout, reviewer, worker/);
111
165
  assert.doesNotMatch(text, /step 1\/3/);
112
166
  });
113
167
 
114
168
  it("collapses repeated async parallel agent names", () => {
115
169
  const lines = buildWidgetLines([
116
- { asyncId: "run-1", asyncDir: "/tmp/1", status: "running", mode: "parallel", agents: ["commentator", "commentator", "commentator"], activeParallelGroup: true, runningSteps: 3, completedSteps: 0, stepsTotal: 3 },
170
+ { asyncId: "run-1", asyncDir: "/tmp/1", status: "running", mode: "parallel", agents: ["reviewer", "reviewer", "reviewer"], activeParallelGroup: true, runningSteps: 3, completedSteps: 0, stepsTotal: 3 },
117
171
  ], theme, 120);
118
172
 
119
173
  const text = lines.join("\n");
120
174
  assert.match(text, /parallel · 3 agents running/);
121
- assert.doesNotMatch(text, /parallel · commentator ×3/);
122
- assert.doesNotMatch(text, /commentator → commentator → commentator/);
175
+ assert.doesNotMatch(text, /parallel · reviewer ×3/);
176
+ assert.doesNotMatch(text, /reviewer → reviewer → reviewer/);
123
177
  });
124
178
 
125
179
  it("renders a compact component widget for three active parallel agents without core truncation", () => {
@@ -130,16 +184,16 @@ describe("subagent async widget rendering", () => {
130
184
  asyncDir: "/tmp/1",
131
185
  status: "running",
132
186
  mode: "parallel",
133
- agents: ["commentator", "commentator", "commentator"],
187
+ agents: ["reviewer", "reviewer", "reviewer"],
134
188
  activeParallelGroup: true,
135
189
  runningSteps: 3,
136
190
  completedSteps: 0,
137
191
  stepsTotal: 3,
138
192
  updatedAt: now,
139
193
  steps: [
140
- { index: 0, agent: "commentator", status: "running", lastActivityAt: now, turnCount: 5, toolCount: 18, tokens: { input: 30_000, output: 10_000, cache: 4_000, total: 44_000 } },
141
- { index: 1, agent: "commentator", status: "running", lastActivityAt: now - 2000, turnCount: 4, toolCount: 13, tokens: { input: 16_000, output: 4_000, cache: 2_000, total: 22_000 } },
142
- { index: 2, agent: "commentator", status: "running", currentTool: "grep", currentToolStartedAt: now - 1000, turnCount: 3, toolCount: 11, tokens: { input: 14_000, output: 3_000, cache: 2_000, total: 19_000 } },
194
+ { index: 0, agent: "reviewer", status: "running", lastActivityAt: now, turnCount: 5, toolCount: 18, tokens: { input: 30_000, output: 10_000, cache: 4_000, total: 44_000 } },
195
+ { index: 1, agent: "reviewer", status: "running", lastActivityAt: now - 2000, turnCount: 4, toolCount: 13, tokens: { input: 16_000, output: 4_000, cache: 2_000, total: 22_000 } },
196
+ { index: 2, agent: "reviewer", status: "running", currentTool: "grep", currentToolStartedAt: now - 1000, turnCount: 3, toolCount: 11, tokens: { input: 14_000, output: 3_000, cache: 2_000, total: 19_000 } },
143
197
  ],
144
198
  }]);
145
199
  const widget = ui.widgets.at(-1);
@@ -147,14 +201,46 @@ describe("subagent async widget rendering", () => {
147
201
  const lines = (widget as (_tui: unknown, widgetTheme: typeof theme) => { render(width: number): string[] })(undefined, theme).render(180).map((line) => line.trimEnd());
148
202
  const text = lines.join("\n");
149
203
  assert.match(text, /async subagent parallel \(3\) · background/);
150
- assert.match(text, /Agent 1\/3: commentator · running · active now · 5 turns · 18 tool uses · 44k token/);
151
- assert.match(text, /Agent 2\/3: commentator · running · active 2s ago · 4 turns · 13 tool uses · 22k token/);
152
- assert.match(text, /Agent 3\/3: commentator · running · grep \| 1\.0s · 3 turns · 11 tool uses · 19k token/);
153
- assert.match(text, /Press configured-expand-key for live detail/);
204
+ assert.match(text, /Agent 1\/3: reviewer · running · active now · 5 turns · 18 tool uses · 44k token/);
205
+ assert.match(text, /Agent 2\/3: reviewer · running · active 2s ago · 4 turns · 13 tool uses · 22k token/);
206
+ assert.match(text, /Agent 3\/3: reviewer · running · grep \| 1\.0s · 3 turns · 11 tool uses · 19k token/);
207
+ assert.match(text, /Press\s+for live detail/);
154
208
  assert.doesNotMatch(text, /widget truncated/);
155
209
  assert.ok(lines.length <= 10, "collapsed component should stay under Pi's string-widget cap even though it bypasses it");
156
210
  });
157
211
 
212
+ it("honors the component render width instead of the terminal width", () => {
213
+ resetWidgetLayout();
214
+ withStdoutSize(50, 120, () => {
215
+ const ui = createUiContext();
216
+ renderWidget(ui.ctx as never, [{
217
+ asyncId: "run-narrow",
218
+ asyncDir: "/tmp/pi-subagents-uid-1000/async-subagent-runs/call_with_a_long_identifier",
219
+ status: "running",
220
+ mode: "parallel",
221
+ agents: ["correctness", "tests-maintainability"],
222
+ activeParallelGroup: true,
223
+ runningSteps: 2,
224
+ completedSteps: 0,
225
+ stepsTotal: 2,
226
+ steps: [
227
+ { index: 0, agent: "correctness", status: "running" },
228
+ { index: 1, agent: "tests-maintainability", status: "running" },
229
+ ],
230
+ }]);
231
+
232
+ const widget = ui.widgets.at(-1);
233
+ for (const width of [0, 1, 2, 3, 74]) {
234
+ const lines = renderWidgetLines(widget, width);
235
+ assert.ok(lines.length > 0);
236
+ for (const line of lines) {
237
+ assert.ok(visibleWidth(line) <= width, `widget line exceeds render width: ${visibleWidth(line)} > ${width}`);
238
+ }
239
+ }
240
+ });
241
+ resetWidgetLayout();
242
+ });
243
+
158
244
  it("locks crowded collapsed widget height for the current terminal session", () => {
159
245
  resetWidgetLayout();
160
246
  withStdoutSize(30, 120, () => {
@@ -164,15 +250,15 @@ describe("subagent async widget rendering", () => {
164
250
  asyncDir: `/tmp/run-${jobIndex + 1}`,
165
251
  status: "running",
166
252
  mode: "parallel",
167
- agents: ["explorer", "commentator"],
253
+ agents: ["scout", "reviewer"],
168
254
  activeParallelGroup: true,
169
255
  runningSteps: 2,
170
256
  completedSteps: 0,
171
257
  stepsTotal: 2,
172
258
  updatedAt: now + jobIndex,
173
259
  steps: [
174
- { index: 0, agent: "explorer", status: "running", currentTool: "read", currentToolStartedAt: now - 1000 },
175
- { index: 1, agent: "commentator", status: "running", currentTool: "grep", currentToolStartedAt: now - 2000 },
260
+ { index: 0, agent: "scout", status: "running", currentTool: "read", currentToolStartedAt: now - 1000 },
261
+ { index: 1, agent: "reviewer", status: "running", currentTool: "grep", currentToolStartedAt: now - 2000 },
176
262
  ],
177
263
  }));
178
264
  const ui = createUiContext();
@@ -188,8 +274,8 @@ describe("subagent async widget rendering", () => {
188
274
  runningSteps: 0,
189
275
  completedSteps: 2,
190
276
  steps: [
191
- { index: 0, agent: "explorer", status: "complete" },
192
- { index: 1, agent: "commentator", status: "complete" },
277
+ { index: 0, agent: "scout", status: "complete" },
278
+ { index: 1, agent: "reviewer", status: "complete" },
193
279
  ],
194
280
  }]);
195
281
  const settledLines = renderWidgetLines(ui.widgets.at(-1));
@@ -197,7 +283,7 @@ describe("subagent async widget rendering", () => {
197
283
  assert.match(settledLines.join("\n"), /parallel · done/);
198
284
 
199
285
  renderWidget(ui.ctx as never, []);
200
- renderWidget(ui.ctx as never, [{ asyncId: "small", asyncDir: "/tmp/small", status: "running", agents: ["builder"], currentTool: "read" }]);
286
+ renderWidget(ui.ctx as never, [{ asyncId: "small", asyncDir: "/tmp/small", status: "running", agents: ["worker"], currentTool: "read" }]);
201
287
  const resetLines = renderWidgetLines(ui.widgets.at(-1));
202
288
  assert.ok(resetLines.length < 10, "clearing the widget starts a fresh layout session");
203
289
  });
@@ -264,7 +350,7 @@ describe("subagent async widget rendering", () => {
264
350
  asyncId: "run-tiny",
265
351
  asyncDir: "/tmp/run-tiny",
266
352
  status: "running",
267
- agents: ["builder"],
353
+ agents: ["worker"],
268
354
  currentTool: "read",
269
355
  }]);
270
356
 
@@ -285,17 +371,17 @@ describe("subagent async widget rendering", () => {
285
371
  asyncDir: "/tmp/run-expanded",
286
372
  status: "running",
287
373
  mode: "parallel",
288
- agents: ["commentator"],
374
+ agents: ["reviewer"],
289
375
  activeParallelGroup: true,
290
376
  runningSteps: 1,
291
377
  completedSteps: 0,
292
378
  stepsTotal: 1,
293
- steps: [{ index: 0, agent: "commentator", status: "running", currentTool: "read" }],
379
+ steps: [{ index: 0, agent: "reviewer", status: "running", currentTool: "read" }],
294
380
  }]);
295
381
 
296
382
  const text = renderWidgetLines(ui.widgets.at(-1)).join("\n");
297
383
  assert.match(text, /async subagent parallel · background/);
298
- assert.match(text, /Agent 1\/1: commentator · running/);
384
+ assert.match(text, /Agent 1\/1: reviewer · running/);
299
385
  assert.doesNotMatch(text, /subagents \(1\/1 running\)/);
300
386
  });
301
387
  resetWidgetLayout();
@@ -309,16 +395,16 @@ describe("subagent async widget rendering", () => {
309
395
  asyncDir: "/tmp/1",
310
396
  status: "running",
311
397
  mode: "parallel",
312
- agents: ["commentator", "commentator", "commentator"],
398
+ agents: ["reviewer", "reviewer", "reviewer"],
313
399
  activeParallelGroup: true,
314
400
  runningSteps: 2,
315
401
  completedSteps: 1,
316
402
  stepsTotal: 3,
317
403
  updatedAt: now,
318
404
  steps: [
319
- { agent: "commentator", status: "running", lastActivityAt: now, toolCount: 2 },
320
- { agent: "commentator", status: "running", currentTool: "read", currentToolStartedAt: now - 2000 },
321
- { agent: "commentator", status: "complete", tokens: { input: 1000, output: 500, cache: 0, total: 1500 } },
405
+ { agent: "reviewer", status: "running", lastActivityAt: now, toolCount: 2 },
406
+ { agent: "reviewer", status: "running", currentTool: "read", currentToolStartedAt: now - 2000 },
407
+ { agent: "reviewer", status: "complete", tokens: { input: 1000, output: 500, cache: 0, total: 1500 } },
322
408
  ],
323
409
  },
324
410
  ], theme, 160);
@@ -326,11 +412,11 @@ describe("subagent async widget rendering", () => {
326
412
  const text = lines.join("\n");
327
413
  assert.match(text, /async subagent parallel \(3\) · background/);
328
414
  assert.match(text, /parallel · 2 agents running · 1\/3 done/);
329
- assert.match(text, /Agent 1\/3: commentator · running · 2 tool uses/);
415
+ assert.match(text, /Agent 1\/3: reviewer · running · 2 tool uses/);
330
416
  assert.match(text, /⎿ active now/);
331
- assert.match(text, /Agent 2\/3: commentator · running\n\s+⎿ read \| 2\.0s/);
332
- assert.match(text, /Press configured-expand-key for live detail/);
333
- assert.match(text, /Agent 3\/3: commentator · complete · 1\.5k token/);
417
+ assert.match(text, /Agent 2\/3: reviewer · running\n\s+⎿ read \| 2\.0s/);
418
+ assert.match(text, /Press\s+for live detail/);
419
+ assert.match(text, /Agent 3\/3: reviewer · complete · 1\.5k token/);
334
420
  });
335
421
 
336
422
  it("shows async job and step context badges", () => {
@@ -342,22 +428,22 @@ describe("subagent async widget rendering", () => {
342
428
  status: "running",
343
429
  mode: "parallel",
344
430
  context: "mixed",
345
- agents: ["explorer", "builder"],
431
+ agents: ["scout", "worker"],
346
432
  activeParallelGroup: true,
347
433
  runningSteps: 2,
348
434
  completedSteps: 0,
349
435
  stepsTotal: 2,
350
436
  updatedAt: now,
351
437
  steps: [
352
- { agent: "explorer", context: "fresh", status: "running", lastActivityAt: now },
353
- { agent: "builder", context: "fork", status: "running", currentTool: "bash", currentToolStartedAt: now - 1000 },
438
+ { agent: "scout", context: "fresh", status: "running", lastActivityAt: now },
439
+ { agent: "worker", context: "fork", status: "running", currentTool: "bash", currentToolStartedAt: now - 1000 },
354
440
  ],
355
441
  },
356
442
  ], theme, 160).join("\n");
357
443
 
358
444
  assert.match(text, /parallel \[mixed\]/);
359
- assert.match(text, /Agent 1\/2: explorer \[fresh\] · running/);
360
- assert.match(text, /Agent 2\/2: builder \[fork\] · running/);
445
+ assert.match(text, /Agent 1\/2: scout \[fresh\] · running/);
446
+ assert.match(text, /Agent 2\/2: worker \[fork\] · running/);
361
447
  });
362
448
 
363
449
  it("shows model and thinking for active async widget rows", () => {
@@ -367,21 +453,21 @@ describe("subagent async widget rendering", () => {
367
453
  asyncDir: "/tmp/1",
368
454
  status: "running",
369
455
  mode: "parallel",
370
- agents: ["commentator", "explorer"],
456
+ agents: ["reviewer", "scout"],
371
457
  activeParallelGroup: true,
372
458
  runningSteps: 2,
373
459
  completedSteps: 0,
374
460
  stepsTotal: 2,
375
461
  steps: [
376
- { agent: "commentator", status: "running", model: "openai-codex/gpt-5.5:high" },
377
- { agent: "explorer", status: "running", model: "anthropic/claude-haiku-4-5", thinking: "low" },
462
+ { agent: "reviewer", status: "running", model: "openai-codex/gpt-5.5:high" },
463
+ { agent: "scout", status: "running", model: "anthropic/claude-haiku-4-5", thinking: "low" },
378
464
  ],
379
465
  },
380
466
  ], theme, 180);
381
467
 
382
468
  const text = lines.join("\n");
383
- assert.match(text, /Agent 1\/2: commentator · running \(gpt-5\.5 · thinking high\)/);
384
- assert.match(text, /Agent 2\/2: explorer · running \(claude-haiku-4-5 · thinking low\)/);
469
+ assert.match(text, /Agent 1\/2: reviewer · running \(gpt-5\.5 · thinking high\)/);
470
+ assert.match(text, /Agent 2\/2: scout · running \(claude-haiku-4-5 · thinking low\)/);
385
471
  assert.doesNotMatch(text, /openai-codex\/gpt-5\.5/);
386
472
  assert.doesNotMatch(text, /gpt-5\.5:high/);
387
473
  });
@@ -393,20 +479,20 @@ describe("subagent async widget rendering", () => {
393
479
  asyncDir: "/tmp/1",
394
480
  status: "running",
395
481
  mode: "parallel",
396
- agents: ["commentator"],
482
+ agents: ["reviewer"],
397
483
  activeParallelGroup: true,
398
484
  runningSteps: 1,
399
485
  completedSteps: 0,
400
486
  stepsTotal: 1,
401
487
  steps: [
402
- { agent: "commentator", status: "running", model: "anthropic/claude-opus-4-5-20260501-super-long-model-name:high" },
488
+ { agent: "reviewer", status: "running", model: "anthropic/claude-opus-4-5-20260501-super-long-model-name:high" },
403
489
  ],
404
490
  },
405
491
  ], theme, 68);
406
492
 
407
493
  const row = lines.find((line) => line.includes("Agent 1/1")) ?? "";
408
- assert.match(row, /Agent 1\/1: commentator · running/);
409
- assert.doesNotMatch(row, /Agent 1\/1: commentator \(/);
494
+ assert.match(row, /Agent 1\/1: reviewer · running/);
495
+ assert.doesNotMatch(row, /Agent 1\/1: reviewer \(/);
410
496
  });
411
497
 
412
498
  it("shows inline live detail for expanded async parallel widget rows", () => {
@@ -416,7 +502,7 @@ describe("subagent async widget rendering", () => {
416
502
  asyncDir: "/tmp/1",
417
503
  status: "running",
418
504
  mode: "parallel",
419
- agents: ["commentator"],
505
+ agents: ["reviewer"],
420
506
  activeParallelGroup: true,
421
507
  runningSteps: 1,
422
508
  completedSteps: 0,
@@ -425,7 +511,7 @@ describe("subagent async widget rendering", () => {
425
511
  steps: [
426
512
  {
427
513
  index: 0,
428
- agent: "commentator",
514
+ agent: "reviewer",
429
515
  status: "running",
430
516
  currentTool: "read",
431
517
  currentToolArgs: "src/tui/render.ts",
@@ -437,11 +523,11 @@ describe("subagent async widget rendering", () => {
437
523
  };
438
524
 
439
525
  const collapsedText = buildWidgetLines([job], theme, 180).join("\n");
440
- assert.match(collapsedText, /Press configured-expand-key for live detail/);
526
+ assert.match(collapsedText, /Press\s+for live detail/);
441
527
  assert.doesNotMatch(collapsedText, /found renderWidget/);
442
528
 
443
529
  const expandedText = buildWidgetLines([job], theme, 180, true).join("\n");
444
- assert.doesNotMatch(expandedText, /Press configured-expand-key for live detail/);
530
+ assert.doesNotMatch(expandedText, /Press\s+for live detail/);
445
531
  assert.match(expandedText, /⎿ read: src\/tui\/render\.ts \| 2\.0s/);
446
532
  assert.match(expandedText, outputPathPattern("/tmp/1/output-0.log"));
447
533
  assert.match(expandedText, /grep: async widget/);
@@ -449,6 +535,164 @@ describe("subagent async widget rendering", () => {
449
535
  assert.match(expandedText, /checking expanded state/);
450
536
  });
451
537
 
538
+ it("compacts noisy repeated live output in expanded async widget rows", () => {
539
+ const now = Date.now();
540
+ const job = {
541
+ asyncId: "run-noisy",
542
+ asyncDir: "/tmp/noisy",
543
+ status: "running",
544
+ mode: "parallel",
545
+ agents: ["reviewer"],
546
+ activeParallelGroup: true,
547
+ runningSteps: 1,
548
+ completedSteps: 0,
549
+ stepsTotal: 1,
550
+ updatedAt: now,
551
+ steps: [
552
+ {
553
+ index: 0,
554
+ agent: "reviewer",
555
+ status: "running",
556
+ currentTool: "read",
557
+ currentToolArgs: "src/tui/render.ts",
558
+ currentToolStartedAt: now - 2000,
559
+ recentOutput: [
560
+ "I will read the required plan first.",
561
+ "I will inspect the exact head.",
562
+ "I will read the relevant implementation seams.",
563
+ "I will verify the action list.",
564
+ "I will inspect the public tool schema.",
565
+ "I will check the async launch path.",
566
+ "I will read agent default application path.",
567
+ ],
568
+ },
569
+ ],
570
+ };
571
+
572
+ const expandedText = buildWidgetLines([job], theme, 180, true).join("\n");
573
+ assert.match(expandedText, /↻ 7 progress updates/);
574
+ assert.match(expandedText, /latest: read agent default application path/);
575
+ assert.match(expandedText, /pattern: repeated short status lines/);
576
+ assert.doesNotMatch(expandedText, /required plan first/);
577
+ });
578
+
579
+ it("compacts repeated subagent status snapshots inside mixed live output", () => {
580
+ const now = Date.now();
581
+ const job = {
582
+ asyncId: "run-status-snapshots",
583
+ asyncDir: "/tmp/status-snapshots",
584
+ status: "running",
585
+ mode: "parallel",
586
+ agents: ["reviewer"],
587
+ activeParallelGroup: true,
588
+ runningSteps: 1,
589
+ completedSteps: 0,
590
+ stepsTotal: 1,
591
+ updatedAt: now,
592
+ steps: [
593
+ {
594
+ index: 0,
595
+ agent: "reviewer",
596
+ status: "running",
597
+ currentTool: "bash",
598
+ currentToolArgs: "set -euo pipefail",
599
+ currentToolStartedAt: now - 2000,
600
+ recentOutput: [
601
+ "reviewer · step 1/1 · 11 tool uses · 3m27s",
602
+ "Step 1/1: reviewer · running (gpt-5.5 · thinking xhigh) · 4 turns · 11 tool uses",
603
+ "reviewer · step 1/1 · 11 tool uses · 3m29s",
604
+ "Step 1/1: reviewer · running (gpt-5.5 · thinking xhigh) · 4 turns · 11 tool uses",
605
+ "reviewer · step 1/1 · 11 tool uses · 3m32s",
606
+ "Step 1/1: reviewer · running (gpt-5.5 · thinking xhigh) · 4 turns · 11 tool uses",
607
+ "repo=nicobailon/pi-subagents",
608
+ "sha=d61aca... | 2m32s",
609
+ "output: /var/folders/x/T/pi-subagents-uid-501/async-subagent-runs/run-status-snapshots/output.log",
610
+ ],
611
+ },
612
+ ],
613
+ };
614
+
615
+ const expandedText = buildWidgetLines([job], theme, 180, true).join("\n");
616
+ assert.match(expandedText, /↻ 7 progress updates/);
617
+ assert.match(expandedText, /latest: output: \/var\/folders\/x\/T\/pi-subagents-uid-501\/async-subagent-runs\/run-status-snapshots\/output.log/);
618
+ assert.match(expandedText, /repo=nicobailon\/pi-subagents/);
619
+ assert.match(expandedText, /sha=d61aca\.\.\. \| 2m32s/);
620
+ assert.doesNotMatch(expandedText, /3m27s/);
621
+ assert.doesNotMatch(expandedText, /3m29s/);
622
+ });
623
+
624
+ it("keeps mixed live output raw instead of hiding non-status lines", () => {
625
+ const now = Date.now();
626
+ const job = {
627
+ asyncId: "run-mixed",
628
+ asyncDir: "/tmp/mixed",
629
+ status: "running",
630
+ mode: "parallel",
631
+ agents: ["reviewer"],
632
+ activeParallelGroup: true,
633
+ runningSteps: 1,
634
+ completedSteps: 0,
635
+ stepsTotal: 1,
636
+ updatedAt: now,
637
+ steps: [
638
+ {
639
+ index: 0,
640
+ agent: "reviewer",
641
+ status: "running",
642
+ recentOutput: [
643
+ "I will read the required plan first.",
644
+ "I will inspect the exact head.",
645
+ "I will verify the action list.",
646
+ "I will check the async launch path.",
647
+ "error: failed to fetch review threads",
648
+ "details: GraphQL returned 502",
649
+ ],
650
+ },
651
+ ],
652
+ };
653
+
654
+ const expandedText = buildWidgetLines([job], theme, 180, true).join("\n");
655
+ assert.doesNotMatch(expandedText, /↻/);
656
+ assert.match(expandedText, /error: failed to fetch review threads/);
657
+ assert.match(expandedText, /details: GraphQL returned 502/);
658
+ });
659
+
660
+ it("keeps status-looking error signals visible", () => {
661
+ const now = Date.now();
662
+ const job = {
663
+ asyncId: "run-status-error",
664
+ asyncDir: "/tmp/status-error",
665
+ status: "running",
666
+ mode: "parallel",
667
+ agents: ["reviewer"],
668
+ activeParallelGroup: true,
669
+ runningSteps: 1,
670
+ completedSteps: 0,
671
+ stepsTotal: 1,
672
+ updatedAt: now,
673
+ steps: [
674
+ {
675
+ index: 0,
676
+ agent: "reviewer",
677
+ status: "running",
678
+ recentOutput: [
679
+ "Checking permissions: Access Denied",
680
+ "Checking token state: error from GitHub",
681
+ "Checking CI: failed",
682
+ "Checking retry: timed out",
683
+ "Checking fallback: unable to recover",
684
+ "Checking final status: rejected",
685
+ ],
686
+ },
687
+ ],
688
+ };
689
+
690
+ const expandedText = buildWidgetLines([job], theme, 180, true).join("\n");
691
+ assert.doesNotMatch(expandedText, /↻/);
692
+ assert.match(expandedText, /older signal line: Checking permissions: Access Denied/);
693
+ assert.match(expandedText, /Checking final status: rejected/);
694
+ });
695
+
452
696
  it("shows step detail and configured live detail key hint for running single async jobs with steps", () => {
453
697
  const now = Date.now();
454
698
  const job = {
@@ -456,13 +700,13 @@ describe("subagent async widget rendering", () => {
456
700
  asyncDir: "/tmp/single-run",
457
701
  status: "running",
458
702
  mode: "single",
459
- agents: ["builder"],
703
+ agents: ["worker"],
460
704
  stepsTotal: 1,
461
705
  updatedAt: now,
462
706
  steps: [
463
707
  {
464
708
  index: 0,
465
- agent: "builder",
709
+ agent: "worker",
466
710
  status: "running",
467
711
  currentTool: "read",
468
712
  currentToolArgs: "src/tui/render.ts",
@@ -473,15 +717,15 @@ describe("subagent async widget rendering", () => {
473
717
  };
474
718
 
475
719
  const collapsedText = buildWidgetLines([job], theme, 180).join("\n");
476
- assert.match(collapsedText, /async subagent builder · background/);
477
- assert.match(collapsedText, /Step 1\/1: builder · running/);
720
+ assert.match(collapsedText, /async subagent worker · background/);
721
+ assert.match(collapsedText, /Step 1\/1: worker · running/);
478
722
  assert.match(collapsedText, /⎿ read: src\/tui\/render\.ts \| 2\.0s/);
479
- assert.match(collapsedText, /Press configured-expand-key for live detail/);
723
+ assert.match(collapsedText, /Press\s+for live detail/);
480
724
  assert.match(collapsedText, outputPathPattern("/tmp/single-run/output-0.log"));
481
725
  assert.doesNotMatch(collapsedText, /reading render widget/);
482
726
 
483
727
  const expandedText = buildWidgetLines([job], theme, 180, true).join("\n");
484
- assert.doesNotMatch(expandedText, /Press configured-expand-key for live detail/);
728
+ assert.doesNotMatch(expandedText, /Press\s+for live detail/);
485
729
  assert.match(expandedText, /reading render widget/);
486
730
  });
487
731
 
@@ -493,7 +737,7 @@ describe("subagent async widget rendering", () => {
493
737
  asyncDir: "/tmp/single-no-steps",
494
738
  status: "running",
495
739
  mode: "single",
496
- agents: ["builder"],
740
+ agents: ["worker"],
497
741
  currentTool: "read",
498
742
  currentToolStartedAt: now - 1000,
499
743
  updatedAt: now,
@@ -502,7 +746,7 @@ describe("subagent async widget rendering", () => {
502
746
 
503
747
  assert.match(text, /⎿ read 1\.0s/);
504
748
  assert.doesNotMatch(text, /Step 1\/1/);
505
- assert.doesNotMatch(text, /Press configured-expand-key for live detail/);
749
+ assert.doesNotMatch(text, /Press\s+for live detail/);
506
750
  });
507
751
 
508
752
  it("includes logical chain context for active async chain parallel groups", () => {
@@ -512,7 +756,7 @@ describe("subagent async widget rendering", () => {
512
756
  asyncDir: "/tmp/chain",
513
757
  status: "running",
514
758
  mode: "chain",
515
- agents: ["commentator", "auditor"],
759
+ agents: ["reviewer", "auditor"],
516
760
  activeParallelGroup: true,
517
761
  currentStep: 1,
518
762
  chainStepCount: 3,
@@ -528,36 +772,42 @@ describe("subagent async widget rendering", () => {
528
772
  });
529
773
 
530
774
  it("uses logical chain steps after an async chain parallel group finishes", () => {
531
- const lines = buildWidgetLines([
532
- {
533
- asyncId: "run-chain",
534
- asyncDir: "/tmp/chain",
535
- status: "running",
536
- mode: "chain",
537
- agents: ["explorer", "commentator", "auditor", "writer"],
538
- activeParallelGroup: false,
539
- currentStep: 3,
540
- chainStepCount: 2,
541
- parallelGroups: [{ start: 0, count: 3, stepIndex: 0 }],
542
- stepsTotal: 4,
543
- steps: [
544
- { index: 0, agent: "explorer", status: "complete" },
545
- { index: 1, agent: "commentator", status: "complete" },
546
- { index: 2, agent: "auditor", status: "complete" },
547
- { index: 3, agent: "writer", status: "running", toolCount: 1 },
548
- ],
549
- },
550
- ], theme, 180);
775
+ const job = {
776
+ asyncId: "run-chain",
777
+ asyncDir: "/tmp/chain",
778
+ status: "running",
779
+ mode: "chain",
780
+ agents: ["scout", "reviewer", "auditor", "writer"],
781
+ activeParallelGroup: false,
782
+ currentStep: 3,
783
+ chainStepCount: 2,
784
+ parallelGroups: [{ start: 0, count: 3, stepIndex: 0 }],
785
+ stepsTotal: 4,
786
+ steps: [
787
+ { index: 0, agent: "scout", status: "complete" },
788
+ { index: 1, agent: "reviewer", status: "complete" },
789
+ { index: 2, agent: "auditor", status: "complete" },
790
+ { index: 3, agent: "writer", status: "running", toolCount: 1 },
791
+ ],
792
+ };
793
+ const lines = buildWidgetLines([job], theme, 180, false, 0);
551
794
 
552
795
  const text = lines.join("\n");
553
796
  assert.match(text, /async subagent chain \(2\)/);
554
797
  assert.match(text, /chain · step 2\/2/);
555
798
  assert.match(text, /Step 1\/2: parallel group · 3\/3 done/);
556
799
  assert.match(text, /Step 2\/2: writer · running · 1 tool use/);
557
- assert.match(text, /Press configured-expand-key for live detail/);
800
+ assert.match(text, /Press\s+for live detail/);
558
801
  assert.match(text, outputPathPattern("/tmp/chain/output-3.log"));
559
802
  assert.doesNotMatch(text, /step 4\/4/);
560
803
  assert.doesNotMatch(text, /Step 4\/4/);
804
+
805
+ const second = buildWidgetLines([job], theme, 180, false, 1);
806
+ assert.notEqual(
807
+ firstRunningGlyph(lines.find((line) => line.includes("Step 2/2")) ?? ""),
808
+ firstRunningGlyph(second.find((line) => line.includes("Step 2/2")) ?? ""),
809
+ "logical chain step glyph should advance with the render frame",
810
+ );
561
811
  });
562
812
 
563
813
  it("omits zero-running labels for pending active async parallel groups", () => {
@@ -567,7 +817,7 @@ describe("subagent async widget rendering", () => {
567
817
  asyncDir: "/tmp/parallel-pending",
568
818
  status: "running",
569
819
  mode: "parallel",
570
- agents: ["explorer", "commentator", "builder"],
820
+ agents: ["scout", "reviewer", "worker"],
571
821
  activeParallelGroup: true,
572
822
  runningSteps: 0,
573
823
  completedSteps: 0,
@@ -578,7 +828,7 @@ describe("subagent async widget rendering", () => {
578
828
  asyncDir: "/tmp/chain-pending",
579
829
  status: "running",
580
830
  mode: "chain",
581
- agents: ["commentator", "auditor"],
831
+ agents: ["reviewer", "auditor"],
582
832
  activeParallelGroup: true,
583
833
  currentStep: 0,
584
834
  chainStepCount: 2,
@@ -613,7 +863,7 @@ describe("subagent async widget rendering", () => {
613
863
  { asyncId: "run-2", asyncDir: "/tmp/2", status: "running", agents: ["a2"] },
614
864
  { asyncId: "run-3", asyncDir: "/tmp/3", status: "running", agents: ["a3"] },
615
865
  { asyncId: "run-4", asyncDir: "/tmp/4", status: "running", agents: ["a4"] },
616
- { asyncId: "queued-1", asyncDir: "/tmp/q", status: "queued", agents: ["architect"] },
866
+ { asyncId: "queued-1", asyncDir: "/tmp/q", status: "queued", agents: ["planner"] },
617
867
  ], theme, 120);
618
868
 
619
869
  assert.match(lines.join("\n"), /\+1 more \(1 queued\)/);
@@ -621,12 +871,12 @@ describe("subagent async widget rendering", () => {
621
871
 
622
872
  it("advances running widget glyphs when progress seed changes", () => {
623
873
  const first = buildWidgetLines([
624
- { asyncId: "run-progress", asyncDir: "/tmp/run", status: "running", agents: ["builder"], updatedAt: 11 },
625
- { asyncId: "run-other", asyncDir: "/tmp/other", status: "running", agents: ["explorer"], updatedAt: 0 },
874
+ { asyncId: "run-progress", asyncDir: "/tmp/run", status: "running", agents: ["worker"], updatedAt: 11 },
875
+ { asyncId: "run-other", asyncDir: "/tmp/other", status: "running", agents: ["scout"], updatedAt: 0 },
626
876
  ], theme, 120);
627
877
  const second = buildWidgetLines([
628
- { asyncId: "run-progress", asyncDir: "/tmp/run", status: "running", agents: ["builder"], updatedAt: 12 },
629
- { asyncId: "run-other", asyncDir: "/tmp/other", status: "running", agents: ["explorer"], updatedAt: 0 },
878
+ { asyncId: "run-progress", asyncDir: "/tmp/run", status: "running", agents: ["worker"], updatedAt: 12 },
879
+ { asyncId: "run-other", asyncDir: "/tmp/other", status: "running", agents: ["scout"], updatedAt: 0 },
630
880
  ], theme, 120);
631
881
 
632
882
  assert.notEqual(firstGrapheme(first[0] ?? ""), firstGrapheme(second[0] ?? ""), "header glyph should advance from changed progress");
@@ -636,19 +886,19 @@ describe("subagent async widget rendering", () => {
636
886
  asyncId: "run-step-progress",
637
887
  asyncDir: "/tmp/run-step",
638
888
  status: "running",
639
- agents: ["builder"],
889
+ agents: ["worker"],
640
890
  stepsTotal: 1,
641
891
  updatedAt: 20,
642
- steps: [{ agent: "builder", status: "running", currentToolStartedAt: 10 }],
892
+ steps: [{ agent: "worker", status: "running", currentToolStartedAt: 10 }],
643
893
  }], theme, 120);
644
894
  const secondStep = buildWidgetLines([{
645
895
  asyncId: "run-step-progress",
646
896
  asyncDir: "/tmp/run-step",
647
897
  status: "running",
648
- agents: ["builder"],
898
+ agents: ["worker"],
649
899
  stepsTotal: 1,
650
900
  updatedAt: 20,
651
- steps: [{ agent: "builder", status: "running", currentToolStartedAt: 11 }],
901
+ steps: [{ agent: "worker", status: "running", currentToolStartedAt: 11 }],
652
902
  }], theme, 120);
653
903
  assert.notEqual(
654
904
  firstRunningGlyph(firstStep.find((line) => line.includes("Step 1/1")) ?? ""),
@@ -662,7 +912,7 @@ describe("subagent async widget rendering", () => {
662
912
  asyncId: "run-stable",
663
913
  asyncDir: "/tmp/run",
664
914
  status: "running",
665
- agents: ["builder"],
915
+ agents: ["worker"],
666
916
  startedAt: 1_000,
667
917
  updatedAt: 3_000,
668
918
  currentTool: "read",
@@ -677,13 +927,73 @@ describe("subagent async widget rendering", () => {
677
927
  assert.equal(firstGrapheme(first[1] ?? ""), firstGrapheme(second[1] ?? ""));
678
928
  });
679
929
 
680
- it("does not animate queued-only widgets", async () => {
681
- const ui = createUiContext();
682
- renderWidget(ui.ctx as never, [{ asyncId: "queued-only", asyncDir: "/tmp/queued", status: "queued", agents: ["architect"] }]);
683
- const initialWidgetCount = ui.widgets.length;
684
- await new Promise((resolve) => setTimeout(resolve, 190));
685
- assert.equal(ui.widgets.length, initialWidgetCount, "static queued widget should not refresh at animation cadence");
686
- assert.equal(ui.renderRequests, 0);
930
+ it("advances component running glyphs with the render clock", () => {
931
+ const originalNow = Date.now;
932
+ let renderRequests = 0;
933
+ try {
934
+ Date.now = () => 1_000;
935
+ const ui = createUiContext();
936
+ renderWidget(ui.ctx as never, [{
937
+ asyncId: "run-stable",
938
+ asyncDir: "/tmp/run",
939
+ status: "running",
940
+ mode: "parallel",
941
+ agents: ["reviewer"],
942
+ activeParallelGroup: true,
943
+ runningSteps: 1,
944
+ completedSteps: 0,
945
+ stepsTotal: 1,
946
+ updatedAt: 1_000,
947
+ steps: [{ index: 0, agent: "reviewer", status: "running" }],
948
+ }, {
949
+ asyncId: "run-other",
950
+ asyncDir: "/tmp/other",
951
+ status: "running",
952
+ mode: "single",
953
+ agents: ["scout"],
954
+ updatedAt: 1_000,
955
+ }]);
956
+ const component = (ui.widgets.at(-1) as (_tui: { requestRender(): void }, widgetTheme: typeof theme) => { render(width: number): string[] })(
957
+ { requestRender: () => { renderRequests += 1; } },
958
+ theme,
959
+ );
960
+ const first = component.render(180);
961
+
962
+ Date.now = () => 1_250;
963
+ const second = component.render(180);
964
+ const withoutRunningGlyphs = (lines: string[]) => lines.map((line) => line.replace(/[⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏]/gu, ""));
965
+
966
+ assert.equal(renderRequests, 0, "the component must not own the repaint cadence");
967
+ assert.notDeepEqual(second, first, "the render clock should advance quiet running glyphs");
968
+ assert.deepEqual(withoutRunningGlyphs(second), withoutRunningGlyphs(first), "only running glyphs should change");
969
+ assert.notEqual(firstRunningGlyph(first[0] ?? ""), firstRunningGlyph(second[0] ?? ""), "header glyph should advance");
970
+ assert.notEqual(firstRunningGlyph(first[1] ?? ""), firstRunningGlyph(second[1] ?? ""), "job glyph should advance");
971
+ assert.notEqual(
972
+ firstRunningGlyph(first.find((line) => line.includes("Agent 1/1")) ?? ""),
973
+ firstRunningGlyph(second.find((line) => line.includes("Agent 1/1")) ?? ""),
974
+ "step glyph should advance",
975
+ );
976
+ } finally {
977
+ Date.now = originalNow;
978
+ renderWidget(createUiContext().ctx as never, []);
979
+ }
980
+ });
981
+
982
+ it("does not animate queued-only widgets", () => {
983
+ const originalNow = Date.now;
984
+ try {
985
+ Date.now = () => 1_000;
986
+ const ui = createUiContext();
987
+ renderWidget(ui.ctx as never, [{ asyncId: "queued-only", asyncDir: "/tmp/queued", status: "queued", agents: ["planner"] }]);
988
+ const component = (ui.widgets.at(-1) as (_tui: unknown, widgetTheme: typeof theme) => { render(width: number): string[] })(undefined, theme);
989
+ const first = component.render(180);
990
+ Date.now = () => 1_250;
991
+ assert.deepEqual(component.render(180), first);
992
+ assert.equal(ui.renderRequests, 0);
993
+ } finally {
994
+ Date.now = originalNow;
995
+ renderWidget(createUiContext().ctx as never, []);
996
+ }
687
997
  });
688
998
 
689
999
  it("clears legacy result row animation timers", async () => {
@@ -703,7 +1013,7 @@ describe("subagent async widget rendering", () => {
703
1013
 
704
1014
  it("does not refresh running widgets at animation cadence", async () => {
705
1015
  const ui = createUiContext();
706
- renderWidget(ui.ctx as never, [{ asyncId: "run-static", asyncDir: "/tmp/run", status: "running", agents: ["explorer"] }]);
1016
+ renderWidget(ui.ctx as never, [{ asyncId: "run-static", asyncDir: "/tmp/run", status: "running", agents: ["scout"] }]);
707
1017
  const initialWidgetCount = ui.widgets.length;
708
1018
  await new Promise((resolve) => setTimeout(resolve, 190));
709
1019
  assert.equal(ui.widgets.length, initialWidgetCount, "running widget should wait for status updates instead of animation ticks");