@selesai/code 0.13.15 → 0.13.18

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 (473) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/README.md +2 -14
  3. package/dist/bun/cli.d.ts +3 -1
  4. package/dist/bun/cli.js +3 -9
  5. package/dist/bun/{register-bedrock.js → runtime-setup.js} +5 -0
  6. package/dist/bun/sandbox-env-setup.d.ts +1 -0
  7. package/dist/bun/sandbox-env-setup.js +3 -0
  8. package/dist/cli/auth-command.d.ts +23 -0
  9. package/dist/cli/auth-command.js +102 -0
  10. package/dist/cli/config-selector.js +2 -1
  11. package/dist/cli/setup.d.ts +1 -0
  12. package/dist/cli/setup.js +11 -0
  13. package/dist/cli.js +2 -14
  14. package/dist/config.d.ts +3 -2
  15. package/dist/config.js +9 -4
  16. package/dist/core/agent-session-runtime.js +15 -7
  17. package/dist/core/agent-session.d.ts +2 -6
  18. package/dist/core/agent-session.js +15 -4
  19. package/dist/core/compaction/branch-summarization.d.ts +1 -1
  20. package/dist/core/compaction/branch-summarization.js +2 -1
  21. package/dist/core/extensions/loader.js +3 -0
  22. package/dist/core/extensions/types.d.ts +16 -2
  23. package/dist/core/http-dispatcher.js +2 -0
  24. package/dist/core/keybindings.d.ts +5 -0
  25. package/dist/core/keybindings.js +4 -0
  26. package/dist/core/messages.d.ts +1 -1
  27. package/dist/core/model-config.d.ts +15 -0
  28. package/dist/core/model-config.js +3 -0
  29. package/dist/core/model-runtime.d.ts +1 -0
  30. package/dist/core/model-runtime.js +5 -2
  31. package/dist/core/provider-composer.js +8 -2
  32. package/dist/core/session-export.d.ts +3 -0
  33. package/dist/core/session-export.js +31 -0
  34. package/dist/core/session-manager.d.ts +3 -2
  35. package/dist/core/session-manager.js +40 -13
  36. package/dist/core/skills.d.ts +1 -1
  37. package/dist/core/skills.js +4 -2
  38. package/dist/core/system-prompt.js +10 -10
  39. package/dist/core/tools/bash.js +3 -117
  40. package/dist/core/tools/edit.d.ts +1 -12
  41. package/dist/core/tools/edit.js +5 -163
  42. package/dist/core/tools/find.js +4 -55
  43. package/dist/core/tools/grep.js +4 -60
  44. package/dist/core/tools/ls.js +4 -49
  45. package/dist/core/tools/read.d.ts +4 -0
  46. package/dist/core/tools/read.js +10 -122
  47. package/dist/core/tools/renderers/bash.d.ts +11 -0
  48. package/dist/core/tools/renderers/bash.js +129 -0
  49. package/dist/core/tools/renderers/edit.d.ts +22 -0
  50. package/dist/core/tools/renderers/edit.js +166 -0
  51. package/dist/core/tools/renderers/find.d.ts +9 -0
  52. package/dist/core/tools/renderers/find.js +63 -0
  53. package/dist/core/tools/renderers/grep.d.ts +9 -0
  54. package/dist/core/tools/renderers/grep.js +68 -0
  55. package/dist/core/tools/renderers/index.d.ts +27 -0
  56. package/dist/core/tools/renderers/index.js +46 -0
  57. package/dist/core/tools/renderers/ls.d.ts +9 -0
  58. package/dist/core/tools/renderers/ls.js +57 -0
  59. package/dist/core/tools/renderers/read.d.ts +10 -0
  60. package/dist/core/tools/renderers/read.js +128 -0
  61. package/dist/core/tools/renderers/write.d.ts +9 -0
  62. package/dist/core/tools/renderers/write.js +152 -0
  63. package/dist/core/tools/write.js +5 -146
  64. package/dist/extensions/capability-gateway/index.ts +12 -1
  65. package/dist/extensions/capability-gateway/integration.test.ts +23 -0
  66. package/dist/extensions/pi-hermes-memory/CHANGELOG.md +18 -0
  67. package/dist/extensions/pi-hermes-memory/README.md +16 -12
  68. package/dist/extensions/pi-hermes-memory/docs/ROADMAP.md +1 -1
  69. package/dist/extensions/pi-hermes-memory/package-lock.json +587 -62
  70. package/dist/extensions/pi-hermes-memory/package.json +4 -4
  71. package/dist/extensions/pi-hermes-memory/src/config.ts +32 -0
  72. package/dist/extensions/pi-hermes-memory/src/constants.ts +12 -2
  73. package/dist/extensions/pi-hermes-memory/src/handlers/background-review.ts +109 -51
  74. package/dist/extensions/pi-hermes-memory/src/handlers/index-sessions.ts +9 -3
  75. package/dist/extensions/pi-hermes-memory/src/handlers/review-memory-ops.ts +257 -98
  76. package/dist/extensions/pi-hermes-memory/src/handlers/session-backfill.ts +9 -2
  77. package/dist/extensions/pi-hermes-memory/src/handlers/sync-markdown-memories.ts +5 -0
  78. package/dist/extensions/pi-hermes-memory/src/index.ts +22 -2
  79. package/dist/extensions/pi-hermes-memory/src/paths.ts +1 -1
  80. package/dist/extensions/pi-hermes-memory/src/store/db.ts +6 -0
  81. package/dist/extensions/pi-hermes-memory/src/store/fts-query.ts +58 -1
  82. package/dist/extensions/pi-hermes-memory/src/store/memory-store.ts +60 -8
  83. package/dist/extensions/pi-hermes-memory/src/store/session-indexer.ts +169 -7
  84. package/dist/extensions/pi-hermes-memory/src/store/session-search.ts +7 -21
  85. package/dist/extensions/pi-hermes-memory/src/store/sqlite-memory-store.ts +134 -15
  86. package/dist/extensions/pi-hermes-memory/src/tools/memory-search-tool.ts +4 -2
  87. package/dist/extensions/pi-hermes-memory/src/tools/memory-tool.ts +24 -9
  88. package/dist/extensions/pi-hermes-memory/src/types.ts +11 -0
  89. package/dist/extensions/pi-hermes-memory/tests/config.test.ts +42 -0
  90. package/dist/extensions/pi-hermes-memory/tests/handlers/background-review.test.ts +159 -3
  91. package/dist/extensions/pi-hermes-memory/tests/handlers/review-memory-ops.test.ts +452 -0
  92. package/dist/extensions/pi-hermes-memory/tests/handlers/session-backfill.test.ts +39 -0
  93. package/dist/extensions/pi-hermes-memory/tests/integration/corruption-recovery-integration.test.ts +91 -0
  94. package/dist/extensions/pi-hermes-memory/tests/store/db.test.ts +29 -0
  95. package/dist/extensions/pi-hermes-memory/tests/store/fts-query.test.ts +116 -0
  96. package/dist/extensions/pi-hermes-memory/tests/store/memory-store.test.ts +163 -0
  97. package/dist/extensions/pi-hermes-memory/tests/store/session-indexer.test.ts +233 -0
  98. package/dist/extensions/pi-hermes-memory/tests/store/session-search.test.ts +12 -0
  99. package/dist/extensions/pi-hermes-memory/tests/store/sqlite-memory-store.test.ts +175 -0
  100. package/dist/extensions/pi-hermes-memory/tests/store/sqlite-native.test.ts +2 -2
  101. package/dist/extensions/pi-hermes-memory/tests/tools/memory-search-tool.test.ts +22 -0
  102. package/dist/extensions/pi-hermes-memory/tests/tools/memory-tool.test.ts +37 -1
  103. package/dist/extensions/pi-intercom/CHANGELOG.md +13 -0
  104. package/dist/extensions/pi-intercom/README.md +16 -2
  105. package/dist/extensions/pi-intercom/broker/spawn.test.ts +19 -2
  106. package/dist/extensions/pi-intercom/broker/spawn.ts +4 -4
  107. package/dist/extensions/pi-intercom/index.ts +1 -1
  108. package/dist/extensions/pi-intercom/intercom.integration.test.ts +121 -2
  109. package/dist/extensions/pi-intercom/package.json +1 -1
  110. package/dist/extensions/pi-intercom/project-agent.test.ts +1 -1
  111. package/dist/extensions/pi-intercom/project-agent.ts +1 -6
  112. package/dist/extensions/pi-intercom/skills/pi-intercom/SKILL.md +7 -6
  113. package/dist/extensions/pi-rewind-hook/index.test.ts +7 -0
  114. package/dist/extensions/pi-subagents/.github/workflows/test.yml +36 -4
  115. package/dist/extensions/pi-subagents/CHANGELOG.md +120 -0
  116. package/dist/extensions/pi-subagents/README.md +3 -3
  117. package/dist/extensions/pi-subagents/agents/researcher.md +23 -13
  118. package/dist/extensions/pi-subagents/agents/reviewer.md +1 -1
  119. package/dist/extensions/pi-subagents/agents/scout.md +1 -1
  120. package/dist/extensions/pi-subagents/docs/agents.md +32 -16
  121. package/dist/extensions/pi-subagents/docs/configuration.md +41 -15
  122. package/dist/extensions/pi-subagents/docs/extension-api.md +109 -6
  123. package/dist/extensions/pi-subagents/docs/missions.md +2 -0
  124. package/dist/extensions/pi-subagents/docs/models.md +58 -1
  125. package/dist/extensions/pi-subagents/docs/observability.md +50 -12
  126. package/dist/extensions/pi-subagents/docs/tool-reference.md +17 -10
  127. package/dist/extensions/pi-subagents/docs/watchdog.md +1 -1
  128. package/dist/extensions/pi-subagents/docs/workflows.md +26 -9
  129. package/dist/extensions/pi-subagents/package-lock.json +747 -177
  130. package/dist/extensions/pi-subagents/package.json +6 -4
  131. package/dist/extensions/pi-subagents/runner-server-preload.mjs +13 -0
  132. package/dist/extensions/pi-subagents/skills/pi-subagents/SKILL.md +2 -1
  133. package/dist/extensions/pi-subagents/skills/pi-subagents/references/constraints-and-recipes.md +1 -1
  134. package/dist/extensions/pi-subagents/skills/pi-subagents/references/execution-controls.md +21 -4
  135. package/dist/extensions/pi-subagents/skills/pi-subagents/references/management-authoring-rpc.md +2 -1
  136. package/dist/extensions/pi-subagents/skills/pi-subagents/references/multi-lane-orchestration.md +2 -0
  137. package/dist/extensions/pi-subagents/src/agents/advertised-agent-prompt.ts +63 -0
  138. package/dist/extensions/pi-subagents/src/agents/agent-management.ts +61 -16
  139. package/dist/extensions/pi-subagents/src/agents/agent-serializer.ts +2 -0
  140. package/dist/extensions/pi-subagents/src/agents/agents.ts +8 -0
  141. package/dist/extensions/pi-subagents/src/api/capability-ceiling.ts +0 -1
  142. package/dist/extensions/pi-subagents/src/api/{pi-args.ts → child-tool-plan.ts} +1 -1
  143. package/dist/extensions/pi-subagents/src/api/preflight.ts +7 -4
  144. package/dist/extensions/pi-subagents/src/api/shared-types.ts +2 -2
  145. package/dist/extensions/pi-subagents/src/api/workflow-resources.ts +6 -0
  146. package/dist/extensions/pi-subagents/src/extension/config.ts +4 -2
  147. package/dist/extensions/pi-subagents/src/extension/doctor.ts +2 -10
  148. package/dist/extensions/pi-subagents/src/extension/fanout-child.ts +9 -11
  149. package/dist/extensions/pi-subagents/src/extension/index.ts +99 -10
  150. package/dist/extensions/pi-subagents/src/extension/public-execution.ts +13 -0
  151. package/dist/extensions/pi-subagents/src/extension/rpc.ts +7 -23
  152. package/dist/extensions/pi-subagents/src/extension/schemas.ts +11 -8
  153. package/dist/extensions/pi-subagents/src/extension/tool-description.ts +25 -7
  154. package/dist/extensions/pi-subagents/src/integrations/pi-web-session-liveness.ts +73 -0
  155. package/dist/extensions/pi-subagents/src/intercom/native-supervisor-channel.ts +228 -136
  156. package/dist/extensions/pi-subagents/src/intercom/supervisor-ui.ts +244 -0
  157. package/dist/extensions/pi-subagents/src/missions/workflow-state.ts +37 -16
  158. package/dist/extensions/pi-subagents/src/runs/background/active-async-capacity.ts +18 -18
  159. package/dist/extensions/pi-subagents/src/runs/background/async-execution.ts +51 -25
  160. package/dist/extensions/pi-subagents/src/runs/background/async-job-tracker.ts +46 -3
  161. package/dist/extensions/pi-subagents/src/runs/background/async-resume.ts +14 -3
  162. package/dist/extensions/pi-subagents/src/runs/background/async-retention.ts +9 -0
  163. package/dist/extensions/pi-subagents/src/runs/background/async-status-snapshot.ts +10 -12
  164. package/dist/extensions/pi-subagents/src/runs/background/async-status.ts +18 -15
  165. package/dist/extensions/pi-subagents/src/runs/background/auto-drain.ts +40 -29
  166. package/dist/extensions/pi-subagents/src/runs/background/chain-root-attachment.ts +8 -0
  167. package/dist/extensions/pi-subagents/src/runs/background/control-channel.ts +79 -247
  168. package/dist/extensions/pi-subagents/src/runs/background/notify.ts +88 -12
  169. package/dist/extensions/pi-subagents/src/runs/background/owned-process-tree.ts +6 -6
  170. package/dist/extensions/pi-subagents/src/runs/background/process-terminal.ts +24 -24
  171. package/dist/extensions/pi-subagents/src/runs/background/retained-nested-route-tracker.ts +96 -0
  172. package/dist/extensions/pi-subagents/src/runs/background/run-child-session.ts +642 -0
  173. package/dist/extensions/pi-subagents/src/runs/background/run-status.ts +75 -6
  174. package/dist/extensions/pi-subagents/src/runs/background/runner-aliases.ts +163 -0
  175. package/dist/extensions/pi-subagents/src/runs/background/runner-child-launch.ts +86 -0
  176. package/dist/extensions/pi-subagents/src/runs/background/runner-child-sessions.ts +31 -0
  177. package/dist/extensions/pi-subagents/src/runs/background/scheduled-runs.ts +18 -4
  178. package/dist/extensions/pi-subagents/src/runs/background/stale-run-reconciler.ts +3 -1
  179. package/dist/extensions/pi-subagents/src/runs/background/subagent-runner.ts +597 -1092
  180. package/dist/extensions/pi-subagents/src/runs/background/subagent-wait.ts +3 -0
  181. package/dist/extensions/pi-subagents/src/runs/background/wait-completions.ts +4 -0
  182. package/dist/extensions/pi-subagents/src/runs/foreground/async-steering-action.ts +20 -17
  183. package/dist/extensions/pi-subagents/src/runs/foreground/execution.ts +296 -394
  184. package/dist/extensions/pi-subagents/src/runs/foreground/foreground-control.ts +4 -0
  185. package/dist/extensions/pi-subagents/src/runs/foreground/foreground-history.ts +3 -1
  186. package/dist/extensions/pi-subagents/src/runs/foreground/prompt-audit.ts +9 -5
  187. package/dist/extensions/pi-subagents/src/runs/foreground/subagent-executor.ts +630 -283
  188. package/dist/extensions/pi-subagents/src/runs/foreground/workflow-detach-reconcile.ts +8 -5
  189. package/dist/extensions/pi-subagents/src/runs/foreground/workflow-foreground-steering.ts +78 -98
  190. package/dist/extensions/pi-subagents/src/runs/shared/abort-recovery.ts +3 -3
  191. package/dist/extensions/pi-subagents/src/runs/shared/acceptance.ts +16 -3
  192. package/dist/extensions/pi-subagents/src/runs/shared/agent-contract.ts +1 -1
  193. package/dist/extensions/pi-subagents/src/runs/shared/async-status-projection.ts +47 -47
  194. package/dist/extensions/pi-subagents/src/runs/shared/capability-ceiling.ts +1 -2
  195. package/dist/extensions/pi-subagents/src/runs/shared/child-hooks.ts +174 -0
  196. package/dist/extensions/pi-subagents/src/runs/shared/child-identity.ts +14 -3
  197. package/dist/extensions/pi-subagents/src/runs/shared/child-launch.ts +319 -0
  198. package/dist/extensions/pi-subagents/src/runs/shared/child-lifecycle.ts +25 -0
  199. package/dist/extensions/pi-subagents/src/runs/shared/child-runtime-config.ts +126 -0
  200. package/dist/extensions/pi-subagents/src/runs/shared/child-session.ts +373 -0
  201. package/dist/extensions/pi-subagents/src/runs/shared/child-tool-plan.ts +530 -0
  202. package/dist/extensions/pi-subagents/src/runs/shared/completion-evidence.ts +2 -2
  203. package/dist/extensions/pi-subagents/src/runs/shared/completion-guard.ts +2 -1
  204. package/dist/extensions/pi-subagents/src/runs/shared/external-cli-preflight.ts +16 -0
  205. package/dist/extensions/pi-subagents/src/runs/shared/host-step-status.ts +11 -11
  206. package/dist/extensions/pi-subagents/src/runs/shared/llm-intent-arbiter.ts +30 -20
  207. package/dist/extensions/pi-subagents/src/runs/shared/mcp-direct-tool-allowlist.ts +5 -4
  208. package/dist/extensions/pi-subagents/src/runs/shared/model-exclusions.ts +84 -15
  209. package/dist/extensions/pi-subagents/src/runs/shared/model-fallback.ts +88 -12
  210. package/dist/extensions/pi-subagents/src/runs/shared/nested-events.ts +37 -53
  211. package/dist/extensions/pi-subagents/src/runs/shared/nested-path.ts +1 -1
  212. package/dist/extensions/pi-subagents/src/runs/shared/orca-progress-tabs.ts +18 -7
  213. package/dist/extensions/pi-subagents/src/runs/shared/parallel-handoff.ts +57 -12
  214. package/dist/extensions/pi-subagents/src/runs/shared/parallel-utils.ts +3 -4
  215. package/dist/extensions/pi-subagents/src/runs/shared/permissions.ts +0 -11
  216. package/dist/extensions/pi-subagents/src/runs/shared/process-signal.ts +4 -1
  217. package/dist/extensions/pi-subagents/src/runs/shared/readonly-drain-observation.ts +42 -0
  218. package/dist/extensions/pi-subagents/src/runs/shared/readonly-model-continuation.ts +69 -0
  219. package/dist/extensions/pi-subagents/src/runs/shared/readonly-session-evidence.ts +307 -0
  220. package/dist/extensions/pi-subagents/src/runs/shared/run-fanout-budget.ts +8 -21
  221. package/dist/extensions/pi-subagents/src/runs/shared/runtime-acknowledged-extensions.ts +3 -30
  222. package/dist/extensions/pi-subagents/src/runs/shared/structured-output.ts +17 -4
  223. package/dist/extensions/pi-subagents/src/runs/shared/subagent-control.ts +2 -0
  224. package/dist/extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.ts +99 -386
  225. package/dist/extensions/pi-subagents/src/runs/shared/tool-availability.ts +18 -62
  226. package/dist/extensions/pi-subagents/src/runs/shared/tool-budget.ts +0 -14
  227. package/dist/extensions/pi-subagents/src/runs/shared/worktree-cleanup-plan.ts +31 -9
  228. package/dist/extensions/pi-subagents/src/runs/shared/worktree-setup-command.ts +190 -0
  229. package/dist/extensions/pi-subagents/src/runs/shared/worktree.ts +506 -226
  230. package/dist/extensions/pi-subagents/src/shared/child-session-name.ts +1 -1
  231. package/dist/extensions/pi-subagents/src/shared/jsonl-writer.ts +11 -0
  232. package/dist/extensions/pi-subagents/src/shared/model-response-aliases.ts +13 -0
  233. package/dist/extensions/pi-subagents/src/shared/thinking-ceiling.ts +0 -6
  234. package/dist/extensions/pi-subagents/src/shared/types.ts +145 -89
  235. package/dist/extensions/pi-subagents/src/shared/utils.ts +13 -6
  236. package/dist/extensions/pi-subagents/src/shared/watch-strategy.ts +2 -0
  237. package/dist/extensions/pi-subagents/src/shared/workflow-child-permit.ts +18 -13
  238. package/dist/extensions/pi-subagents/src/slash/slash-commands.ts +0 -6
  239. package/dist/extensions/pi-subagents/src/tui/fleet-status.ts +1 -1
  240. package/dist/extensions/pi-subagents/src/tui/fleet.ts +11 -6
  241. package/dist/extensions/pi-subagents/src/tui/render.ts +277 -46
  242. package/dist/extensions/pi-subagents/src/watchdog/child-status.ts +0 -1
  243. package/dist/extensions/pi-subagents/src/watchdog/register-child.ts +12 -12
  244. package/dist/extensions/pi-subagents/src/workflows/chat-progress.ts +3 -3
  245. package/dist/extensions/pi-subagents/src/workflows/scripted-workflow.ts +116 -15
  246. package/dist/extensions/pi-subagents/src/workflows/workflow-checklist.ts +15 -18
  247. package/dist/extensions/pi-subagents/src/workflows/workflow-child-summary.ts +57 -8
  248. package/dist/extensions/pi-subagents/src/workflows/workflow-preflight.ts +19 -19
  249. package/dist/extensions/pi-subagents/src/workflows/workflow-receipt.ts +3 -3
  250. package/dist/extensions/pi-subagents/src/workflows/workflow-resources.ts +97 -22
  251. package/dist/extensions/pi-subagents/src/workflows/workflow-settlement.ts +3 -0
  252. package/dist/extensions/pi-subagents/test/integration/acceptance-file-report.test.ts +336 -21
  253. package/dist/extensions/pi-subagents/test/integration/async-execution.part-1.test.ts +1181 -0
  254. package/dist/extensions/pi-subagents/test/integration/async-execution.part-2.test.ts +2240 -0
  255. package/dist/extensions/pi-subagents/test/integration/async-execution.part-3.test.ts +2268 -0
  256. package/dist/extensions/pi-subagents/test/integration/async-execution.part-4.test.ts +1512 -0
  257. package/dist/extensions/pi-subagents/test/integration/async-job-tracker.test.ts +231 -16
  258. package/dist/extensions/pi-subagents/test/integration/error-handling.test.ts +4 -18
  259. package/dist/extensions/pi-subagents/test/integration/foreign-workflow-steering.test.ts +95 -0
  260. package/dist/extensions/pi-subagents/test/integration/fork-context-execution.test.ts +9 -15
  261. package/dist/extensions/pi-subagents/test/integration/in-process-child.test.ts +374 -0
  262. package/dist/extensions/pi-subagents/test/integration/intercom-result-delivery.test.ts +20 -10
  263. package/dist/extensions/pi-subagents/test/integration/orca-progress-tabs.test.ts +18 -6
  264. package/dist/extensions/pi-subagents/test/integration/recovered-assistant-error.test.ts +151 -0
  265. package/dist/extensions/pi-subagents/test/integration/render-fork-badge.test.ts +42 -1
  266. package/dist/extensions/pi-subagents/test/integration/render-widget.test.ts +150 -25
  267. package/dist/extensions/pi-subagents/test/integration/result-publication.test.ts +354 -0
  268. package/dist/extensions/pi-subagents/test/integration/shared-cwd-terminal-evidence.test.ts +117 -0
  269. package/dist/extensions/pi-subagents/test/integration/single-execution.part-1.test.ts +3678 -0
  270. package/dist/extensions/pi-subagents/test/integration/{single-execution.test.ts → single-execution.part-2.test.ts} +500 -4207
  271. package/dist/extensions/pi-subagents/test/integration/slash-commands.test.ts +1 -2
  272. package/dist/extensions/pi-subagents/test/integration/workflow-result-publication.test.ts +127 -0
  273. package/dist/extensions/pi-subagents/test/integration/workflow-steer-inbox.test.ts +365 -0
  274. package/dist/extensions/pi-subagents/test/smoke/pi085-child.ts +31 -0
  275. package/dist/extensions/pi-subagents/test/smoke/pi085-clean-install.mjs +74 -0
  276. package/dist/extensions/pi-subagents/test/smoke/pi085-extension.ts +16 -0
  277. package/dist/extensions/pi-subagents/test/support/async-execution-fixture.ts +699 -0
  278. package/dist/extensions/pi-subagents/test/support/fake-child-session.ts +418 -0
  279. package/dist/extensions/pi-subagents/test/support/foreign-workflow-steer-host.mjs +13 -0
  280. package/dist/extensions/pi-subagents/test/support/mock-pi.ts +30 -76
  281. package/dist/extensions/pi-subagents/test/support/notify-diagnostics-fixture.ts +84 -0
  282. package/dist/extensions/pi-subagents/test/support/result-publication-capacity-preload.mjs +70 -0
  283. package/dist/extensions/pi-subagents/test/support/runner-child-session-factory.ts +17 -0
  284. package/dist/extensions/pi-subagents/test/support/single-execution-fixture.ts +390 -0
  285. package/dist/extensions/pi-subagents/test/unit/acceptance-compaction.test.ts +120 -0
  286. package/dist/extensions/pi-subagents/test/unit/acceptance.test.ts +24 -3
  287. package/dist/extensions/pi-subagents/test/unit/advertised-agent-prompt.test.ts +87 -0
  288. package/dist/extensions/pi-subagents/test/unit/advertised-agent-refresh.test.ts +163 -0
  289. package/dist/extensions/pi-subagents/test/unit/agent-frontmatter.test.ts +70 -31
  290. package/dist/extensions/pi-subagents/test/unit/agent-management.test.ts +78 -3
  291. package/dist/extensions/pi-subagents/test/unit/agent-overrides.test.ts +2 -8
  292. package/dist/extensions/pi-subagents/test/unit/async-execution.test.ts +1 -1
  293. package/dist/extensions/pi-subagents/test/unit/async-interrupt-action.test.ts +73 -66
  294. package/dist/extensions/pi-subagents/test/unit/async-recovery-descriptor.test.ts +51 -1
  295. package/dist/extensions/pi-subagents/test/unit/async-retention.test.ts +49 -1
  296. package/dist/extensions/pi-subagents/test/unit/async-spawn-preload.test.ts +103 -0
  297. package/dist/extensions/pi-subagents/test/unit/async-status-projection.test.ts +3 -3
  298. package/dist/extensions/pi-subagents/test/unit/capability-ceiling-agent-allowlist.test.ts +9 -8
  299. package/dist/extensions/pi-subagents/test/unit/capability-ceiling.test.ts +10 -7
  300. package/dist/extensions/pi-subagents/test/unit/chain-root-attachment.test.ts +48 -6
  301. package/dist/extensions/pi-subagents/test/unit/child-runtime-config.test.ts +90 -0
  302. package/dist/extensions/pi-subagents/test/unit/{pi-args-permission-system.test.ts → child-tool-plan-permission-system.test.ts} +48 -86
  303. package/dist/extensions/pi-subagents/test/unit/child-tool-plan.test.ts +33 -0
  304. package/dist/extensions/pi-subagents/test/unit/compaction-resume.test.ts +18 -18
  305. package/dist/extensions/pi-subagents/test/unit/completion-evidence.test.ts +9 -9
  306. package/dist/extensions/pi-subagents/test/unit/completion-guard.test.ts +8 -7
  307. package/dist/extensions/pi-subagents/test/unit/control-channel.test.ts +225 -65
  308. package/dist/extensions/pi-subagents/test/unit/extension-bindings.test.ts +17 -22
  309. package/dist/extensions/pi-subagents/test/unit/fleet-status.test.ts +11 -1
  310. package/dist/extensions/pi-subagents/test/unit/fleet.test.ts +47 -3
  311. package/dist/extensions/pi-subagents/test/unit/foreign-workflow-steering.test.ts +74 -0
  312. package/dist/extensions/pi-subagents/test/unit/fork-cache-key.test.ts +23 -29
  313. package/dist/extensions/pi-subagents/test/unit/host-peer-runtime-imports.test.ts +96 -4
  314. package/dist/extensions/pi-subagents/test/unit/host-step-status.test.ts +4 -4
  315. package/dist/extensions/pi-subagents/test/unit/index-child-registration.test.ts +116 -55
  316. package/dist/extensions/pi-subagents/test/unit/index-segment.test.ts +58 -1
  317. package/dist/extensions/pi-subagents/test/unit/llm-intent-arbiter.test.ts +104 -3
  318. package/dist/extensions/pi-subagents/test/unit/mission-lifecycle.test.ts +10 -1
  319. package/dist/extensions/pi-subagents/test/unit/mission-store.test.ts +31 -1
  320. package/dist/extensions/pi-subagents/test/unit/model-exclusions.test.ts +102 -51
  321. package/dist/extensions/pi-subagents/test/unit/model-fallback.test.ts +196 -6
  322. package/dist/extensions/pi-subagents/test/unit/native-supervisor-channel.test.ts +181 -38
  323. package/dist/extensions/pi-subagents/test/unit/nested-control.test.ts +62 -70
  324. package/dist/extensions/pi-subagents/test/unit/nested-events.test.ts +58 -53
  325. package/dist/extensions/pi-subagents/test/unit/notify-diagnostics.test.ts +42 -0
  326. package/dist/extensions/pi-subagents/test/unit/notify.test.ts +84 -0
  327. package/dist/extensions/pi-subagents/test/unit/orca-progress-tabs.test.ts +13 -5
  328. package/dist/extensions/pi-subagents/test/unit/package-manifest.test.ts +21 -5
  329. package/dist/extensions/pi-subagents/test/unit/parallel-handoff.test.ts +5 -4
  330. package/dist/extensions/pi-subagents/test/unit/permissions.test.ts +2 -6
  331. package/dist/extensions/pi-subagents/test/unit/pi-coding-agent-dir.test.ts +28 -2
  332. package/dist/extensions/pi-subagents/test/unit/pi-web-session-liveness.test.ts +209 -0
  333. package/dist/extensions/pi-subagents/test/unit/preflight.test.ts +38 -1
  334. package/dist/extensions/pi-subagents/test/unit/prompt-audit-optional-peers.test.ts +43 -0
  335. package/dist/extensions/pi-subagents/test/unit/public-execution.test.ts +24 -2
  336. package/dist/extensions/pi-subagents/test/unit/readonly-drain-observation.test.ts +174 -0
  337. package/dist/extensions/pi-subagents/test/unit/readonly-model-continuation.test.ts +94 -0
  338. package/dist/extensions/pi-subagents/test/unit/readonly-session-evidence.test.ts +1329 -0
  339. package/dist/extensions/pi-subagents/test/unit/recursion-guard.test.ts +29 -80
  340. package/dist/extensions/pi-subagents/test/unit/render-helpers.test.ts +11 -8
  341. package/dist/extensions/pi-subagents/test/unit/result-files.test.ts +2 -2
  342. package/dist/extensions/pi-subagents/test/unit/retained-nested-route-tracker.test.ts +175 -0
  343. package/dist/extensions/pi-subagents/test/unit/rpc.test.ts +38 -12
  344. package/dist/extensions/pi-subagents/test/unit/run-fanout-budget.test.ts +2 -5
  345. package/dist/extensions/pi-subagents/test/unit/run-status.test.ts +89 -1
  346. package/dist/extensions/pi-subagents/test/unit/runtime-acknowledged-extensions.test.ts +2 -16
  347. package/dist/extensions/pi-subagents/test/unit/scheduled-runs.test.ts +27 -3
  348. package/dist/extensions/pi-subagents/test/unit/scheduled-supervisor-demand.test.ts +215 -0
  349. package/dist/extensions/pi-subagents/test/unit/schemas.test.ts +15 -11
  350. package/dist/extensions/pi-subagents/test/unit/scripted-workflow.test.ts +237 -1
  351. package/dist/extensions/pi-subagents/test/unit/steering-action.test.ts +2 -5
  352. package/dist/extensions/pi-subagents/test/unit/streamed-progress-bounds.test.ts +2 -2
  353. package/dist/extensions/pi-subagents/test/unit/subagent-guide.test.ts +14 -1
  354. package/dist/extensions/pi-subagents/test/unit/subagent-prompt-runtime.test.ts +130 -739
  355. package/dist/extensions/pi-subagents/test/unit/supervisor-ask-registration.test.ts +682 -0
  356. package/dist/extensions/pi-subagents/test/unit/supervisor-ui.test.ts +137 -0
  357. package/dist/extensions/pi-subagents/test/unit/tool-budget.test.ts +1 -11
  358. package/dist/extensions/pi-subagents/test/unit/tool-description.test.ts +23 -3
  359. package/dist/extensions/pi-subagents/test/unit/wait-completions.test.ts +8 -1
  360. package/dist/extensions/pi-subagents/test/unit/watchdog-tool-actions.test.ts +19 -1
  361. package/dist/extensions/pi-subagents/test/unit/workflow-chat-progress.test.ts +72 -4
  362. package/dist/extensions/pi-subagents/test/unit/workflow-checklist.test.ts +17 -3
  363. package/dist/extensions/pi-subagents/test/unit/workflow-child-summary.test.ts +34 -0
  364. package/dist/extensions/pi-subagents/test/unit/workflow-detach-reconcile.test.ts +12 -2
  365. package/dist/extensions/pi-subagents/test/unit/workflow-launch-params.test.ts +46 -6
  366. package/dist/extensions/pi-subagents/test/unit/workflow-receipt.test.ts +3 -3
  367. package/dist/extensions/pi-subagents/test/unit/workflow-resources.test.ts +133 -1
  368. package/dist/extensions/pi-subagents/test/unit/workflow-resume-hint.test.ts +53 -2
  369. package/dist/extensions/pi-subagents/test/unit/worktree-cleanup-plan.test.ts +222 -14
  370. package/dist/extensions/pi-subagents/test/unit/worktree.test.ts +526 -85
  371. package/dist/extensions/pi-web-agent/src/backends/config.ts +1 -0
  372. package/dist/extensions/pi-web-agent/src/backends/settings-reader.ts +5 -3
  373. package/dist/extensions/pi-web-agent/src/search/tokenin.ts +7 -3
  374. package/dist/extensions/pi-web-agent/src/types.ts +1 -1
  375. package/dist/extensions/pi-zentui/README.md +17 -0
  376. package/dist/extensions/pi-zentui/assets/screenshots/footer-status-hyperlink.png +0 -0
  377. package/dist/extensions/pi-zentui/docs/configuration.md +71 -2
  378. package/dist/extensions/pi-zentui/extensions/zentui/config.ts +11 -0
  379. package/dist/extensions/pi-zentui/extensions/zentui/editor-transfer.ts +14 -0
  380. package/dist/extensions/pi-zentui/extensions/zentui/extension-status.ts +29 -13
  381. package/dist/extensions/pi-zentui/extensions/zentui/footer-layout.ts +5 -4
  382. package/dist/extensions/pi-zentui/extensions/zentui/footer-text.ts +11 -0
  383. package/dist/extensions/pi-zentui/extensions/zentui/footer.ts +11 -10
  384. package/dist/extensions/pi-zentui/extensions/zentui/index.ts +77 -3
  385. package/dist/extensions/pi-zentui/extensions/zentui/presets.ts +77 -0
  386. package/dist/extensions/pi-zentui/extensions/zentui/settings-command.ts +103 -2
  387. package/dist/extensions/pi-zentui/extensions/zentui/working-line-extension-segments.ts +115 -0
  388. package/dist/extensions/pi-zentui/extensions/zentui/working-line.ts +87 -5
  389. package/dist/extensions/pi-zentui/package-lock.json +277 -517
  390. package/dist/extensions/pi-zentui/package.json +7 -4
  391. package/dist/extensions/pi-zentui/test/config-presets.test.ts +238 -0
  392. package/dist/extensions/pi-zentui/test/editor-transfer.test.ts +24 -1
  393. package/dist/extensions/pi-zentui/test/extension-compliance.test.ts +570 -2
  394. package/dist/extensions/pi-zentui/test/extension-status.test.ts +90 -0
  395. package/dist/extensions/pi-zentui/test/footer-hyperlink.test.ts +243 -0
  396. package/dist/extensions/pi-zentui/test/package-contents.mjs +1 -0
  397. package/dist/extensions/pi-zentui/test/presets.test.ts +121 -0
  398. package/dist/extensions/pi-zentui/test/settings-command.test.ts +205 -1
  399. package/dist/extensions/pi-zentui/test/working-line-extension-segments.test.ts +139 -0
  400. package/dist/extensions/pi-zentui/test/working-line-lifecycle.integration.test.ts +237 -3
  401. package/dist/extensions/pi-zentui/test/working-line.test.ts +94 -2
  402. package/dist/index.d.ts +1 -1
  403. package/dist/main.js +4 -1
  404. package/dist/modes/interactive/chat-viewport.d.ts +19 -0
  405. package/dist/modes/interactive/chat-viewport.js +27 -0
  406. package/dist/modes/interactive/components/assistant-message.d.ts +6 -2
  407. package/dist/modes/interactive/components/assistant-message.js +30 -13
  408. package/dist/modes/interactive/components/custom-editor.d.ts +10 -1
  409. package/dist/modes/interactive/components/custom-editor.js +39 -1
  410. package/dist/modes/interactive/components/first-time-setup.js +1 -1
  411. package/dist/modes/interactive/components/index.d.ts +1 -1
  412. package/dist/modes/interactive/components/markdown-transform.d.ts +2 -0
  413. package/dist/modes/interactive/components/markdown-transform.js +18 -0
  414. package/dist/modes/interactive/components/model-selector.js +19 -17
  415. package/dist/modes/interactive/components/scoped-models-selector.js +21 -23
  416. package/dist/modes/interactive/components/settings-selector.d.ts +7 -1
  417. package/dist/modes/interactive/components/settings-selector.js +128 -20
  418. package/dist/modes/interactive/components/settings-submenu.d.ts +71 -0
  419. package/dist/modes/interactive/components/settings-submenu.js +164 -0
  420. package/dist/modes/interactive/components/status-indicator.d.ts +3 -1
  421. package/dist/modes/interactive/components/status-indicator.js +10 -3
  422. package/dist/modes/interactive/components/thinking-selector.d.ts +15 -3
  423. package/dist/modes/interactive/components/thinking-selector.js +75 -18
  424. package/dist/modes/interactive/components/tool-execution.d.ts +21 -4
  425. package/dist/modes/interactive/components/tool-execution.js +35 -33
  426. package/dist/modes/interactive/components/trust-selector.js +2 -2
  427. package/dist/modes/interactive/interactive-mode.d.ts +13 -15
  428. package/dist/modes/interactive/interactive-mode.js +144 -80
  429. package/dist/modes/interactive/session-share.d.ts +15 -0
  430. package/dist/modes/interactive/session-share.js +183 -0
  431. package/dist/modes/interactive/theme/dark.json +2 -1
  432. package/dist/modes/interactive/theme/light.json +2 -1
  433. package/dist/modes/interactive/theme/theme-controller.d.ts +1 -0
  434. package/dist/modes/interactive/theme/theme-controller.js +5 -0
  435. package/dist/modes/interactive/theme/theme-json.d.ts +83 -0
  436. package/dist/modes/interactive/theme/theme-json.js +129 -0
  437. package/dist/modes/interactive/theme/theme-schema.json +9 -1
  438. package/dist/modes/interactive/theme/theme.d.ts +14 -5
  439. package/dist/modes/interactive/theme/theme.js +18 -119
  440. package/dist/modes/interactive/tui-renderer.d.ts +20 -0
  441. package/dist/modes/interactive/tui-renderer.js +65 -0
  442. package/dist/utils/exif-orientation.js +2 -3
  443. package/dist/utils/management-http.d.ts +24 -0
  444. package/dist/utils/management-http.js +53 -0
  445. package/dist/utils/text.d.ts +7 -0
  446. package/dist/utils/text.js +8 -0
  447. package/dist/utils/tools-manager.d.ts +1 -0
  448. package/dist/utils/tools-manager.js +43 -21
  449. package/docs/docs.json +0 -4
  450. package/package.json +4 -4
  451. package/dist/extensions/pi-subagents/src/runs/shared/child-protocol.ts +0 -415
  452. package/dist/extensions/pi-subagents/src/runs/shared/pi-args.ts +0 -1059
  453. package/dist/extensions/pi-subagents/src/runs/shared/subagent-startup-retry.ts +0 -116
  454. package/dist/extensions/pi-subagents/src/shared/post-exit-stdio-guard.ts +0 -85
  455. package/dist/extensions/pi-subagents/test/e2e/real-session-subagent.test.ts +0 -224
  456. package/dist/extensions/pi-subagents/test/integration/async-execution.test.ts +0 -6986
  457. package/dist/extensions/pi-subagents/test/support/mock-pi-script.mjs +0 -447
  458. package/dist/extensions/pi-subagents/test/support/real-session-child-cli.mjs +0 -185
  459. package/dist/extensions/pi-subagents/test/support/real-session-runner.ts +0 -311
  460. package/dist/extensions/pi-subagents/test/unit/capability-ceiling-pi-args.test.ts +0 -84
  461. package/dist/extensions/pi-subagents/test/unit/child-protocol.test.ts +0 -202
  462. package/dist/extensions/pi-subagents/test/unit/close-grace-timer.test.ts +0 -101
  463. package/dist/extensions/pi-subagents/test/unit/pi-args.test.ts +0 -2347
  464. package/dist/extensions/pi-subagents/test/unit/subagent-startup-retry.test.ts +0 -104
  465. package/dist/extensions/pi-subagents/test/unit/windows-hide-spawn.test.ts +0 -49
  466. package/dist/skills/imagegen-frontend-mobile/SKILL.md +0 -1465
  467. package/dist/skills/imagegen-frontend-web/SKILL.md +0 -987
  468. package/dist/skills/implanger/SKILL.md +0 -70
  469. package/dist/skills/output/SKILL.md +0 -49
  470. package/dist/skills/planger/SKILL.md +0 -167
  471. package/dist/skills/workflow/SKILL.md +0 -95
  472. package/docs/workflows.md +0 -18
  473. /package/dist/bun/{register-bedrock.d.ts → runtime-setup.d.ts} +0 -0
