detached 2c1ebcb

feat(agent): delegate by default in proactive mode

The proactive prompt makes the primary an orchestrator: substantial work goes to subagents, small edits stay local, blocking work is delegated with required:true, and routing repeats for each request. It adds parallelism planning, a feature-branch sub-worktree workflow, and worktree cleanup. The lifecycle addendum is shorter.
commit
2c1ebcbcc04e9c51ac76b1dafde0716dd9ad9f6d
author
brice · · 2026-10-18 17:58 UTC
parent
5b5f89f
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
7 files · +84 -56
M README.md +3 -3
@@ -271,7 +271,7 @@ Print-mode stats contain `provider`, `model`, `prompt_tokens`, `reasoning_tokens
271271 - `ast`: search or rewrite source code structurally with an [ast-grep](https://ast-grep.github.io/) pattern. Prefer it when the operation depends on code syntax; use `grep`/`edit` for plain text. `language` is optional; when omitted, ast-grep infers it from each file's extension. Zut starts an installed `ast-grep` executable, or `sg` when it identifies itself as ast-grep, directly without a shell. Searches return compact `path:line` matches. Rewrites are planned in memory, shown as a diff for confirmation, checked against the active filesystem scope, verified against the files' current contents, written through a temporary file and rename with file permissions preserved, and followed by bounded diagnostics. When `grep` is given a regex that looks like a call or definition search and `ast` is available, its result includes a short `ast` suggestion. Install ast-grep separately; the tool returns a clear error when it is not available.
272272 - `bash`: run a command in the session cwd with merged stdout/stderr. Every call must include a positive integer `timeout` in seconds; calls without it or with `timeout <= 0` are rejected, and the deadline is always enforced. On Unix, zut uses `/bin/bash -c` when available, then `bash -c` from `PATH`, and falls back to POSIX `/bin/sh -c` when Bash is unavailable. On Windows, it uses `cmd /C`. macOS ships Bash 3.2 by default, so newer Bash features may be unavailable.
273273 - `python`: execute inline Python 3 code with an existing interpreter, never installing one. Every call must include nonblank `code` and a positive integer `timeout` in seconds (shared by interpreter discovery and execution). Each call runs a fresh stateless subprocess directly (`-u -B -`, code on stdin) in the session cwd with merged stdout/stderr; there is no persistent interpreter state, no script file, and no bytecode cache. Interactive input is unsupported (stdin observes EOF). Output is bounded (50 KiB, 2,000 lines) with explicit truncation marks; truncated results persist the byte-capped buffer to a temp file referenced as `full output` with its path in `full_output_path`, mirroring `bash`. Discovery order: `python_interpreter` in `$ZUT_HOME/config.json` (one executable path; relative paths resolve against the session cwd), then the active `VIRTUAL_ENV`, then `./.venv`, then `python3`/`python` on `PATH`. On Windows, Store aliases, `py` launchers, and install-manager entrypoints are rejected; only positively identified installed interpreters run. Missing packages fail with the ordinary import traceback. Tool arguments and output are recorded in the session like other tools; files the code deliberately writes persist. Save reusable scripts with `write`/`edit` instead of using `python` as an opaque file-edit path. Unavailable to packaged agents, and rejected while jailed (see below).
274-- `worktree`: manage Git worktrees with the `create`, `list`, and `cleanup` actions. Creation checks out a new branch under `$ZUT_HOME/worktrees/<repo-id>`; an absolute local Git setting, `zut.worktrees.path`, overrides that root per repository. Listing inventories registered worktrees. Cleanup requires exact paths, confirmation through the normal preview gate, and revalidation immediately before removal. It refuses the primary worktree, dirty or detached checkouts, and commits not merged into the current branch. It removes neither local branches nor unmerged work.
274+- `worktree`: manage Git worktrees with the `create`, `list`, and `cleanup` actions. Creation checks out a new branch under `$ZUT_HOME/worktrees/<repo-id>`, starting from the current HEAD or from `base` (a branch, tag, or commit); an absolute local Git setting, `zut.worktrees.path`, overrides that root per repository. Listing inventories registered worktrees. Cleanup requires exact paths, confirmation through the normal preview gate, and revalidation immediately before removal. It refuses the primary worktree, dirty or detached checkouts, and commits not merged into the current branch, or into `into` when given. With `delete_branch`, it also deletes each removed worktree's local branch, only while the branch is still at the inspected commit; it never deletes the merge target or a branch checked out in another worktree, and it reports a branch-deletion failure while keeping the removed worktrees removed. It never removes unmerged work. For a feature-branch workflow, create `feat/x` from main, then create sub-worktrees with `base: "feat/x"` (for example `feat/x-api`). After committing on each sub-branch and merging it into `feat/x`, clean up with `into: "feat/x"` and `delete_branch: true`. `list` also accepts `into` to check eligibility against that branch.
275275 - `lsp`: query configured language servers and linters for diagnostics, definitions, references, hover information, symbols, renames, code actions, capabilities, and raw protocol requests. LSP servers use stdio JSON-RPC; project `lsp.json` files can add or override servers and CLI linters. Diagnostics are bounded, sorted, deduplicated by path/severity/code/start position, and repeated issues are grouped before they reach the model. Successful native edits, writes, renames, and applied code actions automatically attach bounded diagnostics when available. See [docs/lsp.md](docs/lsp.md).
276276 - `web_search`: search DuckDuckGo HTML and return bounded source titles, URLs, snippets, and opaque references. `web_open` opens either a complete public URL or a referenced page, while `web_find` and `web_click` respectively find literal text in an opened page and follow a displayed link. The four tools are enabled together by default for normal CLI sessions and unavailable to bot, default SDK, and packaged-agent runs. See [docs/web-search.md](docs/web-search.md).
277277 - `update_goal`: let the main agent start its own mission when none is active, set the next bounded goal within an active mission, pause work while a decision is pending, resume it once settled, mark the active goal `done` or `blocked`, or atomically supersede an invalid goal with a necessary in-mission replacement. Users can also pause and resume through `/goal`; clearing remains user-controlled.
@@ -457,7 +457,7 @@ Each child runs without a cumulative token budget or step cap: it inherits the p
457457
458458 Worktree isolation captures a patch and changed-file list without applying it. Shared children use the host checkout. The available logical references are `subagent://<id>`, `subagent://<id>/history`, `subagent://<id>/result`, and `subagent://<id>/patch`.
459459
460-**Proactive delegation.** With `/settings` → **proactive delegation** on (or `/orchestrator`), the interactive primary remains the owner and implementer of the task. Process start reveals neither the task nor which workers it needs, so it routes when the user states the request: the reply that starts the work names the parts it keeps on the critical path and the profile that owns each delegable part, before implementing or spawning anything. It delegates only concrete sidecars that can progress while the primary performs a preselected non-overlapping task; immediate blockers and tightly coupled work stay local. An active worker owns its scope until completion, so the primary does not repeat that investigation, review, testing, or implementation. If an explicit user request or workflow hands blocking work to a child, the primary yields for the host completion update instead. The canonical resident `subagent` tool remains available for user-requested delegation when the setting is off, subject to launch-time permissions. Do not poll the status action or journal files solely to wait for completion.
460+**Proactive delegation.** With `/settings` → **proactive delegation** on (or `/orchestrator`), the interactive primary acts as an orchestrator and delegates by default. Implementation, debugging, testing, review, and broad research go to workers; answers, quick lookups, edits of a few lines, and integration stay local. For each new request, the reply that starts the work names each part, its owner, and the profile for each delegated part. The primary maps dependencies, runs independent parts in parallel, and for multi-part features gives each worker a sub-worktree based on a feature branch, gates each result with a review before merging, and removes merged worktrees and branches when done. Blocking work is spawned with `required: true` and the primary yields for the host completion update. An active worker owns its scope until completion, so the primary does not repeat that investigation, review, testing, or implementation. The canonical resident `subagent` tool remains available for user-requested delegation when the setting is off, subject to launch-time permissions. Do not poll the status action or journal files solely to wait for completion.
461461
462462 ### Named subagent profiles
463463
@@ -471,7 +471,7 @@ Opens a dialog with every persistent setting. `up`/`down` to navigate, `enter` o
471471 - **render images when supported** — draw screenshots / `read`-returned images inline using the terminal's image protocol, or fall back to a text placeholder. Auto-detected from `TERM_PROGRAM`; the toggle overrides the detection. The row is greyed out and forced off on terminals that don't speak any image protocol.
472472 - **terminal alerts** — emit a terminal bell when the main session stops with work that may need attention, or when an extension raises a structured alert. Enabled by default; changes apply immediately and persist as `terminal_alerts_enabled`. Terminal emulators may render the bell audibly, visually, or not at all.
473473 - **AI terminal titles** — after the first real prompt of a fresh interactive session, make one small hidden request to the active model and set the terminal title to `zut: <title>`. The title is limited to 40 Unicode characters, persisted with the session, restored on resume, and never added to the conversation. Enabled by default; disable it to avoid the extra model request. The toggle applies immediately, but title generation still waits for the first real prompt and never starts from startup context, resumed history, or slash commands. Persists as `terminal_title_enabled`.
474-- **proactive delegation** — let the interactive primary delegate concrete, bounded sidecars while it keeps ownership of the critical path. Because the task and the workers it needs are unknown until the user states them, the primary routes at that point: the reply that starts the work names the parts it keeps on the critical path and the profile that owns each delegable part, and it states when nothing is worth delegating instead of forcing workers. Before spawning, it identifies useful local work and gives the child a non-overlapping question, responsibility, package, or file set. Immediate blockers and tightly coupled work stay local; after spawning, the worker owns its scope until completion and the primary continues only its preselected independent task. If a user request or active workflow explicitly delegates blocking work, the primary yields rather than reproducing it. Off by default. When off, the permitted canonical subagent tools and profile manifest remain available for user-requested delegation or when an active skill workflow requires it. The tools accept named profiles, reasoning, per-spawn fast-mode overrides, and shared/worktree isolation where applicable; lifecycle and result references are persisted. Completion and required-work state are host-driven through `[auto-subagents update]` and `[required-subagents update]` messages; required work stays asynchronous, persists its outcome, and prevents the terminal parent response until a successful completion. If launch-time restrictions prevent spawning, the interactive primary continues locally. Explicit headless `--orchestrate` remains a separate strict manager-only mode and reports unavailable delegation rather than implementing directly. Do not poll or inspect dashboards, metadata, event logs, or files solely to wait. See `/subagents` and [docs/subagents.md](docs/subagents.md) for details.
474+- **proactive delegation** — make the interactive primary an orchestrator that delegates substantial work by default and keeps small edits, lookups, and integration local. See **Proactive delegation** above. Off by default. When off, the permitted canonical subagent tools and profile manifest remain available for user-requested delegation or when an active skill workflow requires it. The tools accept named profiles, reasoning, per-spawn fast-mode overrides, and shared/worktree isolation where applicable; lifecycle and result references are persisted. Completion and required-work state are host-driven through `[auto-subagents update]` and `[required-subagents update]` messages; required work stays asynchronous, persists its outcome, and prevents the terminal parent response until a successful completion. If launch-time restrictions prevent spawning, the interactive primary continues locally. Explicit headless `--orchestrate` remains a separate strict manager-only mode and reports unavailable delegation rather than implementing directly. Do not poll or inspect dashboards, metadata, event logs, or files solely to wait. See `/subagents` and [docs/subagents.md](docs/subagents.md) for details.
475475 - **fast mode** — request the provider's fast tier where supported. It currently uses OpenAI's Fast service tier for OpenAI, OpenAI Responses, and OpenAI Codex models. Off by default; toggle it with `/fast` or `/settings`; changes apply on the next model call and persist as `fast_mode`. When a model profile is active, the value is saved in that profile and restored when switching profiles. Other providers currently return an unsupported-provider error. Fast mode may cost more and depends on the selected model/account.
476476 - **lsp in main session** — enable the built-in `lsp` tool and code diagnostics for the main agent. Enabled by default; changes persist as `lsp_enabled`.
477477 - **lsp in sub-agents** — allow newly spawned background sub-agents to use the built-in `lsp` tool. Enabled by default; changes persist as `subagent_lsp_enabled` and apply when a child starts.
@@ -271,7 +271,7 @@ Print-mode stats contain `provider`, `model`, `prompt_tokens`, `reasoning_tokens
271 - `ast`: search or rewrite source code structurally with an [ast-grep](https://ast-grep.github.io/) pattern. Prefer it when the operation depends on code syntax; use `grep`/`edit` for plain text. `language` is optional; when omitted, ast-grep infers it from each file's extension. Zut starts an installed `ast-grep` executable, or `sg` when it identifies itself as ast-grep, directly without a shell. Searches return compact `path:line` matches. Rewrites are planned in memory, shown as a diff for confirmation, checked against the active filesystem scope, verified against the files' current contents, written through a temporary file and rename with file permissions preserved, and followed by bounded diagnostics. When `grep` is given a regex that looks like a call or definition search and `ast` is available, its result includes a short `ast` suggestion. Install ast-grep separately; the tool returns a clear error when it is not available.271 - `ast`: search or rewrite source code structurally with an [ast-grep](https://ast-grep.github.io/) pattern. Prefer it when the operation depends on code syntax; use `grep`/`edit` for plain text. `language` is optional; when omitted, ast-grep infers it from each file's extension. Zut starts an installed `ast-grep` executable, or `sg` when it identifies itself as ast-grep, directly without a shell. Searches return compact `path:line` matches. Rewrites are planned in memory, shown as a diff for confirmation, checked against the active filesystem scope, verified against the files' current contents, written through a temporary file and rename with file permissions preserved, and followed by bounded diagnostics. When `grep` is given a regex that looks like a call or definition search and `ast` is available, its result includes a short `ast` suggestion. Install ast-grep separately; the tool returns a clear error when it is not available.
272 - `bash`: run a command in the session cwd with merged stdout/stderr. Every call must include a positive integer `timeout` in seconds; calls without it or with `timeout <= 0` are rejected, and the deadline is always enforced. On Unix, zut uses `/bin/bash -c` when available, then `bash -c` from `PATH`, and falls back to POSIX `/bin/sh -c` when Bash is unavailable. On Windows, it uses `cmd /C`. macOS ships Bash 3.2 by default, so newer Bash features may be unavailable.272 - `bash`: run a command in the session cwd with merged stdout/stderr. Every call must include a positive integer `timeout` in seconds; calls without it or with `timeout <= 0` are rejected, and the deadline is always enforced. On Unix, zut uses `/bin/bash -c` when available, then `bash -c` from `PATH`, and falls back to POSIX `/bin/sh -c` when Bash is unavailable. On Windows, it uses `cmd /C`. macOS ships Bash 3.2 by default, so newer Bash features may be unavailable.
273 - `python`: execute inline Python 3 code with an existing interpreter, never installing one. Every call must include nonblank `code` and a positive integer `timeout` in seconds (shared by interpreter discovery and execution). Each call runs a fresh stateless subprocess directly (`-u -B -`, code on stdin) in the session cwd with merged stdout/stderr; there is no persistent interpreter state, no script file, and no bytecode cache. Interactive input is unsupported (stdin observes EOF). Output is bounded (50 KiB, 2,000 lines) with explicit truncation marks; truncated results persist the byte-capped buffer to a temp file referenced as `full output` with its path in `full_output_path`, mirroring `bash`. Discovery order: `python_interpreter` in `$ZUT_HOME/config.json` (one executable path; relative paths resolve against the session cwd), then the active `VIRTUAL_ENV`, then `./.venv`, then `python3`/`python` on `PATH`. On Windows, Store aliases, `py` launchers, and install-manager entrypoints are rejected; only positively identified installed interpreters run. Missing packages fail with the ordinary import traceback. Tool arguments and output are recorded in the session like other tools; files the code deliberately writes persist. Save reusable scripts with `write`/`edit` instead of using `python` as an opaque file-edit path. Unavailable to packaged agents, and rejected while jailed (see below).273 - `python`: execute inline Python 3 code with an existing interpreter, never installing one. Every call must include nonblank `code` and a positive integer `timeout` in seconds (shared by interpreter discovery and execution). Each call runs a fresh stateless subprocess directly (`-u -B -`, code on stdin) in the session cwd with merged stdout/stderr; there is no persistent interpreter state, no script file, and no bytecode cache. Interactive input is unsupported (stdin observes EOF). Output is bounded (50 KiB, 2,000 lines) with explicit truncation marks; truncated results persist the byte-capped buffer to a temp file referenced as `full output` with its path in `full_output_path`, mirroring `bash`. Discovery order: `python_interpreter` in `$ZUT_HOME/config.json` (one executable path; relative paths resolve against the session cwd), then the active `VIRTUAL_ENV`, then `./.venv`, then `python3`/`python` on `PATH`. On Windows, Store aliases, `py` launchers, and install-manager entrypoints are rejected; only positively identified installed interpreters run. Missing packages fail with the ordinary import traceback. Tool arguments and output are recorded in the session like other tools; files the code deliberately writes persist. Save reusable scripts with `write`/`edit` instead of using `python` as an opaque file-edit path. Unavailable to packaged agents, and rejected while jailed (see below).
274-- `worktree`: manage Git worktrees with the `create`, `list`, and `cleanup` actions. Creation checks out a new branch under `$ZUT_HOME/worktrees/<repo-id>`; an absolute local Git setting, `zut.worktrees.path`, overrides that root per repository. Listing inventories registered worktrees. Cleanup requires exact paths, confirmation through the normal preview gate, and revalidation immediately before removal. It refuses the primary worktree, dirty or detached checkouts, and commits not merged into the current branch. It removes neither local branches nor unmerged work.274+- `worktree`: manage Git worktrees with the `create`, `list`, and `cleanup` actions. Creation checks out a new branch under `$ZUT_HOME/worktrees/<repo-id>`, starting from the current HEAD or from `base` (a branch, tag, or commit); an absolute local Git setting, `zut.worktrees.path`, overrides that root per repository. Listing inventories registered worktrees. Cleanup requires exact paths, confirmation through the normal preview gate, and revalidation immediately before removal. It refuses the primary worktree, dirty or detached checkouts, and commits not merged into the current branch, or into `into` when given. With `delete_branch`, it also deletes each removed worktree's local branch, only while the branch is still at the inspected commit; it never deletes the merge target or a branch checked out in another worktree, and it reports a branch-deletion failure while keeping the removed worktrees removed. It never removes unmerged work. For a feature-branch workflow, create `feat/x` from main, then create sub-worktrees with `base: "feat/x"` (for example `feat/x-api`). After committing on each sub-branch and merging it into `feat/x`, clean up with `into: "feat/x"` and `delete_branch: true`. `list` also accepts `into` to check eligibility against that branch.
275 - `lsp`: query configured language servers and linters for diagnostics, definitions, references, hover information, symbols, renames, code actions, capabilities, and raw protocol requests. LSP servers use stdio JSON-RPC; project `lsp.json` files can add or override servers and CLI linters. Diagnostics are bounded, sorted, deduplicated by path/severity/code/start position, and repeated issues are grouped before they reach the model. Successful native edits, writes, renames, and applied code actions automatically attach bounded diagnostics when available. See [docs/lsp.md](docs/lsp.md).275 - `lsp`: query configured language servers and linters for diagnostics, definitions, references, hover information, symbols, renames, code actions, capabilities, and raw protocol requests. LSP servers use stdio JSON-RPC; project `lsp.json` files can add or override servers and CLI linters. Diagnostics are bounded, sorted, deduplicated by path/severity/code/start position, and repeated issues are grouped before they reach the model. Successful native edits, writes, renames, and applied code actions automatically attach bounded diagnostics when available. See [docs/lsp.md](docs/lsp.md).
276 - `web_search`: search DuckDuckGo HTML and return bounded source titles, URLs, snippets, and opaque references. `web_open` opens either a complete public URL or a referenced page, while `web_find` and `web_click` respectively find literal text in an opened page and follow a displayed link. The four tools are enabled together by default for normal CLI sessions and unavailable to bot, default SDK, and packaged-agent runs. See [docs/web-search.md](docs/web-search.md).276 - `web_search`: search DuckDuckGo HTML and return bounded source titles, URLs, snippets, and opaque references. `web_open` opens either a complete public URL or a referenced page, while `web_find` and `web_click` respectively find literal text in an opened page and follow a displayed link. The four tools are enabled together by default for normal CLI sessions and unavailable to bot, default SDK, and packaged-agent runs. See [docs/web-search.md](docs/web-search.md).
277 - `update_goal`: let the main agent start its own mission when none is active, set the next bounded goal within an active mission, pause work while a decision is pending, resume it once settled, mark the active goal `done` or `blocked`, or atomically supersede an invalid goal with a necessary in-mission replacement. Users can also pause and resume through `/goal`; clearing remains user-controlled.277 - `update_goal`: let the main agent start its own mission when none is active, set the next bounded goal within an active mission, pause work while a decision is pending, resume it once settled, mark the active goal `done` or `blocked`, or atomically supersede an invalid goal with a necessary in-mission replacement. Users can also pause and resume through `/goal`; clearing remains user-controlled.
@@ -457,7 +457,7 @@ Each child runs without a cumulative token budget or step cap: it inherits the p
457 457
458 Worktree isolation captures a patch and changed-file list without applying it. Shared children use the host checkout. The available logical references are `subagent://<id>`, `subagent://<id>/history`, `subagent://<id>/result`, and `subagent://<id>/patch`.458 Worktree isolation captures a patch and changed-file list without applying it. Shared children use the host checkout. The available logical references are `subagent://<id>`, `subagent://<id>/history`, `subagent://<id>/result`, and `subagent://<id>/patch`.
459 459
460-**Proactive delegation.** With `/settings` → **proactive delegation** on (or `/orchestrator`), the interactive primary remains the owner and implementer of the task. Process start reveals neither the task nor which workers it needs, so it routes when the user states the request: the reply that starts the work names the parts it keeps on the critical path and the profile that owns each delegable part, before implementing or spawning anything. It delegates only concrete sidecars that can progress while the primary performs a preselected non-overlapping task; immediate blockers and tightly coupled work stay local. An active worker owns its scope until completion, so the primary does not repeat that investigation, review, testing, or implementation. If an explicit user request or workflow hands blocking work to a child, the primary yields for the host completion update instead. The canonical resident `subagent` tool remains available for user-requested delegation when the setting is off, subject to launch-time permissions. Do not poll the status action or journal files solely to wait for completion.460+**Proactive delegation.** With `/settings` → **proactive delegation** on (or `/orchestrator`), the interactive primary acts as an orchestrator and delegates by default. Implementation, debugging, testing, review, and broad research go to workers; answers, quick lookups, edits of a few lines, and integration stay local. For each new request, the reply that starts the work names each part, its owner, and the profile for each delegated part. The primary maps dependencies, runs independent parts in parallel, and for multi-part features gives each worker a sub-worktree based on a feature branch, gates each result with a review before merging, and removes merged worktrees and branches when done. Blocking work is spawned with `required: true` and the primary yields for the host completion update. An active worker owns its scope until completion, so the primary does not repeat that investigation, review, testing, or implementation. The canonical resident `subagent` tool remains available for user-requested delegation when the setting is off, subject to launch-time permissions. Do not poll the status action or journal files solely to wait for completion.
461 461
462 ### Named subagent profiles462 ### Named subagent profiles
463 463
@@ -471,7 +471,7 @@ Opens a dialog with every persistent setting. `up`/`down` to navigate, `enter` o
471 - **render images when supported** — draw screenshots / `read`-returned images inline using the terminal's image protocol, or fall back to a text placeholder. Auto-detected from `TERM_PROGRAM`; the toggle overrides the detection. The row is greyed out and forced off on terminals that don't speak any image protocol.471 - **render images when supported** — draw screenshots / `read`-returned images inline using the terminal's image protocol, or fall back to a text placeholder. Auto-detected from `TERM_PROGRAM`; the toggle overrides the detection. The row is greyed out and forced off on terminals that don't speak any image protocol.
472 - **terminal alerts** — emit a terminal bell when the main session stops with work that may need attention, or when an extension raises a structured alert. Enabled by default; changes apply immediately and persist as `terminal_alerts_enabled`. Terminal emulators may render the bell audibly, visually, or not at all.472 - **terminal alerts** — emit a terminal bell when the main session stops with work that may need attention, or when an extension raises a structured alert. Enabled by default; changes apply immediately and persist as `terminal_alerts_enabled`. Terminal emulators may render the bell audibly, visually, or not at all.
473 - **AI terminal titles** — after the first real prompt of a fresh interactive session, make one small hidden request to the active model and set the terminal title to `zut: <title>`. The title is limited to 40 Unicode characters, persisted with the session, restored on resume, and never added to the conversation. Enabled by default; disable it to avoid the extra model request. The toggle applies immediately, but title generation still waits for the first real prompt and never starts from startup context, resumed history, or slash commands. Persists as `terminal_title_enabled`.473 - **AI terminal titles** — after the first real prompt of a fresh interactive session, make one small hidden request to the active model and set the terminal title to `zut: <title>`. The title is limited to 40 Unicode characters, persisted with the session, restored on resume, and never added to the conversation. Enabled by default; disable it to avoid the extra model request. The toggle applies immediately, but title generation still waits for the first real prompt and never starts from startup context, resumed history, or slash commands. Persists as `terminal_title_enabled`.
474-- **proactive delegation** — let the interactive primary delegate concrete, bounded sidecars while it keeps ownership of the critical path. Because the task and the workers it needs are unknown until the user states them, the primary routes at that point: the reply that starts the work names the parts it keeps on the critical path and the profile that owns each delegable part, and it states when nothing is worth delegating instead of forcing workers. Before spawning, it identifies useful local work and gives the child a non-overlapping question, responsibility, package, or file set. Immediate blockers and tightly coupled work stay local; after spawning, the worker owns its scope until completion and the primary continues only its preselected independent task. If a user request or active workflow explicitly delegates blocking work, the primary yields rather than reproducing it. Off by default. When off, the permitted canonical subagent tools and profile manifest remain available for user-requested delegation or when an active skill workflow requires it. The tools accept named profiles, reasoning, per-spawn fast-mode overrides, and shared/worktree isolation where applicable; lifecycle and result references are persisted. Completion and required-work state are host-driven through `[auto-subagents update]` and `[required-subagents update]` messages; required work stays asynchronous, persists its outcome, and prevents the terminal parent response until a successful completion. If launch-time restrictions prevent spawning, the interactive primary continues locally. Explicit headless `--orchestrate` remains a separate strict manager-only mode and reports unavailable delegation rather than implementing directly. Do not poll or inspect dashboards, metadata, event logs, or files solely to wait. See `/subagents` and [docs/subagents.md](docs/subagents.md) for details.474+- **proactive delegation** — make the interactive primary an orchestrator that delegates substantial work by default and keeps small edits, lookups, and integration local. See **Proactive delegation** above. Off by default. When off, the permitted canonical subagent tools and profile manifest remain available for user-requested delegation or when an active skill workflow requires it. The tools accept named profiles, reasoning, per-spawn fast-mode overrides, and shared/worktree isolation where applicable; lifecycle and result references are persisted. Completion and required-work state are host-driven through `[auto-subagents update]` and `[required-subagents update]` messages; required work stays asynchronous, persists its outcome, and prevents the terminal parent response until a successful completion. If launch-time restrictions prevent spawning, the interactive primary continues locally. Explicit headless `--orchestrate` remains a separate strict manager-only mode and reports unavailable delegation rather than implementing directly. Do not poll or inspect dashboards, metadata, event logs, or files solely to wait. See `/subagents` and [docs/subagents.md](docs/subagents.md) for details.
475 - **fast mode** — request the provider's fast tier where supported. It currently uses OpenAI's Fast service tier for OpenAI, OpenAI Responses, and OpenAI Codex models. Off by default; toggle it with `/fast` or `/settings`; changes apply on the next model call and persist as `fast_mode`. When a model profile is active, the value is saved in that profile and restored when switching profiles. Other providers currently return an unsupported-provider error. Fast mode may cost more and depends on the selected model/account.475 - **fast mode** — request the provider's fast tier where supported. It currently uses OpenAI's Fast service tier for OpenAI, OpenAI Responses, and OpenAI Codex models. Off by default; toggle it with `/fast` or `/settings`; changes apply on the next model call and persist as `fast_mode`. When a model profile is active, the value is saved in that profile and restored when switching profiles. Other providers currently return an unsupported-provider error. Fast mode may cost more and depends on the selected model/account.
476 - **lsp in main session** — enable the built-in `lsp` tool and code diagnostics for the main agent. Enabled by default; changes persist as `lsp_enabled`.476 - **lsp in main session** — enable the built-in `lsp` tool and code diagnostics for the main agent. Enabled by default; changes persist as `lsp_enabled`.
477 - **lsp in sub-agents** — allow newly spawned background sub-agents to use the built-in `lsp` tool. Enabled by default; changes persist as `subagent_lsp_enabled` and apply when a child starts.477 - **lsp in sub-agents** — allow newly spawned background sub-agents to use the built-in `lsp` tool. Enabled by default; changes persist as `subagent_lsp_enabled` and apply when a child starts.
M docs/subagents.md +25 -17
@@ -189,23 +189,31 @@ retries it automatically.
189189
190190 ## Delegation ownership
191191
192-Interactive proactive delegation keeps the primary agent on the critical path.
193-Process start says nothing about the task, and the workers it needs only become
194-knowable once the user states the request. Routing therefore happens then: the
195-reply that starts the work names the parts the primary keeps on the critical
196-path and the profile that owns each delegable part, before it implements or
197-spawns anything. It states plainly when nothing is worth delegating rather than
198-forcing a worker. The routing guidance is part of the prompt only when
199-launch-time policy exposes the spawn action.
200-Before spawning, it selects useful local work and delegates only a concrete,
201-bounded sidecar with a non-overlapping question, responsibility, package, or
202-file set. Immediate blockers and tightly coupled work stay local. While a child
203-is active, it owns that scope; the primary continues only its preselected
204-independent work instead of repeating the investigation, review, testing, or
205-implementation. If an explicit user request or active workflow hands blocking
206-work to a child, the primary yields for the completion update. Once a worktree
207-child succeeds, the primary may apply and verify its captured patch without
208-redoing the delegated task.
192+Interactive proactive delegation makes the primary agent an orchestrator that
193+delegates by default. Implementation, debugging, testing, review, and broad
194+research go to workers; answers, quick lookups, edits of a few lines, and
195+integration of worker results stay local. Blocking work is delegated too: the
196+primary spawns it with `required: true` and yields for the completion update.
197+
198+Routing happens for each new request, not at process start: the reply that
199+starts the work names each part, its owner, and the profile for each delegated
200+part. The routing guidance is part of the prompt only when launch-time policy
201+exposes the spawn action.
202+
203+Before spawning, the primary maps dependencies, runs independent parts in
204+parallel, and gives every worker a self-contained task with a disjoint scope.
205+For a multi-part feature it creates a feature worktree branch, then one
206+sub-worktree per worker with `worktree` `create` and `base` set to the feature
207+branch. It reviews each result, commits on the sub-branch, and merges it into
208+the feature branch. It then removes merged sub-worktrees and their branches
209+with `worktree` `cleanup`, `into` set to the feature branch and
210+`delete_branch: true`, and checks with `list` that none are left behind.
211+
212+While a child is active, it owns that scope; the primary does not repeat its
213+investigation, review, testing, or implementation. Once an
214+`isolation: "worktree"` child succeeds, the primary may apply and verify its
215+captured patch without redoing the task, then stop the idle child so its
216+temporary worktree is removed.
209217
210218 Explicit headless `--orchestrate` remains manager-only. Its primary divides the
211219 request into disjoint worker scopes, coordinates active children, and yields
@@ -189,23 +189,31 @@ retries it automatically.
189 189
190 ## Delegation ownership190 ## Delegation ownership
191 191
192-Interactive proactive delegation keeps the primary agent on the critical path.192+Interactive proactive delegation makes the primary agent an orchestrator that
193-Process start says nothing about the task, and the workers it needs only become193+delegates by default. Implementation, debugging, testing, review, and broad
194-knowable once the user states the request. Routing therefore happens then: the194+research go to workers; answers, quick lookups, edits of a few lines, and
195-reply that starts the work names the parts the primary keeps on the critical195+integration of worker results stay local. Blocking work is delegated too: the
196-path and the profile that owns each delegable part, before it implements or196+primary spawns it with `required: true` and yields for the completion update.
197-spawns anything. It states plainly when nothing is worth delegating rather than197+
198-forcing a worker. The routing guidance is part of the prompt only when198+Routing happens for each new request, not at process start: the reply that
199-launch-time policy exposes the spawn action.199+starts the work names each part, its owner, and the profile for each delegated
200-Before spawning, it selects useful local work and delegates only a concrete,200+part. The routing guidance is part of the prompt only when launch-time policy
201-bounded sidecar with a non-overlapping question, responsibility, package, or201+exposes the spawn action.
202-file set. Immediate blockers and tightly coupled work stay local. While a child202+
203-is active, it owns that scope; the primary continues only its preselected203+Before spawning, the primary maps dependencies, runs independent parts in
204-independent work instead of repeating the investigation, review, testing, or204+parallel, and gives every worker a self-contained task with a disjoint scope.
205-implementation. If an explicit user request or active workflow hands blocking205+For a multi-part feature it creates a feature worktree branch, then one
206-work to a child, the primary yields for the completion update. Once a worktree206+sub-worktree per worker with `worktree` `create` and `base` set to the feature
207-child succeeds, the primary may apply and verify its captured patch without207+branch. It reviews each result, commits on the sub-branch, and merges it into
208-redoing the delegated task.208+the feature branch. It then removes merged sub-worktrees and their branches
209+with `worktree` `cleanup`, `into` set to the feature branch and
210+`delete_branch: true`, and checks with `list` that none are left behind.
211+
212+While a child is active, it owns that scope; the primary does not repeat its
213+investigation, review, testing, or implementation. Once an
214+`isolation: "worktree"` child succeeds, the primary may apply and verify its
215+captured patch without redoing the task, then stop the idle child so its
216+temporary worktree is removed.
209 217
210 Explicit headless `--orchestrate` remains manager-only. Its primary divides the218 Explicit headless `--orchestrate` remains manager-only. Its primary divides the
211 request into disjoint worker scopes, coordinates active children, and yields219 request into disjoint worker scopes, coordinates active children, and yields
M packages/agent/modes/interactive_settings.go +1 -1
@@ -284,7 +284,7 @@ func (i *Interactive) openSettingsDialog() {
284284 {
285285 key: "auto_subagents_enabled",
286286 label: "proactive delegation",
287- desc: "delegate independent sidecar work while keeping the critical path local",
287+ desc: "delegate substantial work to subagents; keep small edits local",
288288 value: autoSubagents,
289289 disabled: autoSubagentsDisabled,
290290 hint: autoSubagentsHint,
@@ -284,7 +284,7 @@ func (i *Interactive) openSettingsDialog() {
284 {284 {
285 key: "auto_subagents_enabled",285 key: "auto_subagents_enabled",
286 label: "proactive delegation",286 label: "proactive delegation",
287- desc: "delegate independent sidecar work while keeping the critical path local",287+ desc: "delegate substantial work to subagents; keep small edits local",
288 value: autoSubagents,288 value: autoSubagents,
289 disabled: autoSubagentsDisabled,289 disabled: autoSubagentsDisabled,
290 hint: autoSubagentsHint,290 hint: autoSubagentsHint,
M packages/agent/settings_store.go +38 -25
@@ -276,28 +276,41 @@ func AutoSubagentsEnabled() bool {
276276 // ProactiveSubagentsRoutingAddendum is prepended to the interactive
277277 // collaboration contract only when launch-time policy exposes the spawn
278278 // action: naming a profile is meaningless when the primary cannot dispatch.
279-const ProactiveSubagentsRoutingAddendum = `Route before you work:
280-- Process start tells you nothing about the task or the workers it needs; routing happens when the user states the request you are about to work on.
281-- Name the parts you keep on the critical path and the [subagents_list] profile that owns each delegable part, before you implement or spawn.
282-- State that routing once, in the reply that starts the work, and let the tool calls that follow speak for themselves instead of narrating them.
283-- Say plainly when nothing is worth delegating instead of inventing sidecars, and spawn a clearly described general worker when no profile matches a scope.`
284-
285-// ProactiveSubagentsSystemAddendum keeps the interactive primary agent on the
286-// critical path and reserves delegation for genuinely parallel sidecar work.
287-const ProactiveSubagentsSystemAddendum = `Proactive subagent delegation is enabled. You remain the primary owner and implementer of the user's task.
288-
289-Before delegating:
290-- Form a short high-level plan and identify the immediate next task you will perform locally.
291-- Delegate only a concrete, bounded sidecar that can progress independently while you perform useful local work.
292-- Keep urgent, tightly coupled, or immediate blocking work local. If your next action depends on a result, do that work yourself instead of spawning and waiting for it.
293-- Divide ownership by distinct question, responsibility, package, or disjoint file set. Give every worker a self-contained task.
294-- If you cannot name useful non-overlapping local work, do not delegate.
295-
296-After delegating:
297-- The worker owns its delegated scope until it completes. Continue only with the non-overlapping local task selected before delegation.
298-- Do not search, read, test, review, edit, or otherwise reproduce the worker's task. You may dispatch additional workers only for genuinely distinct scopes.
299-- If the user or an active workflow explicitly requires a worker to own blocking work, delegate it with required:true and end or yield your turn instead of duplicating it.
300-- Integrate and, when appropriate, verify completed worker results before answering. You may apply a completed worktree patch without redoing the delegated task.`
279+const ProactiveSubagentsRoutingAddendum = `Route every new task before you work:
280+- Routing happens when the user states a request, not at process start. Re-route each new request, even late in a long session.
281+- In the reply that starts the work, name each part, who owns it, and the [subagents_list] profile for each delegated part. Then spawn; do not narrate the tool calls that follow.
282+- Spawn a clearly described general worker when no profile matches a scope.
283+- Keep a task fully local only when it is small: an answer, a quick lookup, or an edit of a few lines. Say so in one line instead of forcing a worker.`
284+
285+// ProactiveSubagentsSystemAddendum makes the interactive primary agent an
286+// orchestrator by default: substantial work goes to workers, while small
287+// edits, exploration, and integration stay local.
288+const ProactiveSubagentsSystemAddendum = `Proactive subagent delegation is enabled. You are the orchestrator of the user's task: delegate by default and keep work local by exception.
289+
290+Delegate:
291+- Implementation, debugging, test writing and running, and code review that spans more than a few lines or more than one file.
292+- Research that needs many reads or searches across packages or repositories.
293+- Blocking work too. If your next step depends on a worker's result, spawn it with required:true and end or yield your turn; waiting for a worker is expected, not a reason to work locally.
294+
295+Keep local:
296+- Answers, quick lookups, and the short exploration needed to write precise worker tasks.
297+- Edits of a few lines in one file, and integrating, applying, or verifying worker results.
298+
299+Plan parallelism before spawning:
300+- Map dependencies first: which parts are independent, which must run in order, and which files each part touches. Run independent parts in parallel and order dependent parts.
301+- Split work by distinct question, responsibility, package, or disjoint file set, and give every worker a self-contained task with acceptance checks.
302+- One worker editing code: shared workspace is fine. Several workers editing code at once: give each its own tree.
303+- For a multi-part feature, create a feature worktree branch, then one sub-worktree per worker with the worktree tool's create action and base set to the feature branch, and tell each worker its exact path. Review each worker's result as a gate, commit on its branch, and merge it into the feature branch.
304+- Use isolation:"worktree" for a throwaway parallel attempt whose patch you apply yourself.
305+
306+Clean up as soon as a worker's result is integrated:
307+- Remove merged sub-worktrees and their branches with the worktree tool's cleanup action, setting into to the feature branch and delete_branch to true.
308+- Stop idle isolation:"worktree" workers once their patch is applied so their temporary worktree is removed.
309+- Before your final answer, check with the worktree tool's list action that no worktree you created is left behind unless the user should keep it.
310+
311+When you delegate:
312+- A worker owns its scope until it completes. Do not search, read, test, review, edit, or otherwise reproduce it; only coordinate, dispatch disjoint work, or yield.
313+- Integrate and verify completed results before answering. You may apply a completed worktree patch without redoing the delegated task.`
301314
302315 // StrictOrchestratorSystemAddendum is used only by explicit headless
303316 // orchestration. The parent coordinates workers and never becomes an
@@ -312,11 +325,11 @@ const StrictOrchestratorSystemAddendum = `Strict subagent orchestration is enabl
312325
313326 const subagentLifecycleAddendum = `Workers start without this conversation's context. Shared-worktree workers edit the same working directory, so coordinate dependent work and avoid conflicting edits. Use isolation:"worktree" for parallel coding when workers need separate trees; its changes are returned as a patch and never applied automatically. Do not invent feature scope beyond the user's request. Child workers cannot recursively spawn more sub-agents in v1.
314327
315-Use required:true whenever your answer or a declared workflow depends on that worker, especially for required validation or finalization. Required workers remain asynchronous unless you explicitly set the wait field on a spawn or resume action: without it, manager calls return immediately, the parent stays free to coordinate or perform policy-permitted non-overlapping work, and the host delivers terminal outcomes through completion updates. Failed, canceled, or interrupted required work remains unmet: use an enabled manager follow-up action to retry it and do not claim completion. An indeterminate outcome after host restart must not be retried automatically; the user must inspect durable results and side effects, then explicitly resume or restart the worker with a new prompt. Required work has no automatic waiver path. Keep required:false only for independent work that may safely finish later.
328+Use required:true when your answer or a declared workflow depends on a worker. Failed, canceled, or interrupted required work stays unmet until a successful follow-up; never claim completion before it succeeds. After a host restart, do not retry an indeterminate outcome automatically: the user must reconcile it first. Required work has no automatic waiver path.
316329
317-Completion is host-event-driven unless you explicitly set the wait field on a spawn or resume action to a whole number of seconds (1–300): on spawn it bounds the initial task, and on resume it bounds the follow-up turn. Omitting wait always returns immediately. An expired wait leaves the accepted child active, whether queued or running; do not retry it until terminal failure, cancellation, or interruption. Never use "bash sleep", "watch", "tail -f", polling loops, repeated "status" calls, or dashboard, metadata, or file checks solely to wait. Those are not completion signals. Continue only with genuinely non-overlapping work; otherwise end or yield your turn until the host injects a completion update.
330+Completion is host-event-driven: omit the wait field, then continue only non-overlapping work or end or yield your turn; the host injects a completion update. Set wait (1–300 seconds) only to block this turn on a spawn or resume; an expired wait leaves the child active, so do not retry it. Never use "bash sleep", "watch", "tail -f", polling loops, repeated "status" calls, or file checks solely to wait.
318331
319-When workers finish, use the host update's agent ID, status, task, optional error, and final response or tail to coordinate any follow-up and summarize the outcome. Treat [auto-subagents update] and [required-subagents update] messages as observed worker state, not as new user requests.`
332+Treat [auto-subagents update] and [required-subagents update] messages as observed worker state, not as new user requests; use their agent ID, status, error, and result to coordinate follow-ups.`
320333
321334 // OnDemandSubagentsSystemAddendum keeps the canonical subagent tools
322335 // available without enabling proactive delegation.
@@ -276,28 +276,41 @@ func AutoSubagentsEnabled() bool {
276 // ProactiveSubagentsRoutingAddendum is prepended to the interactive276 // ProactiveSubagentsRoutingAddendum is prepended to the interactive
277 // collaboration contract only when launch-time policy exposes the spawn277 // collaboration contract only when launch-time policy exposes the spawn
278 // action: naming a profile is meaningless when the primary cannot dispatch.278 // action: naming a profile is meaningless when the primary cannot dispatch.
279-const ProactiveSubagentsRoutingAddendum = `Route before you work:279+const ProactiveSubagentsRoutingAddendum = `Route every new task before you work:
280-- Process start tells you nothing about the task or the workers it needs; routing happens when the user states the request you are about to work on.280+- Routing happens when the user states a request, not at process start. Re-route each new request, even late in a long session.
281-- Name the parts you keep on the critical path and the [subagents_list] profile that owns each delegable part, before you implement or spawn.281+- In the reply that starts the work, name each part, who owns it, and the [subagents_list] profile for each delegated part. Then spawn; do not narrate the tool calls that follow.
282-- State that routing once, in the reply that starts the work, and let the tool calls that follow speak for themselves instead of narrating them.282+- Spawn a clearly described general worker when no profile matches a scope.
283-- Say plainly when nothing is worth delegating instead of inventing sidecars, and spawn a clearly described general worker when no profile matches a scope.`283+- Keep a task fully local only when it is small: an answer, a quick lookup, or an edit of a few lines. Say so in one line instead of forcing a worker.`
284-284+
285-// ProactiveSubagentsSystemAddendum keeps the interactive primary agent on the285+// ProactiveSubagentsSystemAddendum makes the interactive primary agent an
286-// critical path and reserves delegation for genuinely parallel sidecar work.286+// orchestrator by default: substantial work goes to workers, while small
287-const ProactiveSubagentsSystemAddendum = `Proactive subagent delegation is enabled. You remain the primary owner and implementer of the user's task.287+// edits, exploration, and integration stay local.
288-288+const ProactiveSubagentsSystemAddendum = `Proactive subagent delegation is enabled. You are the orchestrator of the user's task: delegate by default and keep work local by exception.
289-Before delegating:289+
290-- Form a short high-level plan and identify the immediate next task you will perform locally.290+Delegate:
291-- Delegate only a concrete, bounded sidecar that can progress independently while you perform useful local work.291+- Implementation, debugging, test writing and running, and code review that spans more than a few lines or more than one file.
292-- Keep urgent, tightly coupled, or immediate blocking work local. If your next action depends on a result, do that work yourself instead of spawning and waiting for it.292+- Research that needs many reads or searches across packages or repositories.
293-- Divide ownership by distinct question, responsibility, package, or disjoint file set. Give every worker a self-contained task.293+- Blocking work too. If your next step depends on a worker's result, spawn it with required:true and end or yield your turn; waiting for a worker is expected, not a reason to work locally.
294-- If you cannot name useful non-overlapping local work, do not delegate.294+
295-295+Keep local:
296-After delegating:296+- Answers, quick lookups, and the short exploration needed to write precise worker tasks.
297-- The worker owns its delegated scope until it completes. Continue only with the non-overlapping local task selected before delegation.297+- Edits of a few lines in one file, and integrating, applying, or verifying worker results.
298-- Do not search, read, test, review, edit, or otherwise reproduce the worker's task. You may dispatch additional workers only for genuinely distinct scopes.298+
299-- If the user or an active workflow explicitly requires a worker to own blocking work, delegate it with required:true and end or yield your turn instead of duplicating it.299+Plan parallelism before spawning:
300-- Integrate and, when appropriate, verify completed worker results before answering. You may apply a completed worktree patch without redoing the delegated task.`300+- Map dependencies first: which parts are independent, which must run in order, and which files each part touches. Run independent parts in parallel and order dependent parts.
301+- Split work by distinct question, responsibility, package, or disjoint file set, and give every worker a self-contained task with acceptance checks.
302+- One worker editing code: shared workspace is fine. Several workers editing code at once: give each its own tree.
303+- For a multi-part feature, create a feature worktree branch, then one sub-worktree per worker with the worktree tool's create action and base set to the feature branch, and tell each worker its exact path. Review each worker's result as a gate, commit on its branch, and merge it into the feature branch.
304+- Use isolation:"worktree" for a throwaway parallel attempt whose patch you apply yourself.
305+
306+Clean up as soon as a worker's result is integrated:
307+- Remove merged sub-worktrees and their branches with the worktree tool's cleanup action, setting into to the feature branch and delete_branch to true.
308+- Stop idle isolation:"worktree" workers once their patch is applied so their temporary worktree is removed.
309+- Before your final answer, check with the worktree tool's list action that no worktree you created is left behind unless the user should keep it.
310+
311+When you delegate:
312+- A worker owns its scope until it completes. Do not search, read, test, review, edit, or otherwise reproduce it; only coordinate, dispatch disjoint work, or yield.
313+- Integrate and verify completed results before answering. You may apply a completed worktree patch without redoing the delegated task.`
301 314
302 // StrictOrchestratorSystemAddendum is used only by explicit headless315 // StrictOrchestratorSystemAddendum is used only by explicit headless
303 // orchestration. The parent coordinates workers and never becomes an316 // orchestration. The parent coordinates workers and never becomes an
@@ -312,11 +325,11 @@ const StrictOrchestratorSystemAddendum = `Strict subagent orchestration is enabl
312 325
313 const subagentLifecycleAddendum = `Workers start without this conversation's context. Shared-worktree workers edit the same working directory, so coordinate dependent work and avoid conflicting edits. Use isolation:"worktree" for parallel coding when workers need separate trees; its changes are returned as a patch and never applied automatically. Do not invent feature scope beyond the user's request. Child workers cannot recursively spawn more sub-agents in v1.326 const subagentLifecycleAddendum = `Workers start without this conversation's context. Shared-worktree workers edit the same working directory, so coordinate dependent work and avoid conflicting edits. Use isolation:"worktree" for parallel coding when workers need separate trees; its changes are returned as a patch and never applied automatically. Do not invent feature scope beyond the user's request. Child workers cannot recursively spawn more sub-agents in v1.
314 327
315-Use required:true whenever your answer or a declared workflow depends on that worker, especially for required validation or finalization. Required workers remain asynchronous unless you explicitly set the wait field on a spawn or resume action: without it, manager calls return immediately, the parent stays free to coordinate or perform policy-permitted non-overlapping work, and the host delivers terminal outcomes through completion updates. Failed, canceled, or interrupted required work remains unmet: use an enabled manager follow-up action to retry it and do not claim completion. An indeterminate outcome after host restart must not be retried automatically; the user must inspect durable results and side effects, then explicitly resume or restart the worker with a new prompt. Required work has no automatic waiver path. Keep required:false only for independent work that may safely finish later.328+Use required:true when your answer or a declared workflow depends on a worker. Failed, canceled, or interrupted required work stays unmet until a successful follow-up; never claim completion before it succeeds. After a host restart, do not retry an indeterminate outcome automatically: the user must reconcile it first. Required work has no automatic waiver path.
316 329
317-Completion is host-event-driven unless you explicitly set the wait field on a spawn or resume action to a whole number of seconds (1–300): on spawn it bounds the initial task, and on resume it bounds the follow-up turn. Omitting wait always returns immediately. An expired wait leaves the accepted child active, whether queued or running; do not retry it until terminal failure, cancellation, or interruption. Never use "bash sleep", "watch", "tail -f", polling loops, repeated "status" calls, or dashboard, metadata, or file checks solely to wait. Those are not completion signals. Continue only with genuinely non-overlapping work; otherwise end or yield your turn until the host injects a completion update.330+Completion is host-event-driven: omit the wait field, then continue only non-overlapping work or end or yield your turn; the host injects a completion update. Set wait (1–300 seconds) only to block this turn on a spawn or resume; an expired wait leaves the child active, so do not retry it. Never use "bash sleep", "watch", "tail -f", polling loops, repeated "status" calls, or file checks solely to wait.
318 331
319-When workers finish, use the host update's agent ID, status, task, optional error, and final response or tail to coordinate any follow-up and summarize the outcome. Treat [auto-subagents update] and [required-subagents update] messages as observed worker state, not as new user requests.`332+Treat [auto-subagents update] and [required-subagents update] messages as observed worker state, not as new user requests; use their agent ID, status, error, and result to coordinate follow-ups.`
320 333
321 // OnDemandSubagentsSystemAddendum keeps the canonical subagent tools334 // OnDemandSubagentsSystemAddendum keeps the canonical subagent tools
322 // available without enabling proactive delegation.335 // available without enabling proactive delegation.
M packages/agent/settings_store_test.go +15 -8
@@ -70,7 +70,7 @@ func TestSubagentsSystemAddendaListOnlyEnabledLifecycleTools(t *testing.T) {
7070
7171 func TestSubagentPoliciesSeparateProactiveAndStrictOwnership(t *testing.T) {
7272 proactive := ProactiveSubagentsSystemAddendumFor(SubagentActions{Spawn: true, Stop: false, Resume: false})
73- for _, want := range []string{"primary owner and implementer", "immediate next task you will perform locally", "If you cannot name useful non-overlapping local work, do not delegate", "Do not search, read, test, review, edit"} {
73+ for _, want := range []string{"delegate by default and keep work local by exception", "spawn it with required:true and end or yield your turn", "Edits of a few lines in one file", "Do not search, read, test, review, edit", "Map dependencies first", "base set to the feature branch", "Review each worker's result as a gate", "into to the feature branch and delete_branch to true", "no worktree you created is left behind"} {
7474 if !strings.Contains(proactive, want) {
7575 t.Fatalf("proactive addendum missing %q:\n%s", want, proactive)
7676 }
@@ -78,6 +78,13 @@ func TestSubagentPoliciesSeparateProactiveAndStrictOwnership(t *testing.T) {
7878 if strings.Contains(proactive, "not an implementer") {
7979 t.Fatalf("proactive addendum retained strict orchestrator contract:\n%s", proactive)
8080 }
81+ // These lines vetoed delegation whenever the next step depended on a
82+ // result, which made the primary implement nearly every task itself.
83+ for _, unwanted := range []string{"primary owner and implementer", "do that work yourself instead of spawning", "do not delegate"} {
84+ if strings.Contains(proactive, unwanted) {
85+ t.Fatalf("proactive addendum kept delegation veto %q:\n%s", unwanted, proactive)
86+ }
87+ }
8188
8289 strict := StrictOrchestratorSystemAddendumFor(SubagentActions{Spawn: true, Stop: false, Resume: false})
8390 for _, want := range []string{"not an implementer", "non-overlapping worker scopes", "Once a worker is active", "Only coordinate workers"} {
@@ -90,11 +97,11 @@ func TestSubagentPoliciesSeparateProactiveAndStrictOwnership(t *testing.T) {
9097 func TestProactiveAddendumRoutesBeforeWorkOnlyWhenSpawningIsAvailable(t *testing.T) {
9198 proactive := ProactiveSubagentsSystemAddendumFor(SubagentActions{Spawn: true, Stop: false, Resume: false})
9299 for _, want := range []string{
93- "Route before you work:",
94- "routing happens when the user states the request you are about to work on",
95- "the [subagents_list] profile that owns each delegable part",
96- "let the tool calls that follow speak for themselves",
97- "Say plainly when nothing is worth delegating",
100+ "Route every new task before you work:",
101+ "Re-route each new request, even late in a long session",
102+ "the [subagents_list] profile for each delegated part",
103+ "do not narrate the tool calls that follow",
104+ "Keep a task fully local only when it is small",
98105 } {
99106 if !strings.Contains(proactive, want) {
100107 t.Fatalf("proactive addendum missing %q:\n%s", want, proactive)
@@ -115,7 +122,7 @@ func TestProactiveAddendumRoutesBeforeWorkOnlyWhenSpawningIsAvailable(t *testing
115122 } {
116123 t.Run(tc.name, func(t *testing.T) {
117124 got := ProactiveSubagentsSystemAddendumFor(SubagentActions{Spawn: false, Stop: tc.stop, Resume: tc.resume})
118- for _, unwanted := range []string{"Route before you work:", "[subagents_list]", "spawn a clearly described general worker"} {
125+ for _, unwanted := range []string{"Route every new task before you work:", "[subagents_list]", "Spawn a clearly described general worker"} {
119126 if strings.Contains(got, unwanted) {
120127 t.Fatalf("spawn-withheld addendum kept %q:\n%s", unwanted, got)
121128 }
@@ -138,7 +145,7 @@ func TestProactiveAddendumRoutesBeforeWorkOnlyWhenSpawningIsAvailable(t *testing
138145 // Routing is the interactive collaboration step; the headless strict
139146 // contract divides scopes itself and must not inherit it.
140147 strict := StrictOrchestratorSystemAddendumFor(SubagentActions{Spawn: true, Stop: false, Resume: false})
141- if strings.Contains(strict, "Route before you work:") || strings.Contains(strict, "[subagents_list]") {
148+ if strings.Contains(strict, "Route every new task before you work:") || strings.Contains(strict, "[subagents_list]") {
142149 t.Fatalf("strict orchestrator inherited interactive routing guidance:\n%s", strict)
143150 }
144151 }
@@ -70,7 +70,7 @@ func TestSubagentsSystemAddendaListOnlyEnabledLifecycleTools(t *testing.T) {
70 70
71 func TestSubagentPoliciesSeparateProactiveAndStrictOwnership(t *testing.T) {71 func TestSubagentPoliciesSeparateProactiveAndStrictOwnership(t *testing.T) {
72 proactive := ProactiveSubagentsSystemAddendumFor(SubagentActions{Spawn: true, Stop: false, Resume: false})72 proactive := ProactiveSubagentsSystemAddendumFor(SubagentActions{Spawn: true, Stop: false, Resume: false})
73- for _, want := range []string{"primary owner and implementer", "immediate next task you will perform locally", "If you cannot name useful non-overlapping local work, do not delegate", "Do not search, read, test, review, edit"} {73+ for _, want := range []string{"delegate by default and keep work local by exception", "spawn it with required:true and end or yield your turn", "Edits of a few lines in one file", "Do not search, read, test, review, edit", "Map dependencies first", "base set to the feature branch", "Review each worker's result as a gate", "into to the feature branch and delete_branch to true", "no worktree you created is left behind"} {
74 if !strings.Contains(proactive, want) {74 if !strings.Contains(proactive, want) {
75 t.Fatalf("proactive addendum missing %q:\n%s", want, proactive)75 t.Fatalf("proactive addendum missing %q:\n%s", want, proactive)
76 }76 }
@@ -78,6 +78,13 @@ func TestSubagentPoliciesSeparateProactiveAndStrictOwnership(t *testing.T) {
78 if strings.Contains(proactive, "not an implementer") {78 if strings.Contains(proactive, "not an implementer") {
79 t.Fatalf("proactive addendum retained strict orchestrator contract:\n%s", proactive)79 t.Fatalf("proactive addendum retained strict orchestrator contract:\n%s", proactive)
80 }80 }
81+ // These lines vetoed delegation whenever the next step depended on a
82+ // result, which made the primary implement nearly every task itself.
83+ for _, unwanted := range []string{"primary owner and implementer", "do that work yourself instead of spawning", "do not delegate"} {
84+ if strings.Contains(proactive, unwanted) {
85+ t.Fatalf("proactive addendum kept delegation veto %q:\n%s", unwanted, proactive)
86+ }
87+ }
81 88
82 strict := StrictOrchestratorSystemAddendumFor(SubagentActions{Spawn: true, Stop: false, Resume: false})89 strict := StrictOrchestratorSystemAddendumFor(SubagentActions{Spawn: true, Stop: false, Resume: false})
83 for _, want := range []string{"not an implementer", "non-overlapping worker scopes", "Once a worker is active", "Only coordinate workers"} {90 for _, want := range []string{"not an implementer", "non-overlapping worker scopes", "Once a worker is active", "Only coordinate workers"} {
@@ -90,11 +97,11 @@ func TestSubagentPoliciesSeparateProactiveAndStrictOwnership(t *testing.T) {
90 func TestProactiveAddendumRoutesBeforeWorkOnlyWhenSpawningIsAvailable(t *testing.T) {97 func TestProactiveAddendumRoutesBeforeWorkOnlyWhenSpawningIsAvailable(t *testing.T) {
91 proactive := ProactiveSubagentsSystemAddendumFor(SubagentActions{Spawn: true, Stop: false, Resume: false})98 proactive := ProactiveSubagentsSystemAddendumFor(SubagentActions{Spawn: true, Stop: false, Resume: false})
92 for _, want := range []string{99 for _, want := range []string{
93- "Route before you work:",100+ "Route every new task before you work:",
94- "routing happens when the user states the request you are about to work on",101+ "Re-route each new request, even late in a long session",
95- "the [subagents_list] profile that owns each delegable part",102+ "the [subagents_list] profile for each delegated part",
96- "let the tool calls that follow speak for themselves",103+ "do not narrate the tool calls that follow",
97- "Say plainly when nothing is worth delegating",104+ "Keep a task fully local only when it is small",
98 } {105 } {
99 if !strings.Contains(proactive, want) {106 if !strings.Contains(proactive, want) {
100 t.Fatalf("proactive addendum missing %q:\n%s", want, proactive)107 t.Fatalf("proactive addendum missing %q:\n%s", want, proactive)
@@ -115,7 +122,7 @@ func TestProactiveAddendumRoutesBeforeWorkOnlyWhenSpawningIsAvailable(t *testing
115 } {122 } {
116 t.Run(tc.name, func(t *testing.T) {123 t.Run(tc.name, func(t *testing.T) {
117 got := ProactiveSubagentsSystemAddendumFor(SubagentActions{Spawn: false, Stop: tc.stop, Resume: tc.resume})124 got := ProactiveSubagentsSystemAddendumFor(SubagentActions{Spawn: false, Stop: tc.stop, Resume: tc.resume})
118- for _, unwanted := range []string{"Route before you work:", "[subagents_list]", "spawn a clearly described general worker"} {125+ for _, unwanted := range []string{"Route every new task before you work:", "[subagents_list]", "Spawn a clearly described general worker"} {
119 if strings.Contains(got, unwanted) {126 if strings.Contains(got, unwanted) {
120 t.Fatalf("spawn-withheld addendum kept %q:\n%s", unwanted, got)127 t.Fatalf("spawn-withheld addendum kept %q:\n%s", unwanted, got)
121 }128 }
@@ -138,7 +145,7 @@ func TestProactiveAddendumRoutesBeforeWorkOnlyWhenSpawningIsAvailable(t *testing
138 // Routing is the interactive collaboration step; the headless strict145 // Routing is the interactive collaboration step; the headless strict
139 // contract divides scopes itself and must not inherit it.146 // contract divides scopes itself and must not inherit it.
140 strict := StrictOrchestratorSystemAddendumFor(SubagentActions{Spawn: true, Stop: false, Resume: false})147 strict := StrictOrchestratorSystemAddendumFor(SubagentActions{Spawn: true, Stop: false, Resume: false})
141- if strings.Contains(strict, "Route before you work:") || strings.Contains(strict, "[subagents_list]") {148+ if strings.Contains(strict, "Route every new task before you work:") || strings.Contains(strict, "[subagents_list]") {
142 t.Fatalf("strict orchestrator inherited interactive routing guidance:\n%s", strict)149 t.Fatalf("strict orchestrator inherited interactive routing guidance:\n%s", strict)
143 }150 }
144 }151 }
M packages/agent/tools/resident_tools_test.go +1 -1
@@ -108,7 +108,7 @@ func TestResidentToolsUseManagerOnly(t *testing.T) {
108108
109109 func TestSubagentSpawnGuidanceRequiresIndependentOwnership(t *testing.T) {
110110 facade := &SubagentTool{}
111- for _, want := range []string{"independent sidecar", "keep immediate blockers local", "never duplicate it in the parent", "end or yield the parent turn"} {
111+ for _, want := range []string{"self-contained task", "never duplicate it in the parent", "end or yield the parent turn"} {
112112 if got := facade.Description(); !strings.Contains(got, want) {
113113 t.Fatalf("description missing %q: %s", want, got)
114114 }
@@ -108,7 +108,7 @@ func TestResidentToolsUseManagerOnly(t *testing.T) {
108 108
109 func TestSubagentSpawnGuidanceRequiresIndependentOwnership(t *testing.T) {109 func TestSubagentSpawnGuidanceRequiresIndependentOwnership(t *testing.T) {
110 facade := &SubagentTool{}110 facade := &SubagentTool{}
111- for _, want := range []string{"independent sidecar", "keep immediate blockers local", "never duplicate it in the parent", "end or yield the parent turn"} {111+ for _, want := range []string{"self-contained task", "never duplicate it in the parent", "end or yield the parent turn"} {
112 if got := facade.Description(); !strings.Contains(got, want) {112 if got := facade.Description(); !strings.Contains(got, want) {
113 t.Fatalf("description missing %q: %s", want, got)113 t.Fatalf("description missing %q: %s", want, got)
114 }114 }
M packages/agent/tools/subagent.go +1 -1
@@ -26,7 +26,7 @@ type SubagentTool struct {
2626 // subagentSpawnGuidance is the operational contract for delegation. It is the
2727 // facade description tail and the internal spawn tool description, so the text
2828 // cannot drift between them.
29-const subagentSpawnGuidance = "Delegate a concrete, bounded scope to a resident sub-agent. For proactive delegation, use an independent sidecar only when the parent has useful non-overlapping work; keep immediate blockers local. A worker owns its scope until completion, so never duplicate it in the parent. If delegation owns the blocking task, end or yield the parent turn. Omit wait to return immediately and receive completion through [auto-subagents update]; set wait to an explicit 1–300 second value only when this turn should wait for the initial task. Set required=true when the outcome is mandatory before the parent's terminal response; failures remain recoverable through the resume action. Do not use resume solely to wait for an existing task or request its result again; yield for the automatic completion update instead. Resume requires a real new instruction; queue schedules a separate turn and another completion. Never use bash sleep, watch, tail -f, polling loops, repeated status calls, dashboard, metadata, or file checks solely to wait."
29+const subagentSpawnGuidance = "Delegate a concrete, bounded scope to a resident sub-agent with a self-contained task. A worker owns its scope until completion, so never duplicate it in the parent. If delegation owns the blocking task, end or yield the parent turn. Omit wait to return immediately and receive completion through [auto-subagents update]; set wait to an explicit 1–300 second value only when this turn should wait for the initial task. Set required=true when the outcome is mandatory before the parent's terminal response; failures remain recoverable through the resume action. Do not use resume solely to wait for an existing task or request its result again; yield for the automatic completion update instead. Resume requires a real new instruction; queue schedules a separate turn and another completion. Never use bash sleep, watch, tail -f, polling loops, repeated status calls, dashboard, metadata, or file checks solely to wait."
3030
3131 // subagentSchema merges the action schemas into the flat, model-facing schema
3232 // the project keeps for provider compatibility. Every property is annotated
@@ -26,7 +26,7 @@ type SubagentTool struct {
26 // subagentSpawnGuidance is the operational contract for delegation. It is the26 // subagentSpawnGuidance is the operational contract for delegation. It is the
27 // facade description tail and the internal spawn tool description, so the text27 // facade description tail and the internal spawn tool description, so the text
28 // cannot drift between them.28 // cannot drift between them.
29-const subagentSpawnGuidance = "Delegate a concrete, bounded scope to a resident sub-agent. For proactive delegation, use an independent sidecar only when the parent has useful non-overlapping work; keep immediate blockers local. A worker owns its scope until completion, so never duplicate it in the parent. If delegation owns the blocking task, end or yield the parent turn. Omit wait to return immediately and receive completion through [auto-subagents update]; set wait to an explicit 1–300 second value only when this turn should wait for the initial task. Set required=true when the outcome is mandatory before the parent's terminal response; failures remain recoverable through the resume action. Do not use resume solely to wait for an existing task or request its result again; yield for the automatic completion update instead. Resume requires a real new instruction; queue schedules a separate turn and another completion. Never use bash sleep, watch, tail -f, polling loops, repeated status calls, dashboard, metadata, or file checks solely to wait."29+const subagentSpawnGuidance = "Delegate a concrete, bounded scope to a resident sub-agent with a self-contained task. A worker owns its scope until completion, so never duplicate it in the parent. If delegation owns the blocking task, end or yield the parent turn. Omit wait to return immediately and receive completion through [auto-subagents update]; set wait to an explicit 1–300 second value only when this turn should wait for the initial task. Set required=true when the outcome is mandatory before the parent's terminal response; failures remain recoverable through the resume action. Do not use resume solely to wait for an existing task or request its result again; yield for the automatic completion update instead. Resume requires a real new instruction; queue schedules a separate turn and another completion. Never use bash sleep, watch, tail -f, polling loops, repeated status calls, dashboard, metadata, or file checks solely to wait."
30 30
31 // subagentSchema merges the action schemas into the flat, model-facing schema31 // subagentSchema merges the action schemas into the flat, model-facing schema
32 // the project keeps for provider compatibility. Every property is annotated32 // the project keeps for provider compatibility. Every property is annotated

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 1

Tags 476

↑↓ moveenter openesc close