one-code-extension 0.4.1 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (439) hide show
  1. package/README.md +16 -5
  2. package/agents/general-purpose.md +2 -2
  3. package/docs/guide/README.md +2 -1
  4. package/docs/guide/bring-your-claude-code-setup.md +60 -9
  5. package/docs/guide/configuration.md +48 -14
  6. package/docs/guide/differences-from-claude-code.md +40 -28
  7. package/docs/guide/doctor.md +20 -13
  8. package/docs/guide/hooks.md +18 -3
  9. package/docs/guide/installation.md +26 -4
  10. package/docs/guide/permissions-modes-and-auto-mode.md +225 -49
  11. package/docs/guide/providers-and-models.md +137 -54
  12. package/docs/guide/reference.md +27 -15
  13. package/docs/guide/sessions-and-context.md +69 -16
  14. package/docs/guide/skills-plugins-and-mcp.md +57 -20
  15. package/docs/guide/subagents-and-workflows.md +95 -29
  16. package/docs/guide/tasks-and-background-work.md +101 -26
  17. package/docs/guide/terminal-interface.md +24 -12
  18. package/docs/guide/tools.md +46 -5
  19. package/docs/guide/troubleshooting.md +13 -9
  20. package/docs/guide/windows.md +58 -31
  21. package/extensions/artifacts/gallery.ts +227 -0
  22. package/extensions/artifacts/index.ts +288 -0
  23. package/extensions/artifacts/store.ts +570 -0
  24. package/extensions/artifacts/viewer.ts +199 -0
  25. package/extensions/ask-user/description.ts +67 -0
  26. package/extensions/ask-user/dialogs.ts +80 -0
  27. package/extensions/ask-user/index.ts +37 -33
  28. package/extensions/ask-user/questions.ts +32 -7
  29. package/extensions/ask-user/widget.ts +45 -25
  30. package/extensions/auto-mode/actions.ts +6 -0
  31. package/extensions/auto-mode/cache.ts +88 -0
  32. package/extensions/auto-mode/classifier-prompt.ts +5 -4
  33. package/extensions/auto-mode/classifier.ts +290 -65
  34. package/extensions/auto-mode/config.ts +72 -20
  35. package/extensions/auto-mode/decision-log.ts +2 -0
  36. package/extensions/auto-mode/defaults.ts +1 -1
  37. package/extensions/auto-mode/denials.ts +124 -0
  38. package/extensions/auto-mode/git-checkout-programs.ts +187 -0
  39. package/extensions/auto-mode/git-status-meta.ts +159 -0
  40. package/extensions/auto-mode/history.ts +189 -0
  41. package/extensions/auto-mode/instructions.ts +58 -52
  42. package/extensions/auto-mode/model-select.ts +159 -134
  43. package/extensions/auto-mode/paths.ts +57 -5
  44. package/extensions/auto-mode/pause.ts +57 -2
  45. package/extensions/auto-mode/prompt.ts +37 -21
  46. package/extensions/auto-mode/read-only-options.ts +724 -0
  47. package/extensions/auto-mode/resolved-paths-meta.ts +133 -0
  48. package/extensions/auto-mode/rules.ts +18 -1
  49. package/extensions/auto-mode/safety-floor.ts +361 -18
  50. package/extensions/auto-mode/setup-run.ts +20 -14
  51. package/extensions/auto-mode/shell-analysis.ts +764 -490
  52. package/extensions/auto-mode/shell-parse.ts +885 -0
  53. package/extensions/auto-mode/system-note.ts +33 -0
  54. package/extensions/auto-mode/transcript.ts +80 -51
  55. package/extensions/background/cron.ts +642 -0
  56. package/extensions/background/index.ts +614 -248
  57. package/extensions/background/loop-fire.ts +173 -0
  58. package/extensions/background/loop-preamble.ts +59 -0
  59. package/extensions/background/loop-skill.ts +163 -0
  60. package/extensions/background/monitor-batch.ts +53 -0
  61. package/extensions/background/noop-fold.ts +128 -0
  62. package/extensions/background/switch-guard.ts +56 -0
  63. package/extensions/background/wakeup.ts +178 -55
  64. package/extensions/bash/background.ts +53 -17
  65. package/extensions/bash/child.ts +7 -0
  66. package/extensions/bash/description.ts +188 -0
  67. package/extensions/bash/guards.ts +15 -67
  68. package/extensions/bash/index.ts +66 -35
  69. package/extensions/branding/compaction-keep.ts +63 -0
  70. package/extensions/branding/declined.ts +22 -0
  71. package/extensions/branding/index.ts +133 -9
  72. package/extensions/branding/prompt-editor.ts +53 -6
  73. package/extensions/branding/queued-edit.ts +31 -0
  74. package/extensions/branding/replaced-builtins.ts +68 -0
  75. package/extensions/branding/startup.ts +33 -71
  76. package/extensions/btw/index.ts +250 -78
  77. package/extensions/btw/panel.ts +228 -100
  78. package/extensions/btw/prompt.ts +41 -4
  79. package/extensions/cache-marks/index.ts +42 -0
  80. package/extensions/claude-compat/index.ts +7 -11
  81. package/extensions/claude-context/index.ts +436 -63
  82. package/extensions/compaction/cut.ts +157 -0
  83. package/extensions/compaction/index.ts +219 -75
  84. package/extensions/compaction/kept-thinking.ts +62 -0
  85. package/extensions/compaction/prompt.ts +15 -12
  86. package/extensions/context-budget/budget.ts +16 -2
  87. package/extensions/context-budget/index.ts +35 -15
  88. package/extensions/context-management/index.ts +36 -28
  89. package/extensions/doctor/build.ts +59 -8
  90. package/extensions/doctor/builtins.ts +84 -0
  91. package/extensions/doctor/cli.ts +7 -1
  92. package/extensions/doctor/compat.ts +88 -23
  93. package/extensions/doctor/dependencies.ts +41 -5
  94. package/extensions/doctor/fix-prompt.ts +9 -2
  95. package/extensions/doctor/index.ts +102 -58
  96. package/extensions/doctor/models.ts +102 -63
  97. package/extensions/doctor/presets.ts +42 -27
  98. package/extensions/doctor/report.ts +19 -2
  99. package/extensions/doctor/viewer.ts +49 -27
  100. package/extensions/effort/index.ts +141 -25
  101. package/extensions/effort/settings.ts +21 -0
  102. package/extensions/effort/slider.ts +24 -20
  103. package/extensions/exit/index.ts +32 -1
  104. package/extensions/file-tracker/index.ts +420 -42
  105. package/extensions/file-tracker/replay.ts +137 -24
  106. package/extensions/file-tracker/restore.ts +66 -0
  107. package/extensions/file-tracker/results.ts +66 -0
  108. package/extensions/file-tracker/shell-reads.ts +211 -0
  109. package/extensions/file-tracker/tracker.ts +45 -15
  110. package/extensions/footer/footer-line.ts +45 -24
  111. package/extensions/footer/index.ts +47 -2
  112. package/extensions/footer/pr.ts +34 -5
  113. package/extensions/hooks/compaction.ts +7 -0
  114. package/extensions/hooks/executor.ts +32 -30
  115. package/extensions/hooks/index.ts +209 -58
  116. package/extensions/hooks/matcher.ts +3 -0
  117. package/extensions/hooks/prompt-context.ts +59 -0
  118. package/extensions/hooks/protocol.ts +41 -3
  119. package/extensions/hooks/settings.ts +50 -19
  120. package/extensions/hooks/subagent-bridge.ts +2 -0
  121. package/extensions/hooks/trust.ts +26 -12
  122. package/extensions/idle-compact/index.ts +119 -0
  123. package/extensions/idle-compact/policy.ts +143 -0
  124. package/extensions/init/index.ts +11 -10
  125. package/extensions/init/prompt.ts +25 -32
  126. package/extensions/interrupted/index.ts +13 -1
  127. package/extensions/kept-thinking/index.ts +27 -0
  128. package/extensions/ledger/index.ts +46 -0
  129. package/extensions/ledger/wire.ts +154 -0
  130. package/extensions/lib/agent-cron.ts +146 -0
  131. package/extensions/lib/agent-loader.ts +18 -3
  132. package/extensions/lib/agent-view.ts +85 -0
  133. package/extensions/lib/anthropic-auth.ts +98 -0
  134. package/extensions/lib/anthropic-payload.ts +82 -1
  135. package/extensions/lib/anthropic-server-call.ts +230 -0
  136. package/extensions/lib/anthropic-server-tools.ts +485 -0
  137. package/extensions/lib/app-launch.mjs +94 -0
  138. package/extensions/lib/argument-hints.ts +190 -0
  139. package/extensions/lib/atomic-write.ts +6 -2
  140. package/extensions/lib/auto-memory.ts +75 -0
  141. package/extensions/lib/bash-parser.ts +84 -0
  142. package/extensions/lib/btw-fork.ts +93 -0
  143. package/extensions/lib/child-extensions.ts +52 -0
  144. package/extensions/lib/child-writes.ts +45 -0
  145. package/extensions/lib/claude-context.ts +515 -100
  146. package/extensions/lib/claude-external-includes.ts +68 -0
  147. package/extensions/lib/claude-id.ts +22 -0
  148. package/extensions/lib/claude-rules.ts +323 -0
  149. package/extensions/lib/claude-settings.ts +76 -4
  150. package/extensions/lib/compaction-boundary.ts +36 -0
  151. package/extensions/lib/compaction-keep.mjs +83 -0
  152. package/extensions/lib/config-mode.ts +112 -0
  153. package/extensions/lib/consent-dialogs.ts +63 -0
  154. package/extensions/lib/consent-preview.ts +5 -1
  155. package/extensions/lib/consent-stores.ts +48 -0
  156. package/extensions/lib/context-facts.ts +97 -0
  157. package/extensions/lib/covered-messages.ts +23 -0
  158. package/extensions/lib/deferred.ts +359 -25
  159. package/extensions/lib/dock-rows.ts +60 -0
  160. package/extensions/lib/empty-tool-result.ts +27 -0
  161. package/extensions/lib/environment-block.ts +76 -0
  162. package/extensions/lib/fetch-timeout.ts +24 -6
  163. package/extensions/{system-prompt → lib}/git-status.ts +51 -13
  164. package/extensions/lib/git.ts +75 -13
  165. package/extensions/lib/grammars/LICENSE-tree-sitter-bash +21 -0
  166. package/extensions/lib/grammars/README.md +2 -0
  167. package/extensions/lib/grammars/tree-sitter-bash.wasm +0 -0
  168. package/extensions/lib/guide-docs.ts +45 -0
  169. package/extensions/lib/headless-output.ts +46 -0
  170. package/extensions/lib/hook-gate.ts +7 -7
  171. package/extensions/lib/interrupt.ts +20 -4
  172. package/extensions/lib/key-input.ts +455 -0
  173. package/extensions/lib/keys.ts +14 -1
  174. package/extensions/lib/ledger/fold-memo.ts +49 -0
  175. package/extensions/lib/ledger/fold.ts +265 -0
  176. package/extensions/lib/ledger/layout.ts +72 -0
  177. package/extensions/lib/ledger/plan.ts +102 -0
  178. package/extensions/lib/ledger/records.ts +276 -0
  179. package/extensions/lib/ledger/state.ts +47 -0
  180. package/extensions/lib/ledger/validate.ts +141 -0
  181. package/extensions/lib/ledger/wire.ts +632 -0
  182. package/extensions/lib/local-command.ts +71 -19
  183. package/extensions/lib/mcp-overrides.ts +1 -1
  184. package/extensions/lib/mcp-share.ts +46 -0
  185. package/extensions/lib/memory-content.ts +146 -0
  186. package/extensions/lib/memory-index.ts +18 -0
  187. package/extensions/lib/memory.ts +134 -123
  188. package/extensions/lib/model-catalog/huggingface.json +178 -0
  189. package/extensions/lib/model-catalog/models-dev.json +18533 -0
  190. package/extensions/lib/model-catalog/openrouter.json +5050 -0
  191. package/extensions/lib/model-catalog-data.ts +513 -0
  192. package/extensions/lib/model-catalog.ts +462 -0
  193. package/extensions/lib/model-choice-warnings.ts +137 -0
  194. package/extensions/lib/model-pairings.ts +152 -0
  195. package/extensions/{auto-mode → lib}/model-picker.ts +26 -43
  196. package/extensions/lib/model-policy.ts +112 -15
  197. package/extensions/lib/model-tier.ts +283 -355
  198. package/extensions/lib/model-unusable.ts +1 -1
  199. package/extensions/lib/newer-model.ts +100 -0
  200. package/extensions/lib/notices.ts +87 -0
  201. package/extensions/lib/notifications.ts +357 -73
  202. package/extensions/lib/one-code-settings.ts +74 -8
  203. package/extensions/lib/open-browser.ts +63 -0
  204. package/extensions/lib/openrouter-generation.ts +94 -0
  205. package/extensions/lib/operation-deadline.ts +30 -0
  206. package/extensions/lib/original-command.ts +4 -4
  207. package/extensions/lib/package-version.ts +1 -1
  208. package/extensions/lib/panel-focus.ts +134 -0
  209. package/extensions/lib/paths.ts +17 -2
  210. package/extensions/lib/permission-gate.ts +72 -6
  211. package/extensions/lib/persisted-output.ts +60 -8
  212. package/extensions/lib/pi-ai-estimate.ts +19 -3
  213. package/extensions/lib/pi-version.ts +38 -2
  214. package/extensions/lib/plan-mode-channels.ts +42 -5
  215. package/extensions/lib/plugins.ts +26 -17
  216. package/extensions/lib/powershell-parse-script.ts +208 -0
  217. package/extensions/lib/powershell-parser.ts +344 -0
  218. package/extensions/lib/previous-mark.ts +101 -0
  219. package/extensions/lib/process-state.ts +48 -0
  220. package/extensions/lib/process-tree.ts +132 -8
  221. package/extensions/lib/prompt-options.ts +82 -0
  222. package/extensions/lib/queued-delivery.ts +44 -0
  223. package/extensions/lib/reminders.ts +370 -358
  224. package/extensions/lib/replaced-builtins.mjs +199 -0
  225. package/extensions/lib/replay-call.ts +70 -0
  226. package/extensions/lib/request-replay.ts +547 -0
  227. package/extensions/lib/scratchpad.ts +81 -14
  228. package/extensions/lib/send-now-channel.ts +7 -0
  229. package/extensions/lib/session-model-tier.ts +51 -0
  230. package/extensions/lib/session-work.ts +64 -0
  231. package/extensions/lib/settings-channels.ts +4 -4
  232. package/extensions/lib/shell-exit-semantics.ts +170 -0
  233. package/extensions/lib/shell-quote.ts +11 -0
  234. package/extensions/lib/shell-result.ts +70 -0
  235. package/extensions/lib/shell-spawn.ts +70 -6
  236. package/extensions/lib/shell-tool.ts +75 -25
  237. package/extensions/lib/side-call-cache.ts +124 -0
  238. package/extensions/lib/side-call-run.ts +96 -0
  239. package/extensions/lib/side-call-usage.ts +38 -0
  240. package/extensions/lib/side-call.ts +24 -1
  241. package/extensions/lib/single-flight.ts +18 -0
  242. package/extensions/lib/skill-body.ts +42 -0
  243. package/extensions/lib/skill-scan.ts +63 -24
  244. package/extensions/lib/spill-file.ts +140 -0
  245. package/extensions/lib/subagent-handback.ts +112 -0
  246. package/extensions/lib/system-role.ts +156 -0
  247. package/extensions/lib/terminal-text.ts +114 -0
  248. package/extensions/lib/text-width.ts +47 -16
  249. package/extensions/lib/timer-ops.ts +20 -0
  250. package/extensions/lib/tool-additions.ts +129 -0
  251. package/extensions/lib/tool-call-corruption.ts +134 -0
  252. package/extensions/lib/tool-path.ts +66 -0
  253. package/extensions/lib/tool-variants.ts +69 -0
  254. package/extensions/lib/tui-render.ts +255 -27
  255. package/extensions/lib/turn-budget-layout.ts +159 -0
  256. package/extensions/lib/update-check.mjs +15 -2
  257. package/extensions/lib/usage-bus.ts +1 -1
  258. package/extensions/lib/user-denial.ts +38 -0
  259. package/extensions/lib/workspace-channel.ts +16 -0
  260. package/extensions/lib/worktree-channel.ts +31 -3
  261. package/extensions/lib/worktree-isolation.ts +40 -10
  262. package/extensions/lsp/client.ts +8 -9
  263. package/extensions/lsp/index.ts +76 -12
  264. package/extensions/lsp/keep-alive.ts +1 -1
  265. package/extensions/lsp/trust.ts +119 -0
  266. package/extensions/lsp/watcher.ts +1 -1
  267. package/extensions/mcp/announce.ts +90 -43
  268. package/extensions/mcp/client.ts +161 -48
  269. package/extensions/mcp/config.ts +132 -8
  270. package/extensions/mcp/discovery.ts +19 -0
  271. package/extensions/mcp/index.ts +220 -121
  272. package/extensions/mcp/oauth/browser.ts +38 -17
  273. package/extensions/mcp/oauth/flow.ts +25 -17
  274. package/extensions/mcp/oauth/provider.ts +14 -8
  275. package/extensions/mcp/oauth/store.ts +34 -16
  276. package/extensions/mcp/panel/keys.ts +12 -11
  277. package/extensions/mcp/panel/render.ts +9 -6
  278. package/extensions/mcp/schema.ts +104 -5
  279. package/extensions/mcp/trust.ts +164 -73
  280. package/extensions/memory/entries.ts +23 -14
  281. package/extensions/memory/index.ts +134 -28
  282. package/extensions/memory/open-external.ts +33 -18
  283. package/extensions/memory/panel.ts +135 -26
  284. package/extensions/model-default/index.ts +86 -19
  285. package/extensions/newer-model/index.ts +31 -0
  286. package/extensions/notebook/description.ts +18 -0
  287. package/extensions/notebook/index.ts +6 -5
  288. package/extensions/notebook/notebook.ts +1 -1
  289. package/extensions/permissions/index.ts +1426 -398
  290. package/extensions/permissions/matcher.ts +425 -74
  291. package/extensions/permissions/modes.ts +11 -4
  292. package/extensions/permissions/panel/host.ts +130 -0
  293. package/extensions/permissions/panel/keys.ts +48 -0
  294. package/extensions/permissions/panel/render.ts +450 -0
  295. package/extensions/permissions/panel/state.ts +550 -0
  296. package/extensions/permissions/powershell-cmdlets.ts +198 -0
  297. package/extensions/permissions/powershell-paths.ts +197 -0
  298. package/extensions/permissions/powershell-rules.ts +207 -280
  299. package/extensions/permissions/powershell-tree.ts +557 -0
  300. package/extensions/permissions/project-trust.ts +27 -11
  301. package/extensions/permissions/protected-paths.ts +14 -2
  302. package/extensions/permissions/session-grant.ts +6 -0
  303. package/extensions/permissions/settings.ts +166 -31
  304. package/extensions/permissions/subagent-gate.ts +25 -0
  305. package/extensions/permissions/workspace.ts +78 -0
  306. package/extensions/plan-mode/index.ts +276 -92
  307. package/extensions/plan-mode/reminder.ts +89 -21
  308. package/extensions/plan-mode/run-state.ts +26 -0
  309. package/extensions/plan-mode/texts.ts +177 -0
  310. package/extensions/plan-mode/viewer.ts +92 -27
  311. package/extensions/plugins/counts.ts +3 -3
  312. package/extensions/plugins/index.ts +64 -46
  313. package/extensions/plugins/install/install.ts +16 -0
  314. package/extensions/plugins/marketplace/sync.ts +9 -3
  315. package/extensions/plugins/marketplace/types.ts +3 -1
  316. package/extensions/plugins/panel/keys.ts +21 -24
  317. package/extensions/plugins/panel/render.ts +12 -6
  318. package/extensions/plugins/shell-expand.ts +107 -0
  319. package/extensions/plugins/template.ts +32 -15
  320. package/extensions/powershell/child.ts +7 -0
  321. package/extensions/powershell/description.ts +38 -6
  322. package/extensions/powershell/guards.ts +1 -1
  323. package/extensions/powershell/index.ts +14 -7
  324. package/extensions/recap/index.ts +73 -71
  325. package/extensions/recap/prompt.ts +2 -2
  326. package/extensions/recap/scheduler.ts +3 -5
  327. package/extensions/search-tools/grep-merge.ts +39 -0
  328. package/extensions/search-tools/index.ts +0 -0
  329. package/extensions/send-now/chord.ts +62 -0
  330. package/extensions/send-now/index.ts +133 -0
  331. package/extensions/session-title/index.ts +3 -0
  332. package/extensions/session-title/title.ts +4 -1
  333. package/extensions/skill/announce.ts +30 -0
  334. package/extensions/skill/code-review.ts +97 -0
  335. package/extensions/skill/index.ts +469 -132
  336. package/extensions/skill/invoke.ts +118 -75
  337. package/extensions/skill/listing.ts +133 -9
  338. package/extensions/skill/panel/keys.ts +15 -16
  339. package/extensions/skill/panel/render.ts +5 -2
  340. package/extensions/skill/panel/state.ts +12 -1
  341. package/extensions/subagents/agent-args.ts +39 -0
  342. package/extensions/subagents/agent-description.ts +132 -0
  343. package/extensions/subagents/agents.ts +146 -31
  344. package/extensions/subagents/default-model.ts +2 -3
  345. package/extensions/subagents/delegation-steer.ts +4 -4
  346. package/extensions/subagents/fork-cache.ts +82 -0
  347. package/extensions/subagents/guide-agent.ts +189 -0
  348. package/extensions/subagents/hand-back-review.ts +3 -0
  349. package/extensions/subagents/index.ts +1594 -852
  350. package/extensions/subagents/live-runs.ts +26 -6
  351. package/extensions/subagents/model-select.ts +38 -25
  352. package/extensions/subagents/outcome.ts +5 -2
  353. package/extensions/subagents/panel-keys.ts +73 -31
  354. package/extensions/subagents/panel-render.ts +120 -96
  355. package/extensions/subagents/panel-widget.ts +60 -89
  356. package/extensions/subagents/parent-mode.ts +50 -0
  357. package/extensions/subagents/pending-claim.ts +18 -1
  358. package/extensions/subagents/runner.ts +135 -80
  359. package/extensions/subagents/runs.ts +44 -5
  360. package/extensions/subagents/send-to-main-tool.ts +1 -1
  361. package/extensions/subagents/session-turns.ts +32 -8
  362. package/extensions/subagents/shell-panel.ts +36 -178
  363. package/extensions/subagents/tasks-dialog.ts +170 -0
  364. package/extensions/subagents/viewport-mirror.ts +95 -0
  365. package/extensions/subagents/worktree.ts +57 -13
  366. package/extensions/system-prompt/environment.ts +19 -19
  367. package/extensions/system-prompt/idle-turn.ts +65 -0
  368. package/extensions/system-prompt/index.ts +165 -47
  369. package/extensions/system-prompt/template.ts +34 -51
  370. package/extensions/system-prompt/tiers/common.ts +23 -64
  371. package/extensions/system-prompt/tiers/frontier.ts +32 -11
  372. package/extensions/system-prompt/tiers/low.ts +67 -45
  373. package/extensions/system-prompt/tiers/mid.ts +96 -38
  374. package/extensions/system-reminder/index.ts +204 -70
  375. package/extensions/tasks/descriptions.ts +190 -0
  376. package/extensions/tasks/index.ts +120 -41
  377. package/extensions/tasks/store.ts +83 -16
  378. package/extensions/tool-call-corruption/child.ts +7 -0
  379. package/extensions/tool-call-corruption/index.ts +237 -0
  380. package/extensions/tool-search/index.ts +366 -144
  381. package/extensions/tool-style/index.ts +68 -10
  382. package/extensions/tool-style/write-description.ts +40 -0
  383. package/extensions/tool-style/write-render.ts +237 -0
  384. package/extensions/turn-duration/index.ts +7 -3
  385. package/extensions/turn-duration/line.ts +47 -4
  386. package/extensions/web/backends.ts +6 -9
  387. package/extensions/web/description.ts +50 -0
  388. package/extensions/web/index.ts +118 -53
  389. package/extensions/web/native-call.ts +15 -0
  390. package/extensions/web/native-results.ts +41 -0
  391. package/extensions/web-fetch/description.ts +42 -0
  392. package/extensions/web-fetch/extract.ts +53 -6
  393. package/extensions/web-fetch/index.ts +125 -76
  394. package/extensions/web-fetch/page-content.ts +19 -0
  395. package/extensions/web-fetch/response.ts +49 -0
  396. package/extensions/web-fetch/summarize.ts +9 -10
  397. package/extensions/workflow/agent-session.ts +108 -18
  398. package/extensions/workflow/args.ts +24 -0
  399. package/extensions/workflow/description.ts +67 -0
  400. package/extensions/workflow/globals.ts +17 -3
  401. package/extensions/workflow/index.ts +157 -162
  402. package/extensions/workflow/records.ts +1 -0
  403. package/extensions/workflow/run-manager.ts +33 -6
  404. package/extensions/workflow/saved-workflows.ts +3 -2
  405. package/extensions/workflow/types.ts +22 -1
  406. package/extensions/workflow/viewer.ts +54 -24
  407. package/extensions/workflow/widget.ts +20 -0
  408. package/extensions/worktree/descriptions.ts +91 -0
  409. package/extensions/worktree/guards.ts +316 -54
  410. package/extensions/worktree/index.ts +162 -44
  411. package/extensions/worktree/powershell-guards.ts +167 -0
  412. package/extensions/worktree/rewrite.ts +14 -16
  413. package/package.json +21 -7
  414. package/skills/artifact-design/SKILL.md +85 -0
  415. package/skills/code-review/SKILL.md +20 -20
  416. package/skills/code-review/cells/arguments-and-flags.md +19 -0
  417. package/skills/code-review/cells/high-3x5-recall-verify.md +137 -0
  418. package/skills/code-review/cells/high-8-inline.md +122 -0
  419. package/skills/code-review/cells/low-1-pass-max4.md +27 -0
  420. package/skills/code-review/cells/low-1-pass-min-files-4.md +28 -0
  421. package/skills/code-review/cells/max-5x5-verify-sweep.md +162 -0
  422. package/skills/code-review/cells/medium-3x5-verify.md +132 -0
  423. package/skills/code-review/cells/minimal-prompt.md +32 -0
  424. package/skills/code-review/cells/xhigh-10-inline-sweep.md +149 -0
  425. package/skills/code-review/cells/xhigh-5x5-verify-sweep.md +162 -0
  426. package/skills/fewer-permission-prompts/SKILL.md +1 -1
  427. package/skills/loop/SKILL.md +11 -0
  428. package/skills/security-review/SKILL.md +2 -5
  429. package/skills/simplify/SKILL.md +7 -5
  430. package/skills/workflow-authoring/SKILL.md +143 -0
  431. package/themes/onecode-light.json +1 -1
  432. package/themes/onecode.json +1 -1
  433. package/types/app.d.ts +58 -0
  434. package/types/community-packages.d.ts +26 -1
  435. package/extensions/auto-mode/recoverability.ts +0 -229
  436. package/extensions/lib/capability-index.ts +0 -466
  437. package/extensions/lib/model-facts.generated.json +0 -2675
  438. package/extensions/lib/model-facts.ts +0 -162
  439. package/extensions/tool-search/announce.ts +0 -42