@@ -2,7 +2,7 @@ import { describe, it, beforeEach, afterEach } from "node:test";
2
2
  import assert from "node:assert/strict";
3
3
  import {
4
4
  checkSubagentDepth,
5
- getSubagentDepthEnv,
5
+ resolveChildDepth,
6
6
  DEFAULT_SUBAGENT_MAX_DEPTH,
7
7
  normalizeMaxSubagentDepth,
8
8
  normalizeMaxSubagentSpawnsPerSession,
@@ -13,21 +13,13 @@ import {
13
13
  resolveCurrentMaxSubagentDepth,
14
14
  } from "../../src/shared/types.ts";
15
15
 
16
- let savedDepth: string | undefined;
17
- let savedMaxDepth: string | undefined;
18
16
  let savedMaxSpawns: string | undefined;
19
17
 
20
18
  beforeEach(() => {
21
- savedDepth = process.env.SELESAI_SUBAGENT_DEPTH;
22
- savedMaxDepth = process.env.SELESAI_SUBAGENT_MAX_DEPTH;
23
19
  savedMaxSpawns = process.env.SELESAI_SUBAGENT_MAX_SPAWNS_PER_SESSION;
24
20
  });
25
21
 
26
22
  afterEach(() => {
27
- if (savedDepth === undefined) delete process.env.SELESAI_SUBAGENT_DEPTH;
28
- else process.env.SELESAI_SUBAGENT_DEPTH = savedDepth;
29
- if (savedMaxDepth === undefined) delete process.env.SELESAI_SUBAGENT_MAX_DEPTH;
30
- else process.env.SELESAI_SUBAGENT_MAX_DEPTH = savedMaxDepth;
31
23
  if (savedMaxSpawns === undefined) delete process.env.SELESAI_SUBAGENT_MAX_SPAWNS_PER_SESSION;
32
24
  else process.env.SELESAI_SUBAGENT_MAX_SPAWNS_PER_SESSION = savedMaxSpawns;
33
25
  });
@@ -100,18 +92,16 @@ describe("resolveMaxSubagentSpawnsPerSession", () => {
100
92
  });
101
93
 
102
94
  describe("resolveCurrentMaxSubagentDepth", () => {
103
- it("uses env when present", () => {
104
- process.env.SELESAI_SUBAGENT_MAX_DEPTH = "5";
105
- assert.equal(resolveCurrentMaxSubagentDepth(1), 5);
95
+ it("uses the executor's own child runtime max when present", () => {
96
+ assert.equal(resolveCurrentMaxSubagentDepth(1, { depth: 1, maxDepth: 5 }), 5);
106
97
  });
107
98
 
108
- it("falls back to config when env is absent", () => {
109
- delete process.env.SELESAI_SUBAGENT_MAX_DEPTH;
99
+ it("falls back to config for a top-level parent", () => {
110
100
  assert.equal(resolveCurrentMaxSubagentDepth(1), 1);
101
+ assert.equal(resolveCurrentMaxSubagentDepth(1, { depth: 1 }), 1);
111
102
  });
112
103
 
113
- it("falls back to default when neither env nor config is valid", () => {
114
- delete process.env.SELESAI_SUBAGENT_MAX_DEPTH;
104
+ it("falls back to default when neither runtime nor config is valid", () => {
115
105
  assert.equal(resolveCurrentMaxSubagentDepth(undefined), 2);
116
106
  assert.equal(resolveCurrentMaxSubagentDepth(-1), 2);
117
107
  });
@@ -150,116 +140,75 @@ describe("resolveChildMaxSubagentDepth", () => {
150
140
 
151
141
  describe("checkSubagentDepth", () => {
152
142
  it("not blocked at depth=0, max=2", () => {
153
- process.env.SELESAI_SUBAGENT_DEPTH = "0";
154
- process.env.SELESAI_SUBAGENT_MAX_DEPTH = "2";
155
- const result = checkSubagentDepth();
143
+ const result = checkSubagentDepth(2);
156
144
  assert.equal(result.blocked, false);
157
145
  assert.equal(result.depth, 0);
158
146
  assert.equal(result.maxDepth, 2);
159
147
  });
160
148
 
161
- it("uses config max depth when env is absent", () => {
162
- process.env.SELESAI_SUBAGENT_DEPTH = "1";
163
- delete process.env.SELESAI_SUBAGENT_MAX_DEPTH;
164
- const result = checkSubagentDepth(1);
149
+ it("uses config max depth when the runtime carries none", () => {
150
+ const result = checkSubagentDepth(1, { depth: 1 });
165
151
  assert.equal(result.blocked, true);
166
152
  assert.equal(result.maxDepth, 1);
167
153
  });
168
154
 
169
155
  it("not blocked at depth=1, max=2", () => {
170
- process.env.SELESAI_SUBAGENT_DEPTH = "1";
171
- process.env.SELESAI_SUBAGENT_MAX_DEPTH = "2";
172
- assert.equal(checkSubagentDepth().blocked, false);
156
+ assert.equal(checkSubagentDepth(undefined, { depth: 1, maxDepth: 2 }).blocked, false);
173
157
  });
174
158
 
175
159
  it("blocks at depth=1, max=1 after one nested level", () => {
176
- process.env.SELESAI_SUBAGENT_DEPTH = "1";
177
- process.env.SELESAI_SUBAGENT_MAX_DEPTH = "1";
178
- assert.equal(checkSubagentDepth().blocked, true);
160
+ assert.equal(checkSubagentDepth(undefined, { depth: 1, maxDepth: 1 }).blocked, true);
179
161
  });
180
162
 
181
163
  it("blocked at depth=2, max=2", () => {
182
- process.env.SELESAI_SUBAGENT_DEPTH = "2";
183
- process.env.SELESAI_SUBAGENT_MAX_DEPTH = "2";
184
- const result = checkSubagentDepth();
164
+ const result = checkSubagentDepth(undefined, { depth: 2, maxDepth: 2 });
185
165
  assert.equal(result.blocked, true);
186
166
  assert.equal(result.depth, 2);
187
167
  assert.equal(result.maxDepth, 2);
188
168
  });
189
169
 
190
170
  it("blocked at depth=3, max=2", () => {
191
- process.env.SELESAI_SUBAGENT_DEPTH = "3";
192
- process.env.SELESAI_SUBAGENT_MAX_DEPTH = "2";
193
- assert.equal(checkSubagentDepth().blocked, true);
171
+ assert.equal(checkSubagentDepth(undefined, { depth: 3, maxDepth: 2 }).blocked, true);
194
172
  });
195
173
 
196
174
  it("blocked at depth=0, max=0 (disables subagent entirely)", () => {
197
- process.env.SELESAI_SUBAGENT_DEPTH = "0";
198
- process.env.SELESAI_SUBAGENT_MAX_DEPTH = "0";
199
- assert.equal(checkSubagentDepth().blocked, true);
175
+ assert.equal(checkSubagentDepth(0).blocked, true);
200
176
  });
201
177
 
202
- it("defaults to depth=0, max=2 when env vars unset", () => {
203
- delete process.env.SELESAI_SUBAGENT_DEPTH;
204
- delete process.env.SELESAI_SUBAGENT_MAX_DEPTH;
178
+ it("defaults to depth=0, max=2 for a top-level parent", () => {
205
179
  const result = checkSubagentDepth();
206
180
  assert.equal(result.blocked, false);
207
181
  assert.equal(result.depth, 0);
208
182
  assert.equal(result.maxDepth, 2);
209
183
  });
210
184
 
211
- it("not blocked when depth is invalid (NaN)", () => {
212
- process.env.SELESAI_SUBAGENT_DEPTH = "garbage";
213
- process.env.SELESAI_SUBAGENT_MAX_DEPTH = "2";
214
- assert.equal(checkSubagentDepth().blocked, false);
185
+ it("not blocked when the runtime depth is invalid (NaN)", () => {
186
+ assert.equal(checkSubagentDepth(undefined, { depth: Number.NaN, maxDepth: 2 }).blocked, false);
215
187
  });
216
188
  });
217
189
 
218
- describe("getSubagentDepthEnv", () => {
219
- it("increments from depth=0", () => {
220
- process.env.SELESAI_SUBAGENT_DEPTH = "0";
221
- delete process.env.SELESAI_SUBAGENT_MAX_DEPTH;
222
- const env = getSubagentDepthEnv();
223
- assert.equal(env.SELESAI_SUBAGENT_DEPTH, "1");
224
- assert.equal(env.SELESAI_SUBAGENT_MAX_DEPTH, "2");
190
+ describe("resolveChildDepth", () => {
191
+ it("increments from a top-level parent", () => {
192
+ assert.deepEqual(resolveChildDepth(), { depth: 1, maxDepth: 2 });
225
193
  });
226
194
 
227
195
  it("increments from depth=1", () => {
228
- process.env.SELESAI_SUBAGENT_DEPTH = "1";
229
- delete process.env.SELESAI_SUBAGENT_MAX_DEPTH;
230
- const env = getSubagentDepthEnv();
231
- assert.equal(env.SELESAI_SUBAGENT_DEPTH, "2");
232
- assert.equal(env.SELESAI_SUBAGENT_MAX_DEPTH, "2");
196
+ assert.deepEqual(resolveChildDepth(undefined, { depth: 1 }), { depth: 2, maxDepth: 2 });
233
197
  });
234
198
 
235
199
  it("uses provided max depth override", () => {
236
- process.env.SELESAI_SUBAGENT_DEPTH = "0";
237
- delete process.env.SELESAI_SUBAGENT_MAX_DEPTH;
238
- const env = getSubagentDepthEnv(1);
239
- assert.equal(env.SELESAI_SUBAGENT_DEPTH, "1");
240
- assert.equal(env.SELESAI_SUBAGENT_MAX_DEPTH, "1");
200
+ assert.deepEqual(resolveChildDepth(1), { depth: 1, maxDepth: 1 });
241
201
  });
242
202
 
243
- it("respects inherited SELESAI_SUBAGENT_MAX_DEPTH when override is absent", () => {
244
- process.env.SELESAI_SUBAGENT_DEPTH = "0";
245
- process.env.SELESAI_SUBAGENT_MAX_DEPTH = "5";
246
- const env = getSubagentDepthEnv();
247
- assert.equal(env.SELESAI_SUBAGENT_DEPTH, "1");
248
- assert.equal(env.SELESAI_SUBAGENT_MAX_DEPTH, "5");
203
+ it("respects the inherited runtime max when override is absent", () => {
204
+ assert.deepEqual(resolveChildDepth(undefined, { depth: 0, maxDepth: 5 }), { depth: 1, maxDepth: 5 });
249
205
  });
250
206
 
251
- it("uses the explicit child override even when a looser inherited env max exists", () => {
252
- process.env.SELESAI_SUBAGENT_DEPTH = "0";
253
- process.env.SELESAI_SUBAGENT_MAX_DEPTH = "5";
254
- const env = getSubagentDepthEnv(1);
255
- assert.equal(env.SELESAI_SUBAGENT_DEPTH, "1");
256
- assert.equal(env.SELESAI_SUBAGENT_MAX_DEPTH, "1");
207
+ it("uses the explicit child override even when a looser inherited max exists", () => {
208
+ assert.deepEqual(resolveChildDepth(1, { depth: 0, maxDepth: 5 }), { depth: 1, maxDepth: 1 });
257
209
  });
258
210
 
259
- it("falls back to depth=1 when env var is invalid (NaN)", () => {
260
- process.env.SELESAI_SUBAGENT_DEPTH = "not-a-number";
261
- delete process.env.SELESAI_SUBAGENT_MAX_DEPTH;
262
- const env = getSubagentDepthEnv();
263
- assert.equal(env.SELESAI_SUBAGENT_DEPTH, "1");
211
+ it("falls back to depth=1 when the runtime depth is invalid (NaN)", () => {
212
+ assert.equal(resolveChildDepth(undefined, { depth: Number.NaN }).depth, 1);
264
213
  });
265
- });
214
+ });
@@ -312,7 +312,7 @@ test("workflow checklist does not map child-local result indexes onto graph node
312
312
  assert.match(text, /✗ Writer · writer · failed/);
313
313
  });
314
314
 
315
- test("collapsed workflow widgets lead with checklist phases while expanded widgets keep child detail", () => {
315
+ test("collapsed async workflow widgets render compact lane rows while expanded widgets keep child detail", () => {
316
316
  const now = 50_000;
317
317
  const workflowGraph = {
318
318
  runId: "workflow-collapsed",
@@ -354,11 +354,12 @@ test("collapsed workflow widgets lead with checklist phases while expanded widge
354
354
  const collapsed = buildWidgetLines([job], theme, 240).join("\n");
355
355
  assert.match(collapsed, /1\/5 done · 1 active · 3 queued/);
356
356
  assert.match(collapsed, /✓ inventory/);
357
- assert.match(collapsed, /writers 1 active · 1 queued/);
358
- assert.match(collapsed, /◦ reviews 1 queued/);
359
- assert.match(collapsed, /◦ gates 1 queued/);
360
- assert.match(collapsed, /bottleneck/);
361
- assert.match(collapsed, /Press configured-expand-key for live detail · Ctrl\+Alt\+F Fleet/);
357
+ assert.match(collapsed, /writer-a · writer · active/);
358
+ assert.match(collapsed, /writer-b · writer · queued/);
359
+ assert.match(collapsed, /review · reviewer · queued/);
360
+ assert.match(collapsed, /gate · reviewer · queued/);
361
+ assert.doesNotMatch(collapsed, /bottleneck/);
362
+ assert.match(collapsed, /Press configured-expand-key for details · Ctrl\+Alt\+F Fleet/);
362
363
  assert.equal((collapsed.match(/1\/5 done · 1 active · 3 queued/g) ?? []).length, 1);
363
364
  assert.doesNotMatch(collapsed, /Step \d\/\d|task:|workspace:|ref:|out(?:put)?:/i);
364
365
 
@@ -381,7 +382,9 @@ test("collapsed workflow widgets lead with checklist phases while expanded widge
381
382
  { index: 1, agent: "scout", status: "running" },
382
383
  ],
383
384
  } as AsyncJobState], theme, 240).join("\n");
384
- assert.match(generic, /Workflow 2 active/);
385
+ assert.match(generic, /id: workflow · 0\/2 done · 2 active/);
386
+ assert.match(generic, /step-1 · reviewer · active · reviewer/);
387
+ assert.match(generic, /step-2 · scout · active · scout/);
385
388
  });
386
389
 
387
390
  test("compact foreground workflow results use checklist phases instead of child rows", () => {
@@ -636,4 +639,4 @@ test("main-window renderer config caps only collapsed rich result rows", () => {
636
639
 
637
640
  assert.ok(expanded.length > 3);
638
641
  assert.doesNotMatch(expanded.join("\n"), /rows hidden/);
639
- });
642
+ });
@@ -41,7 +41,7 @@ describe("result file indexes", () => {
41
41
  fs.rmSync(path.join(resultsDir, "missing.json"));
42
42
  fs.writeFileSync(path.join(resultsDir, "unindexed.json"), JSON.stringify({ id: "unindexed", sessionId: "session-a" }), "utf-8");
43
43
 
44
- assert.equal(cleanupResultIndexes(resultsDir, Date.now() + 86_400_001, 86_400_000), 3);
44
+ assert.equal(cleanupResultIndexes(resultsDir, Date.now() + 86_400_001, 86_400_000) > 0, true);
45
45
 
46
46
  assert.deepEqual(resultFilesForSession(resultsDir, "session-a"), ["kept.json"]);
47
47
  assert.equal(fs.existsSync(path.join(resultsDir, "kept.json")), true);
@@ -498,4 +498,4 @@ describe("result file indexes", () => {
498
498
  fs.rmSync(resultsDir, { recursive: true, force: true });
499
499
  }
500
500
  });
501
- });
501
+ });
@@ -0,0 +1,175 @@
1
+ import assert from "node:assert/strict";
2
+ import { EventEmitter } from "node:events";
3
+ import * as fs from "node:fs";
4
+ import * as path from "node:path";
5
+ import { afterEach, describe, it } from "node:test";
6
+ import { retainLiveForegroundNestedRoute } from "../../src/integrations/pi-web-session-liveness.ts";
7
+ import { createRetainedNestedRouteTracker } from "../../src/runs/background/retained-nested-route-tracker.ts";
8
+ import { createNestedRoute, writeNestedEvent } from "../../src/runs/shared/nested-events.ts";
9
+ import type { SubagentState } from "../../src/shared/types.ts";
10
+
11
+ const routeRoots: string[] = [];
12
+
13
+ class Watcher extends EventEmitter implements fs.FSWatcher {
14
+ close() { this.emit("close"); }
15
+ ref() { return this; }
16
+ unref() { return this; }
17
+ }
18
+
19
+ function route(rootRunId: string) {
20
+ const value = createNestedRoute(rootRunId);
21
+ routeRoots.push(path.dirname(value.eventSink));
22
+ return value;
23
+ }
24
+
25
+ function writeState(value: ReturnType<typeof route>, state: "running" | "complete", ts: number): void {
26
+ writeNestedEvent(value, {
27
+ type: state === "running" ? "subagent.nested.updated" : "subagent.nested.completed",
28
+ ts,
29
+ parentRunId: value.rootRunId,
30
+ child: {
31
+ id: "nested-child",
32
+ parentRunId: value.rootRunId,
33
+ depth: 1,
34
+ path: [{ runId: value.rootRunId }],
35
+ state,
36
+ agent: "worker",
37
+ lastUpdate: ts,
38
+ },
39
+ });
40
+ }
41
+
42
+ async function waitFor(check: () => boolean, timeoutMs = 1000): Promise<void> {
43
+ const deadline = Date.now() + timeoutMs;
44
+ while (!check() && Date.now() < deadline) await new Promise((resolve) => setTimeout(resolve, 5));
45
+ assert.equal(check(), true, "condition did not become true before timeout");
46
+ }
47
+
48
+ afterEach(() => {
49
+ for (const root of routeRoots.splice(0)) fs.rmSync(root, { recursive: true, force: true });
50
+ });
51
+
52
+ describe("retained foreground nested route tracker", () => {
53
+ it("releases retained liveness after the nested descendant completes", async () => {
54
+ const state: Pick<SubagentState, "retainedForegroundNestedRoutes"> = {};
55
+ const nestedRoute = route("retained-root");
56
+ writeState(nestedRoute, "running", 100);
57
+ assert.equal(retainLiveForegroundNestedRoute(state, nestedRoute), true);
58
+
59
+ const tracker = createRetainedNestedRouteTracker(state, { platform: "win32", pollIntervalMs: 10 });
60
+ try {
61
+ tracker.track(nestedRoute.rootRunId);
62
+ writeState(nestedRoute, "complete", 200);
63
+ await waitFor(() => !state.retainedForegroundNestedRoutes?.has(nestedRoute.rootRunId));
64
+ } finally {
65
+ tracker.clear();
66
+ }
67
+ });
68
+
69
+ it("keeps the route through the handoff race until the first tracker refresh", async () => {
70
+ const state: Pick<SubagentState, "retainedForegroundNestedRoutes"> = {};
71
+ const nestedRoute = route("handoff-root");
72
+ writeState(nestedRoute, "running", 100);
73
+ assert.equal(retainLiveForegroundNestedRoute(state, nestedRoute), true);
74
+ writeState(nestedRoute, "complete", 200);
75
+
76
+ const tracker = createRetainedNestedRouteTracker(state, { platform: "win32", pollIntervalMs: 60_000 });
77
+ try {
78
+ tracker.track(nestedRoute.rootRunId);
79
+ assert.equal(state.retainedForegroundNestedRoutes?.has(nestedRoute.rootRunId), true);
80
+ await waitFor(() => !state.retainedForegroundNestedRoutes?.has(nestedRoute.rootRunId));
81
+ } finally {
82
+ tracker.clear();
83
+ }
84
+ });
85
+
86
+ it("keeps polling after a native watcher error", async () => {
87
+ const state: Pick<SubagentState, "retainedForegroundNestedRoutes"> = {};
88
+ const nestedRoute = route("watch-error-root");
89
+ writeState(nestedRoute, "running", 100);
90
+ assert.equal(retainLiveForegroundNestedRoute(state, nestedRoute), true);
91
+
92
+ const watcher = new Watcher();
93
+ const tracker = createRetainedNestedRouteTracker(state, {
94
+ platform: "linux",
95
+ pollIntervalMs: 10,
96
+ watch: () => watcher,
97
+ });
98
+ try {
99
+ tracker.track(nestedRoute.rootRunId);
100
+ watcher.emit("error", new Error("watch failed"));
101
+ writeState(nestedRoute, "complete", 200);
102
+ await waitFor(() => !state.retainedForegroundNestedRoutes?.has(nestedRoute.rootRunId));
103
+ } finally {
104
+ tracker.clear();
105
+ }
106
+ });
107
+
108
+ it("refreshes every retained route instead of stopping at the first live one", async () => {
109
+ const state: Pick<SubagentState, "retainedForegroundNestedRoutes"> = {};
110
+ const liveRoute = route("multi-live-root");
111
+ const terminalRoute = route("multi-terminal-root");
112
+ writeState(liveRoute, "running", 100);
113
+ writeState(terminalRoute, "running", 100);
114
+ assert.equal(retainLiveForegroundNestedRoute(state, liveRoute), true);
115
+ assert.equal(retainLiveForegroundNestedRoute(state, terminalRoute), true);
116
+
117
+ const tracker = createRetainedNestedRouteTracker(state, { platform: "win32", pollIntervalMs: 10 });
118
+ try {
119
+ tracker.track(liveRoute.rootRunId);
120
+ tracker.track(terminalRoute.rootRunId);
121
+ writeState(terminalRoute, "complete", 200);
122
+ await waitFor(() => !state.retainedForegroundNestedRoutes?.has(terminalRoute.rootRunId));
123
+ assert.equal(state.retainedForegroundNestedRoutes?.has(liveRoute.rootRunId), true);
124
+ } finally {
125
+ tracker.clear();
126
+ }
127
+ });
128
+
129
+ it("refreshes promptly from native watch events", (t) => {
130
+ t.mock.timers.enable({ apis: ["setTimeout"] });
131
+ const state: Pick<SubagentState, "retainedForegroundNestedRoutes"> = {};
132
+ const nestedRoute = route("watched-root");
133
+ writeState(nestedRoute, "running", 100);
134
+ assert.equal(retainLiveForegroundNestedRoute(state, nestedRoute), true);
135
+
136
+ let notify: (() => void) | undefined;
137
+ let closed = 0;
138
+ const watcher = new Watcher();
139
+ watcher.on("close", () => { closed += 1; });
140
+ const tracker = createRetainedNestedRouteTracker(state, {
141
+ platform: "linux",
142
+ pollIntervalMs: 60_000,
143
+ // SAFETY: the tracker uses only fs.watch(path, listener), not the options overloads.
144
+ watch: ((_path: fs.PathLike, listener: fs.WatchListener<string>) => {
145
+ notify = () => listener("rename", "event.json");
146
+ return watcher;
147
+ }) as typeof fs.watch,
148
+ });
149
+ try {
150
+ tracker.track(nestedRoute.rootRunId);
151
+ t.mock.timers.tick(25);
152
+ assert.equal(state.retainedForegroundNestedRoutes?.has(nestedRoute.rootRunId), true);
153
+ writeState(nestedRoute, "complete", 200);
154
+ notify?.();
155
+ t.mock.timers.tick(25);
156
+ assert.equal(state.retainedForegroundNestedRoutes?.has(nestedRoute.rootRunId), false);
157
+ assert.equal(closed, 1);
158
+ } finally {
159
+ tracker.clear();
160
+ }
161
+ });
162
+
163
+ it("clears every retained route during session teardown", () => {
164
+ const state: Pick<SubagentState, "retainedForegroundNestedRoutes"> = {};
165
+ const nestedRoute = route("cleared-root");
166
+ writeState(nestedRoute, "running", 100);
167
+ assert.equal(retainLiveForegroundNestedRoute(state, nestedRoute), true);
168
+
169
+ const tracker = createRetainedNestedRouteTracker(state, { platform: "win32", pollIntervalMs: 60_000 });
170
+ tracker.track(nestedRoute.rootRunId);
171
+ tracker.clear();
172
+
173
+ assert.equal(state.retainedForegroundNestedRoutes?.size, 0);
174
+ });
175
+ });
@@ -4,7 +4,7 @@ import * as os from "node:os";
4
4
  import * as path from "node:path";
5
5
  import { describe, it } from "node:test";
6
6
  import type { AgentToolResult } from "@earendil-works/pi-agent-core";
7
- import { consumeStopRequestPayload, stopRequestPath } from "../../src/runs/background/control-channel.ts";
7
+ import { consumeStopRequestPayload, stopRequestPath, stopRequestsDir } from "../../src/runs/background/control-channel.ts";
8
8
  import {
9
9
  SUBAGENT_RPC_PROTOCOL_VERSION,
10
10
  SUBAGENT_RPC_READY_EVENT,
@@ -957,10 +957,17 @@ describe("subagent extension RPC bridge", () => {
957
957
  state: "running",
958
958
  startedAt: 100,
959
959
  lastUpdate: 100,
960
- steps: [{ agent: "worker", status: "running", workflowKey: "slow", startedAt: 100 }],
960
+ steps: [
961
+ { agent: "worker", status: "running", childId: "child-slow", workflowKey: "slow", startedAt: 100 },
962
+ { agent: "worker", status: "completed", workflowKey: "done", startedAt: 100, endedAt: 120 },
963
+ ],
961
964
  }, null, 2), "utf-8");
962
965
  const controller = new AbortController();
963
- const state = { workflowControllers: new Map([["workflow-run-stop", controller]]) } as SubagentState;
966
+ const calls: Array<{ childId: string; message?: string }> = [];
967
+ const state = {
968
+ workflowControllers: new Map([["workflow-run-stop", controller]]),
969
+ workflowChildStops: new Map([["workflow-run-stop", (childId: string, message?: string) => { calls.push({ childId, message }); return true; }]]),
970
+ } as SubagentState;
964
971
  const bridge = registerSubagentRpcBridge({
965
972
  events,
966
973
  getContext: () => ctx(),
@@ -976,6 +983,7 @@ describe("subagent extension RPC bridge", () => {
976
983
  assert.equal((reply as { data: { runId?: string; state?: string; childId?: string } }).data.runId, "workflow-run-stop");
977
984
  assert.equal((reply as { data: { state?: string } }).data.state, "stopping");
978
985
  assert.equal((reply as { data: { childId?: string } }).data.childId, undefined);
986
+ assert.deepEqual(calls, [{ childId: "child-slow", message: "Workflow stopped by RPC." }]);
979
987
  assert.equal(controller.signal.aborted, true);
980
988
  assert.equal(controller.signal.reason instanceof Error ? controller.signal.reason.message : String(controller.signal.reason), "Workflow stopped by RPC.");
981
989
  assert.equal(fs.existsSync(stopRequestPath(asyncDir)), false);
@@ -1029,7 +1037,7 @@ describe("subagent extension RPC bridge", () => {
1029
1037
  }
1030
1038
  });
1031
1039
 
1032
- it("stops reload-recovered workflows through the durable control channel", async () => {
1040
+ for (const scenario of ["no-state", "empty-maps", "child-no-state", "child-controller-only", "child-callback-false", "run-callback-only"] as const) it(`rejects workflow stop without the required live control: ${scenario}`, async () => {
1033
1041
  const root = fs.mkdtempSync(path.join(os.tmpdir(), "pi-rpc-stop-workflow-"));
1034
1042
  try {
1035
1043
  const events = new FakeEvents();
@@ -1037,6 +1045,14 @@ describe("subagent extension RPC bridge", () => {
1037
1045
  const resultsDir = path.join(root, "results");
1038
1046
  const asyncDir = path.join(asyncRoot, "workflow-run");
1039
1047
  let killCalls = 0;
1048
+ const controller = new AbortController();
1049
+ const calls: string[] = [];
1050
+ const stopChild = (childId: string) => { calls.push(childId); return false; };
1051
+ const childId = scenario.startsWith("child-") ? "worker" : undefined;
1052
+ const state = scenario === "no-state" || scenario === "child-no-state" ? undefined : {
1053
+ workflowControllers: new Map(scenario === "child-controller-only" || scenario === "child-callback-false" ? [["workflow-run", controller]] : []),
1054
+ workflowChildStops: new Map(scenario === "child-callback-false" || scenario === "run-callback-only" ? [["workflow-run", stopChild]] : []),
1055
+ } as SubagentState;
1040
1056
  fs.mkdirSync(asyncDir, { recursive: true });
1041
1057
  fs.writeFileSync(path.join(asyncDir, "status.json"), JSON.stringify({
1042
1058
  runId: "workflow-run",
@@ -1046,10 +1062,15 @@ describe("subagent extension RPC bridge", () => {
1046
1062
  pid: 4242,
1047
1063
  startedAt: 100,
1048
1064
  lastUpdate: 100,
1049
- steps: [{ agent: "worker", status: "running", startedAt: 100 }],
1065
+ steps: [
1066
+ { workflowKey: "worker", agent: "worker", status: "running", startedAt: 100 },
1067
+ { workflowKey: "sibling", agent: "worker", status: "running", startedAt: 100 },
1068
+ ],
1050
1069
  }, null, 2), "utf-8");
1070
+ const statusBefore = fs.readFileSync(path.join(asyncDir, "status.json"), "utf-8");
1051
1071
  const bridge = registerSubagentRpcBridge({
1052
1072
  events,
1073
+ state,
1053
1074
  getContext: () => ctx(),
1054
1075
  execute: async () => assert.fail("stop should not call executor"),
1055
1076
  asyncDirRoot: asyncRoot,
@@ -1061,13 +1082,18 @@ describe("subagent extension RPC bridge", () => {
1061
1082
  now: () => 150,
1062
1083
  });
1063
1084
 
1064
- const reply = await request(events, "stop-workflow", "stop", { id: "workflow-run" });
1085
+ const reply = await request(events, "stop-workflow", "stop", { id: "workflow-run", ...(childId ? { childId } : {}) });
1065
1086
 
1066
- assert.equal(reply.success, true);
1067
- assert.equal((reply as { data: { runId?: string; state?: string; message?: string } }).data.runId, "workflow-run");
1068
- assert.equal((reply as { data: { state?: string } }).data.state, "stopping");
1069
- assert.match((reply as { data: { message?: string } }).data.message ?? "", /Stop requested for async run workflow-run/);
1070
- assert.equal(consumeStopRequestPayload(asyncDir)?.type, "stop");
1087
+ assert.equal(reply.success, false);
1088
+ assert.equal((reply as { error: { code: string } }).error.code, "invalid_state");
1089
+ assert.match((reply as { error: { message: string } }).error.message,
1090
+ scenario === "child-callback-false" ? /not available to stop/ : childId ? /no live stop callback/ : /no live run controller/);
1091
+ assert.equal(fs.existsSync(stopRequestPath(asyncDir)), false);
1092
+ assert.equal(fs.existsSync(stopRequestsDir(asyncDir)), false);
1093
+ assert.equal(fs.readFileSync(path.join(asyncDir, "status.json"), "utf-8"), statusBefore);
1094
+ assert.equal(events.emitted.some(({ event }) => event === SUBAGENT_CHILD_STATUS_EVENT), false);
1095
+ assert.equal(controller.signal.aborted, false);
1096
+ assert.deepEqual(calls, scenario === "child-callback-false" ? ["worker"] : []);
1071
1097
  assert.equal(killCalls, 0);
1072
1098
 
1073
1099
  bridge.dispose();
@@ -1121,4 +1147,4 @@ describe("subagent extension RPC bridge", () => {
1121
1147
  fs.rmSync(root, { recursive: true, force: true });
1122
1148
  }
1123
1149
  });
1124
- });
1150
+ });
@@ -8,8 +8,6 @@ import {
8
8
  claimRunFanoutBatch,
9
9
  claimRunFanoutBatchWithCommit,
10
10
  createRunFanoutBudget,
11
- decodeRunFanoutBudgetDescriptor,
12
- encodeRunFanoutBudgetDescriptor,
13
11
  getRunFanoutBudgetSnapshot,
14
12
  RunFanoutLimitError,
15
13
  validateRunFanoutBudgetDescriptor,
@@ -120,8 +118,7 @@ describe("run fan-out budget", () => {
120
118
  it("persists claims and rejects the responsible next path at the exact cap", () => {
121
119
  const descriptor = budget(2);
122
120
  assert.deepEqual(claimRunFanoutBatch(descriptor, ["tasks[0]", "tasks[1]"]), { used: 2, limit: 2, remaining: 0 });
123
- const restored = decodeRunFanoutBudgetDescriptor(encodeRunFanoutBudgetDescriptor(descriptor));
124
- assert.deepEqual(getRunFanoutBudgetSnapshot(restored!), { used: 2, limit: 2, remaining: 0 });
121
+ assert.deepEqual(getRunFanoutBudgetSnapshot(descriptor), { used: 2, limit: 2, remaining: 0 });
125
122
  assert.throws(() => claimRunFanoutBatch(descriptor, ["tasks[2]"]), (error: unknown) => {
126
123
  assert.ok(error instanceof RunFanoutLimitError);
127
124
  assert.equal(error.rejection.path, "tasks[2]");
@@ -188,4 +185,4 @@ describe("run fan-out budget", () => {
188
185
  directories.push(linked);
189
186
  assert.throws(() => validateRunFanoutBudgetDescriptor({ ...descriptor, directory: linked }), /resolves outside/);
190
187
  });
191
- });
188
+ });