@@ -14,13 +14,16 @@
14
14
  * `extensionFactories`, which DefaultResourceLoader always loads.
15
15
  */
16
16
 
17
+ import { childWriteWatcher } from "../lib/child-writes.ts";
18
+ import { randomBytes } from "node:crypto";
17
19
  import os from "node:os";
18
20
  import { getAgentDir, type ModelRuntime, SessionManager, type ToolDefinition } from "@earendil-works/pi-coding-agent";
19
21
  import type { AgentMessage } from "@earendil-works/pi-agent-core";
20
22
  import type { Api, Model } from "@earendil-works/pi-ai";
21
23
  import { Type } from "typebox";
22
24
  import { whenAborted } from "../lib/abort.ts";
23
- import { createSharedModelRuntime, finalAssistantText, openChildSession } from "../lib/agent-loader.ts";
25
+ import { persistIfLarge, sessionResultsDir } from "../lib/persisted-output.ts";
26
+ import { createSharedModelRuntime, disposeChildSession, finalAssistantText, openChildSession } from "../lib/agent-loader.ts";
24
27
  import { modelSpec as modelSpecOf, supportsImageInput } from "../lib/model-policy.ts";
25
28
  import { isModelUnavailableError } from "../auto-mode/model-select.ts";
26
29
  import { agentPromptIdentity, PrefixWarmGate, prefixWarmKey } from "../lib/prefix-warm-gate.ts";
@@ -28,13 +31,17 @@ import type { PermissionBridge } from "../permissions/subagent-gate.ts";
28
31
  import { localGateMode, MODE_ENV } from "../lib/permission-gate.ts";
29
32
  import type { HookBridge } from "../hooks/subagent-bridge.ts";
30
33
  import { summarizeArgs } from "../lib/tui-render.ts";
31
- import { agentDirs, type AgentDefinition, discoverAgents } from "../subagents/agents.ts";
34
+ import { type AgentDefinition, agentFileSources, agentToolOptions, discoverAgents, unusableAllowlistError } from "../subagents/agents.ts";
35
+ import { defaultDiscoverRoots, discoverPlugins } from "../lib/plugins.ts";
36
+ import { CHILD_EXTENSION_PATHS } from "../lib/child-extensions.ts";
37
+ import { oneTurnHandbackSlot, subagentHandbackExtension } from "../lib/subagent-handback.ts";
32
38
  import type { SubagentDefault } from "../subagents/default-model.ts";
33
39
  import { expensiveModelGate, resolveSubagentModel, subagentModelMenu } from "../subagents/model-select.ts";
34
40
  import { withoutUnusable } from "../lib/model-unusable.ts";
35
41
  import { cleanupWorktree, createWorktree, isGitRepo, type Worktree } from "../subagents/worktree.ts";
36
- import type { AgentCallOptions, AgentCallResult, AgentEffort, AgentRunUpdate } from "./types.ts";
42
+ import type { AgentCallOptions, AgentCallResult, AgentEffort, AgentRunUpdate, KeptWorktree } from "./types.ts";
37
43
  import { WorkflowScriptError } from "./types.ts";
44
+ import { type DeferRequest, deferLikeParentExtension, injectedByParent } from "../lib/deferred.ts";
38
45
 
39
46
  const MAX_SCHEMA_RETRIES = 2;
40
47
  const OUTPUT_CAP = 50_000;
@@ -52,6 +59,8 @@ export interface AgentRunnerOptions {
52
59
  unusableModels?: () => ReadonlySet<string>;
53
60
  /** An agent's provider refused its model as not usable on this account (`isModelUnavailableError`): report it so every picker skips it. */
54
61
  onModelUnusable?: (model: string, reason: string) => void;
62
+ /** An agent's edit or write changed a file (lib/child-writes.ts), for the parent's file-tracker. */
63
+ onChildWrite?: (path: string, agent: string | undefined) => void;
55
64
  /**
56
65
  * The parent permissions extension's decision closure (same bridge the
57
66
  * subagent runner uses): when present, a workflow agent's tool calls route
@@ -65,6 +74,15 @@ export interface AgentRunnerOptions {
65
74
  getHookBridge?: () => HookBridge | undefined;
66
75
  /** Each finished agent's dollar cost (review S13: workflow agents never reached the footer). */
67
76
  onUsage?: (cost: number) => void;
77
+ /**
78
+ * The parent's live MCP tools (lib/mcp-share.ts `watchMcpTools`), injected
79
+ * as custom tools over the parent's connections, as the subagent runner does.
80
+ */
81
+ getMcpTools?: () => ToolDefinition[] | Promise<ToolDefinition[]>;
82
+ /** The tools the parent defers (lib/deferred.ts DEFERRED_QUERY_CHANNEL): the agent defers them too, so its MCP tools are listed, not declared. */
83
+ getParentDeferred?: () => DeferRequest[];
84
+ /** Where an answer past OUTPUT_CAP is saved (`<dir>/tool-results/`): the run's directory. */
85
+ resultsDir?: string;
68
86
  }
69
87
 
70
88
  /**
@@ -199,7 +217,9 @@ export class AgentRunner {
199
217
  static async create(options: AgentRunnerOptions): Promise<AgentRunner> {
200
218
  const agentDir = getAgentDir();
201
219
  const modelRuntime = await createSharedModelRuntime(agentDir);
202
- const agentCatalog = discoverAgents(agentDirs(options.cwd, os.homedir()));
220
+ // The Agent tool's registry: bundled and plugin agents too, not only the user and project folders.
221
+ const plugins = discoverPlugins(defaultDiscoverRoots(agentDir, options.cwd));
222
+ const agentCatalog = discoverAgents(agentFileSources(options.cwd, os.homedir(), plugins.agentDirs));
203
223
  const availableModels = [...(await modelRuntime.getAvailable())];
204
224
  return new AgentRunner(options, modelRuntime, agentCatalog, availableModels);
205
225
  }
@@ -245,6 +265,12 @@ export class AgentRunner {
245
265
 
246
266
  await this.judgeDelegation(prompt, opts, agentDef, signal);
247
267
 
268
+ // Before the worktree exists: a malformed schema would otherwise leak it.
269
+ if (opts.schema) assertObjectSchema(opts.schema);
270
+
271
+ // Also before the worktree: a rejection here would leak it the same way.
272
+ const mcpTools = (await this.options.getMcpTools?.()) ?? [];
273
+
248
274
  let worktree: Worktree | undefined;
249
275
  let cwd = this.options.cwd;
250
276
  if (opts.isolation === "worktree") {
@@ -256,13 +282,27 @@ export class AgentRunner {
256
282
  }
257
283
 
258
284
  const capture: { called: boolean; value: unknown } = { called: false, value: undefined };
259
- const customTools: ToolDefinition[] = opts.schema ? [buildStructuredOutputTool(opts.schema, capture)] : [];
285
+ // An agent without a schema hands its answer back through SubagentHandback,
286
+ // as every child does; with a schema, structured_output is the hand-back.
287
+ const handback = opts.schema ? undefined : oneTurnHandbackSlot();
288
+ const customTools: ToolDefinition[] = [
289
+ ...(opts.schema ? [buildStructuredOutputTool(opts.schema, capture)] : []),
290
+ ...mcpTools,
291
+ ];
260
292
 
293
+ // The same child session a subagent gets (SUBAGENTS-WORKFLOWS-REVIEW-2026-09-26
294
+ // H2, H3, M6): the curated child extensions, the parent's MCP tools, and the
295
+ // agent file's tool lists through the one shared builder, which keeps
296
+ // `structured_output` on an allowlist and applies `disallowedTools`.
261
297
  const session = await openChildSession({
262
298
  loader: {
263
299
  cwd: this.options.cwd,
264
300
  agentDir: getAgentDir(),
265
301
  systemPrompt: agentDef?.systemPrompt,
302
+ extraExtensionPaths: CHILD_EXTENSION_PATHS,
303
+ // claude-context (a child extension) injects the CLAUDE.md instructions itself.
304
+ noContextFiles: true,
305
+ extraFactories: [deferLikeParentExtension(this.options.getParentDeferred?.() ?? [], injectedByParent([])), ...(handback ? [subagentHandbackExtension(handback)] : [])],
266
306
  getPermissionBridge: this.options.getPermissionBridge,
267
307
  getHookBridge: this.options.getHookBridge,
268
308
  },
@@ -272,11 +312,16 @@ export class AgentRunner {
272
312
  modelRuntime: this.modelRuntime,
273
313
  model: modelSpec.model as never,
274
314
  thinkingLevel: modelSpec.thinkingLevel as never,
275
- tools: agentDef?.tools,
315
+ ...agentToolOptions(agentDef),
276
316
  customTools,
277
317
  sessionManager: SessionManager.inMemory(cwd),
278
318
  },
279
319
  onError: (error) => this.options.onNotice?.(`${opts.label ?? "agent"}: extension error in ${error.event}: ${error.error}`),
320
+ }).catch(async (error: unknown) => {
321
+ // Not yet under the prompt's try/finally: a session that fails to open
322
+ // must not leak the worktree and its branch.
323
+ if (worktree) await this.settleWorktree(worktree, opts.label, error);
324
+ throw error;
280
325
  });
281
326
 
282
327
  const unhookAbort = whenAborted(signal, () => void session.abort());
@@ -284,8 +329,11 @@ export class AgentRunner {
284
329
  // refusing the agent's model (the same check the subagent runner makes, so
285
330
  // the refusal reaches every automatic picker — lib/model-unusable.ts).
286
331
  // Never let a bad event shape kill the agent.
332
+ const childWrote = childWriteWatcher(session.sessionManager?.getCwd?.() ?? this.options.cwd);
287
333
  const unsubscribe = session.subscribe((event) => {
288
334
  try {
335
+ const wrote = childWrote(event as never);
336
+ if (wrote) this.options.onChildWrite?.(wrote, opts.label);
289
337
  if (event.type === "message_end") {
290
338
  const reply = (event as { message?: { role?: string; stopReason?: string; errorMessage?: string; provider?: string; model?: string } }).message;
291
339
  if (reply?.role === "assistant" && reply.stopReason === "error" && reply.errorMessage && reply.provider && reply.model && isModelUnavailableError(reply.errorMessage)) {
@@ -310,7 +358,17 @@ export class AgentRunner {
310
358
  prefixWarmKey(agentPromptIdentity(agentDef?.name), cwd, model ? modelSpecOf(model) : undefined),
311
359
  session,
312
360
  );
361
+ let failure: unknown;
313
362
  try {
363
+ // An allowlist that matched no real tool would run a tool-less agent.
364
+ const unusable = unusableAllowlistError(
365
+ agentDef,
366
+ session.getAllTools().map((t) => t.name),
367
+ );
368
+ if (unusable) throw new WorkflowScriptError(unusable);
369
+ // A stop during the waits above (MCP tools still connecting, the warm
370
+ // gate) aborted a session that was idle: never send the first request.
371
+ if (signal.aborted) throw new WorkflowScriptError("aborted");
314
372
  await session.prompt(this.buildPrompt(prompt, Boolean(opts.schema)));
315
373
  if (signal.aborted) throw new WorkflowScriptError("aborted");
316
374
 
@@ -318,27 +376,39 @@ export class AgentRunner {
318
376
  if (opts.schema) {
319
377
  value = await this.resolveStructuredOutput(session, capture, signal);
320
378
  } else {
321
- value = finalAssistantText(session.messages);
379
+ // The handed-back report, else the agent's last message.
380
+ value = handback?.report ?? finalAssistantText(session.messages);
322
381
  if (typeof value !== "string" || !value.trim()) {
323
382
  throw new Error("subagent produced no output");
324
383
  }
325
- value = (value as string).slice(0, OUTPUT_CAP);
384
+ // Never cut: a long answer is saved to the run directory and the script
385
+ // gets Claude Code's <persisted-output> block naming the file, which a
386
+ // later agent can read (SUBAGENTS-WORKFLOWS-REVIEW-2026-09-26 M1).
387
+ value = persistIfLarge(value as string, {
388
+ dir: this.options.resultsDir ?? sessionResultsDir(undefined),
389
+ id: `agent-${randomBytes(4).toString("hex")}`,
390
+ maxBytes: OUTPUT_CAP,
391
+ });
326
392
  }
327
393
 
328
394
  const stats = session.getSessionStats();
329
- // cleanupWorktree keeps trees holding uncommitted changes; report those.
330
- let worktreePath: string | undefined;
395
+ // cleanupWorktree keeps trees holding uncommitted changes or commits; report those.
396
+ let kept: Worktree | undefined;
331
397
  if (worktree) {
332
398
  const removed = await cleanupWorktree(this.options.cwd, worktree);
333
- if (!removed) worktreePath = worktree.path;
399
+ if (!removed) kept = worktree;
334
400
  worktree = undefined;
335
401
  }
336
402
  return {
337
403
  value,
338
404
  tokens: { input: stats.tokens.input, output: stats.tokens.output, total: stats.tokens.total },
339
405
  cost: stats.cost,
340
- worktreePath,
406
+ worktreePath: kept?.path,
407
+ worktreeBranch: kept?.branch,
341
408
  };
409
+ } catch (error) {
410
+ failure = error;
411
+ throw error;
342
412
  } finally {
343
413
  // Whatever the outcome — success, failure, or an abort (a user stop, or
344
414
  // the run finishing with this agent un-awaited) — the provider was
@@ -348,11 +418,26 @@ export class AgentRunner {
348
418
  releasePrefix(false);
349
419
  unsubscribe?.();
350
420
  unhookAbort();
351
- session.dispose();
352
- if (worktree) await cleanupWorktree(this.options.cwd, worktree);
421
+ disposeChildSession(session);
422
+ // A failed or aborted agent can still have edited or committed in its
423
+ // worktree: settled after the session is gone, before the error reaches
424
+ // the caller, so the kept path rides on it.
425
+ if (worktree) await this.settleWorktree(worktree, opts.label, failure);
353
426
  }
354
427
  }
355
428
 
429
+ /**
430
+ * Remove a failed agent's worktree, or keep it when it holds changes or
431
+ * commits: then the run log names it, and the kept path rides on `error`
432
+ * (`keptWorktreeOf`) so the agent's end event and the run report list it.
433
+ */
434
+ private async settleWorktree(worktree: Worktree, label: string | undefined, error: unknown): Promise<void> {
435
+ if (await cleanupWorktree(this.options.cwd, worktree)) return;
436
+ const kept: KeptWorktree = { path: worktree.path, branch: worktree.branch };
437
+ this.options.onNotice?.(`${label ?? "agent"}: worktree kept at ${kept.path} (branch ${kept.branch}) with its changes or commits`);
438
+ if (error instanceof Error) (error as Error & { keptWorktree?: KeptWorktree }).keptWorktree = kept;
439
+ }
440
+
356
441
  private judgeDelegation(prompt: string, opts: AgentCallOptions, agentDef: AgentDefinition | undefined, signal: AbortSignal): Promise<void> {
357
442
  return judgeWorkflowDelegation({
358
443
  bridge: this.options.getPermissionBridge?.(),
@@ -367,7 +452,7 @@ export class AgentRunner {
367
452
 
368
453
  private buildPrompt(prompt: string, structured: boolean): string {
369
454
  if (!structured) {
370
- return `${prompt}\n\nYour final message is returned verbatim to an orchestration script, not shown to a human — reply with the requested data/report only.`;
455
+ return `${prompt}\n\nThe report you hand back through SubagentHandback is returned verbatim to an orchestration script, not shown to a human — hand back the requested data/report only.`;
371
456
  }
372
457
  return `${prompt}\n\nWhen you are done, you MUST call the \`structured_output\` tool exactly once with your final result. Its arguments are the only output the caller receives.`;
373
458
  }
@@ -398,9 +483,7 @@ export class AgentRunner {
398
483
 
399
484
  /** Terminating tool capturing schema-validated output (pi validates params pre-execute). */
400
485
  function buildStructuredOutputTool(schema: Record<string, unknown>, capture: { called: boolean; value: unknown }): ToolDefinition {
401
- if (schema.type !== "object" || typeof schema.properties !== "object") {
402
- throw new WorkflowScriptError("agent() schema must be a JSON Schema with top-level type \"object\" and properties");
403
- }
486
+ assertObjectSchema(schema);
404
487
  return {
405
488
  name: "structured_output",
406
489
  label: "Structured Output",
@@ -418,6 +501,13 @@ function buildStructuredOutputTool(schema: Record<string, unknown>, capture: { c
418
501
  } as ToolDefinition;
419
502
  }
420
503
 
504
+ /** A structured_output schema must be an object schema with properties. */
505
+ function assertObjectSchema(schema: Record<string, unknown>): void {
506
+ if (schema.type !== "object" || typeof schema.properties !== "object") {
507
+ throw new WorkflowScriptError("agent() schema must be a JSON Schema with top-level type \"object\" and properties");
508
+ }
509
+ }
510
+
421
511
  /** Pull the first parseable JSON object/array out of free text (```json fences first). */
422
512
  function extractJsonObject(text: string): unknown {
423
513
  const fenced = text.match(/```(?:json)?\s*\n([\s\S]*?)\n```/);
@@ -0,0 +1,24 @@
1
+ /** The workflow tool's argument preparation (pure). */
2
+
3
+ /**
4
+ * The call's arguments with `args` as the script should see it, decoded before
5
+ * the gate, hooks and the stored call see them. Weak models send a list or
6
+ * object as a JSON-encoded string despite the description (every Qwen 3.8
7
+ * model, battery round 7), which breaks `args.map` and `pipeline(args, …)`; a
8
+ * string that parses to an array or object is decoded. Any other value passes
9
+ * verbatim.
10
+ */
11
+ export function prepareWorkflowArguments(raw: unknown): unknown {
12
+ if (!raw || typeof raw !== "object" || !("args" in raw)) return raw;
13
+ return { ...raw, args: decodedArgs((raw as { args: unknown }).args) };
14
+ }
15
+
16
+ function decodedArgs(args: unknown): unknown {
17
+ if (typeof args !== "string" || !/^\s*[[{]/.test(args)) return args;
18
+ try {
19
+ const parsed: unknown = JSON.parse(args);
20
+ return parsed !== null && typeof parsed === "object" ? parsed : args;
21
+ } catch {
22
+ return args;
23
+ }
24
+ }
@@ -0,0 +1,67 @@
1
+ /**
2
+ * The workflow tool's model-facing description: Claude Code's Workflow text
3
+ * and its size-guideline line (pure).
4
+ *
5
+ * The authoring reference (script API, quality patterns, resume, worked
6
+ * examples) is the bundled `workflow-authoring` skill, which the description
7
+ * tells the model to load before writing a script. The size line follows
8
+ * `workflowSizeGuideline` in One Code's settings (lib/one-code-settings.ts);
9
+ * "unrestricted" sends no line, as in Claude Code. Changes from Claude Code's
10
+ * text: the setting is named where Claude Code points to its /config row, and
11
+ * tool names are One Code's.
12
+ */
13
+
14
+ import type { WorkflowSizeGuideline } from "../lib/one-code-settings.ts";
15
+
16
+ export const WORKFLOW_DESCRIPTION_BODY = `Execute a workflow script that orchestrates multiple subagents deterministically. Workflows run in the background — this tool returns immediately with a task ID, and a <task-notification> arrives when the workflow completes. Use /workflows to watch live progress.
17
+
18
+ ONLY call this tool when the user has explicitly opted into multi-agent orchestration. Workflows can spawn dozens of agents and consume a large amount of tokens; the user must request that scale, not have it inferred. Explicit opt-in means one of:
19
+ - The user included the keyword "ultracode" in their prompt (you'll see a system-reminder confirming it).
20
+ - Ultracode is on for the session (a system-reminder confirms it) — see **Ultracode** in the workflow authoring reference.
21
+ - The user directly asked you to run a workflow or use multi-agent orchestration in their own words ("use a workflow", "run a workflow", "fan out agents", "orchestrate this with subagents"). The ask must be in the user's words — a task that would merely benefit from a workflow does not count.
22
+ - The user invoked a skill or slash command whose instructions tell you to call Workflow.
23
+ - The user asked you to run a specific named or saved workflow.
24
+
25
+ For any other task — even one that would clearly benefit from parallelism — do NOT call this tool. Use the Agent tool (if available) for individual subagents, or briefly describe what a multi-agent workflow could do and how much it would roughly cost, and ask the user whether to run it. Mention they can ask for one with "use a workflow" in a future message to skip the ask.
26
+
27
+ Every script must begin with \`export const meta = {...}\`: a PURE LITERAL (no variables, calls or interpolation) giving the workflow's \`name\`, a one-line \`description\` (shown in the permission dialog) and optionally \`phases\` — one \`{ title, detail? }\` per phase() call, titles matched exactly. Pass the script inline via \`script\` — do not write it to a file first, and do not also set the tool's \`name\` input (that selects a saved workflow); it is plain JavaScript, not TypeScript.
28
+
29
+ The canonical multi-stage pattern — pipeline by default, each dimension verifies as soon as its review completes:
30
+ export const meta = {
31
+ name: 'review-changes',
32
+ description: 'Review changed files across dimensions, verify each finding',
33
+ phases: [{ title: 'Review' }, { title: 'Verify' }],
34
+ }
35
+ const DIMENSIONS = [{key: 'bugs', prompt: '...'}, {key: 'perf', prompt: '...'}]
36
+ const results = await pipeline(
37
+ DIMENSIONS,
38
+ d => agent(d.prompt, {label: \`review:\${d.key}\`, phase: 'Review', schema: FINDINGS_SCHEMA}),
39
+ review => parallel(review.findings.map(f => () =>
40
+ agent(\`Adversarially verify: \${f.title}\`, {label: \`verify:\${f.file}\`, phase: 'Verify', schema: VERDICT_SCHEMA})
41
+ .then(v => ({...f, verdict: v}))
42
+ ))
43
+ )
44
+ const confirmed = results.flat().filter(Boolean).filter(f => f.verdict?.isReal)
45
+ return { confirmed }
46
+ // Dimension 'bugs' findings verify while dimension 'perf' is still reviewing. No wasted wall-clock.
47
+
48
+ Before writing a script, load the \`workflow-authoring\` skill — the workflow authoring reference: script API and gotchas, resume, the **Ultracode** section, quality patterns, worked examples.`;
49
+
50
+ /** The agent count each size keeps a workflow under. */
51
+ export const WORKFLOW_SIZE_AGENTS: Record<Exclude<WorkflowSizeGuideline, "unrestricted">, number> = {
52
+ small: 5,
53
+ medium: 10,
54
+ large: 50,
55
+ };
56
+
57
+ /** The size-guideline line; undefined when no guideline applies. */
58
+ export function workflowSizeLine(guideline: WorkflowSizeGuideline, configured: boolean): string | undefined {
59
+ if (guideline === "unrestricted") return undefined;
60
+ const opening = configured ? "A workflow size guideline is configured for this session" : "This session has the default workflow size guideline";
61
+ return `${opening}: ${guideline} — keep workflows under ${WORKFLOW_SIZE_AGENTS[guideline]} agents. This is a guideline, not a hard limit — follow it unless the user's prompt calls for a different scale. The user can raise or remove it with \`workflowSizeGuideline\` in ~/.onecode/settings.json.`;
62
+ }
63
+
64
+ export function workflowDescription(guideline: WorkflowSizeGuideline, configured: boolean): string {
65
+ const line = workflowSizeLine(guideline, configured);
66
+ return line ? `${WORKFLOW_DESCRIPTION_BODY}\n\n${line}` : WORKFLOW_DESCRIPTION_BODY;
67
+ }
@@ -25,7 +25,7 @@ import type {
25
25
  JournalEntry,
26
26
  RunProgressEvent,
27
27
  } from "./types.ts";
28
- import { WorkflowScriptError } from "./types.ts";
28
+ import { keptWorktreeOf, type KeptWorktree, WorkflowScriptError } from "./types.ts";
29
29
  import type { ReplayCursor } from "./journal.ts";
30
30
 
31
31
  export const MAX_AGENTS_PER_RUN = 1000;
@@ -186,6 +186,7 @@ export function createScriptGlobals(options: ScriptGlobalsOptions): { globals: S
186
186
  replayed: true,
187
187
  prompt,
188
188
  preview: previewValue(replayed.value),
189
+ ...keptWorktreeField(replayed.worktreePath, replayed.worktreeBranch),
189
190
  });
190
191
  return replayed.value;
191
192
  }
@@ -216,13 +217,14 @@ export function createScriptGlobals(options: ScriptGlobalsOptions): { globals: S
216
217
  tokens: result.tokens,
217
218
  cost: result.cost,
218
219
  preview: previewValue(result.value),
220
+ ...keptWorktreeField(result.worktreePath, result.worktreeBranch),
219
221
  });
220
222
  return result.value;
221
223
  } catch (error) {
222
224
  if (options.signal.aborted) {
223
225
  // Close the record: the viewer would otherwise show a completed or
224
226
  // stopped run with this agent still "running".
225
- options.onEvent({ type: "agentEnd", callIndex, label, phase, text: "aborted" });
227
+ options.onEvent({ type: "agentEnd", callIndex, label, phase, text: "aborted", ...keptWorktreeField(keptWorktreeOf(error)?.path, keptWorktreeOf(error)?.branch) });
226
228
  throw new WorkflowScriptError("Workflow run was aborted");
227
229
  }
228
230
  // A script-authoring mistake (bad agentType/model, worktree without a
@@ -233,7 +235,14 @@ export function createScriptGlobals(options: ScriptGlobalsOptions): { globals: S
233
235
  if (error instanceof WorkflowScriptError) throw error;
234
236
  // A failed agent resolves to null (Claude Code semantics); the
235
237
  // failure is surfaced as a progress event, not an exception.
236
- options.onEvent({ type: "agentEnd", callIndex, label, phase, text: `failed: ${(error as Error).message}` });
238
+ options.onEvent({
239
+ type: "agentEnd",
240
+ callIndex,
241
+ label,
242
+ phase,
243
+ text: `failed: ${(error as Error).message}`,
244
+ ...keptWorktreeField(keptWorktreeOf(error)?.path, keptWorktreeOf(error)?.branch),
245
+ });
237
246
  return null;
238
247
  }
239
248
  });
@@ -272,3 +281,8 @@ export function createScriptGlobals(options: ScriptGlobalsOptions): { globals: S
272
281
 
273
282
  return { globals, state };
274
283
  }
284
+
285
+ /** The `worktree` field of an agentEnd event, present only for a kept worktree. */
286
+ function keptWorktreeField(path: string | undefined, branch: string | undefined): { worktree?: KeptWorktree } {
287
+ return path ? { worktree: branch ? { path, branch } : { path } } : {};
288
+ }