Skip to content

Commit 8a362b5

Browse files
committed
Remove deprecated task spawn tool
1 parent 7919199 commit 8a362b5

103 files changed

Lines changed: 1522 additions & 4259 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGELOG.md

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@ parallel copies under `docs/` or `scripts/notes/`. At cut time: rename
1313

1414
## [Unreleased]
1515

16+
### Breaking
17+
18+
- `task` is removed. Use `spawn_agent` to start workers and `wait_agents` to
19+
collect reports; `search_agents` profile ids now dispatch through
20+
`spawn_agent(agent=...)`.
21+
1622
### Fixed
1723

1824
- Codex ChatGPT subscription sessions no longer show a public-rate dollar
@@ -48,6 +54,9 @@ parallel copies under `docs/` or `scripts/notes/`. At cut time: rename
4854

4955
### Fixed
5056

57+
- Mid-run Enter delivers a steer into the live reactor (`Agent.deliver`)
58+
instead of starting a second `send`. `/clear` and `/new` drop queued
59+
input so it cannot land in the next session.
5160
- Failed sessions with an `error` string in `run.json` are valid resume
5261
candidates, not corrupt files. A truly unreadable session id prints one
5362
recovery line; parse diagnostics go to the structured log, not the
@@ -246,13 +255,13 @@ parallel copies under `docs/` or `scripts/notes/`. At cut time: rename
246255

247256
### Fixed
248257

249-
- Retained worker sessions (`spawn_agent`, resumable via `resume_agent`/`followup_task`) now have
250-
their own retention cap, separate from the TUI's finished-session display cap. Previously they
251-
shared that 20-item cap, so `resume_agent` on an early worker failed with a bare `not_found` once
252-
a fan-out of more than 20 workers had finished. A session dropped by the retention cap still
253-
releases its sidecars/reactor/lock entry, always evicts least-recently-used first, and never
254-
evicts a running session. `resume_agent`/`followup_task` against an evicted session now report
255-
its terminal status plus a pointer to `read_agent_trace`, instead of `not_found`.
258+
- Retained worker sessions (`spawn_agent`, resumable via `resume_agent`) now have their own
259+
retention cap, separate from the TUI's finished-session display cap. Previously they shared that
260+
20-item cap, so `resume_agent` on an early worker failed with a bare `not_found` once a fan-out
261+
of more than 20 workers had finished. A session dropped by the retention cap still releases its
262+
sidecars/reactor/lock entry, always evicts least-recently-used first, and never evicts a running
263+
session. `resume_agent` against an evicted session now reports its terminal status plus a pointer
264+
to `read_agent_trace`, instead of `not_found`.
256265

257266
## [0.3.0] - 2026-08-24
258267

@@ -293,10 +302,10 @@ parallel copies under `docs/` or `scripts/notes/`. At cut time: rename
293302
operator interrupts it (`interrupt_agent`) rather than the harness enforcing
294303
a count.
295304

296-
- Added `interrupt_agent({ target })` and `followup_task({ target, message })`,
305+
- Added `interrupt_agent({ target })` and `resume_agent({ target, message })`,
297306
the second half of reusable worker sessions: `interrupt_agent` stops a
298307
retained worker's current turn while keeping it and its context alive
299-
(distinct from the permanent `close_agent`), and `followup_task` sends new
308+
(distinct from the permanent `close_agent`), and `resume_agent` sends new
300309
work into a retained worker's existing session, reusing its prior context
301310
and tool outputs rather than starting fresh. Both are gated to orchestrator
302311
tiers via the existing fleet-verb mechanism, denied to leaves. `interrupt_agent`

README.md

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ prompts. Pass `--no-auto` to start in ask-on-every-consequential-action mode
9898
### What auto allows
9999

100100
- File tools inside the workspace: `write_file`, `edit_file`, `delete_file` (and
101-
other non-shell built-ins such as `manage_tasks`, `task`, …)
101+
other non-shell built-ins such as `manage_tasks`, `spawn_agent`, `wait_agents`, …)
102102
- Unconstrained shell (builds, tests, git, one-off commands that match no
103103
deny/ask rule)
104104
- Read-only tools (`read_file`, `grep`, `search_files`, `list_dir`, `lsp`, …)
@@ -152,9 +152,8 @@ Details live in `docs/PRODUCT.md` (safety model) and `docs/ARCHITECTURE.md`
152152

153153
Corbits Code is a single-process CLI built on Interchange primitives. The primary
154154
session is always the **orchestrator** (Skywalker): it can act directly and
155-
delegates substantial work through a closed director fleet via `spawn_agent` /
156-
`wait_agents` / `search_agents` (`task` remains a fused spawn-plus-wait
157-
wrapper).
155+
delegates substantial work through a closed director fleet via `spawn_agent`,
156+
`wait_agents`, and `search_agents`.
158157

159158
```
160159
CLI (src/index.ts)
@@ -202,10 +201,9 @@ Corbits Code keeps repository guidance and the closed director fleet separate:
202201
- `.agents/agents/` — optional local profile additions; this directory is not
203202
required and may be absent
204203

205-
Named workers resolve through `spawn_agent` / `task` (`resolveDirector`): closed
206-
directors first, then enabled agent plugins, then local
207-
`.agents/agents/*.json|*.yaml` profiles. Use `search_agents` to discover ids
208-
before dispatching.
204+
Named workers resolve through `spawn_agent(agent=...)`: closed directors first,
205+
then enabled agent plugins, then local `.agents/agents/*.json|*.yaml` profiles.
206+
Use `search_agents` to discover ids before dispatching.
209207

210208
## Contributing
211209

docs/ARCHITECTURE.md

Lines changed: 28 additions & 23 deletions
Large diffs are not rendered by default.

docs/IMPLEMENTATION.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,8 @@ src/
8787
stream-consumer.ts Async stream consumer with error handling
8888
hooks.ts Lifecycle hooks: discovery, turn collector, run summary
8989
subagent/
90-
index.ts Sub-agent spawn + SubAgentDirector
91-
task-tool.ts task() — fused spawn+wait; resolveDirector first
90+
index.ts Sub-agent run exports + SubAgentDirector
91+
agent-fleet.ts spawn_agent / wait_agents fleet dispatch and mailbox tools
9292
session-store.ts Retained child session transcripts for observe UI
9393
identity-context.ts ALS: worker description + cwd for gate attribution
9494
config/
@@ -153,18 +153,18 @@ docs/
153153

154154
Sixteen packages under `src/agent/directors/<id>/` register in `DIRECTOR_REGISTRY` (`registry.ts`). Wire path:
155155

156-
1. `spawn_agent(agent=…)` / `task(agent=…)` / `task(intent=…)``resolveDirector` in `task-tool.ts` before tools and system prompt are built. Bare `task` (neither field) and `intent=general` fail closed.
156+
1. `spawn_agent(agent=…)` / `spawn_agent(intent=…)``resolveDirector` in `agent-fleet.ts` before tools and system prompt are built. Bare `spawn_agent` (neither field) and `intent=general` fail closed.
157157
2. `packageToProfile` maps envelope (`tools.allow`/`deny`) to `AgentProfile.capabilities` and `spawn.maySpawn``orchestrator`. System prompts are prefixed with a stable identity block (`formatDirectorSystemPrompt`: agent id, model role, optional skills).
158-
3. Nested spawn: packages with `spawn.allowlist` forward that list into nested `task` (`spawnAllowlist` on nestedDispatch). Off-list `agent` is refused. `task(agent=skywalker)` is refused (primary is not a spawned worker). Primary omits the list so plugin profiles stay reachable.
158+
3. Nested spawn: packages with `spawn.allowlist` forward that list into nested `spawn_agent` (`spawnAllowlist` on nestedDispatch). Off-list `agent` is refused. `spawn_agent(agent=skywalker)` is refused (primary is not a spawned worker). Primary omits the list so plugin profiles stay reachable.
159159
4. `directorProfiles()` is the spawn catalog (`default-agents.ts`) — closed set minus skywalker. Plugin and local `.agents/agents/` profiles still load, but closed `DIRECTOR_IDS` cannot be overridden or aliased.
160160
5. Primary chat role is Skywalker: `buildChatRole()``createSkywalkerSystemPrompt()`. Product mutation tools (`write_file` / `edit_file` / `delete_file`) live in CORE (and `SKYWALKER_TOOLS`) so they are advertised on the primary without a `tool_search` round-trip. DIY tiny/bounded edits on the parent; spawn builder/docs directors for substantial work — a prompt judgment call, not a toolset strip. `PRIMARY_DENIED_PRODUCT_TOOLS` is gone. Shell file-writes stay denied; MCP tools are not re-filtered by a product-write deny list. There is no static per-profile write-path lock (CL-6952).
161161

162162
**Codex tool proxies.** When the active provider is Codex (`isCodexProviderName`), `createAgentToolset` and `runSubAgent` mount `apply_patch`, `shell`, and `update_plan` stringTools from `createCodexToolProxies`, all forwarding through the same posix `ToolRunner` seam (`runTool`) so permission plugins still apply. `apply_patch` parses the Codex envelope and forwards each op (`write_file` / `delete_file` / `read_file`). `shell` — the native Codex name is `shell`, not `exec_command`, per the pinned base-instructions text quoted in `codex-responses-adapter.ts`'s bridge message — normalizes Codex's `command` (string or `["bash","-lc",script]`-style argv array), `workdir`, and `timeout_ms` onto `run_shell`'s `{command, cwd?, timeout?}` and is gated by `allowShellFromCapabilities` (mirrors `allowDeleteFromCapabilities` against `run_shell`). `update_plan` maps Codex's `plan: [{step, status}]` onto `manage_tasks(action: "create")`; `pending`/`in_progress`/`completed` map to `todo`/`doing`/`done` — `manage_tasks`'s `cancelled` status has no Codex equivalent and is never produced by this proxy. Primary strips `apply_patch` after mount (Corbits DIY stays on `write_file` / `edit_file` / `delete_file`); `shell` and `update_plan` stay on primary (same classification as `run_shell` / `manage_tasks`). Build and docs leaf allowlists (`BUILD_TOOLS` / `DOCS_TOOLS`) include `apply_patch` so Codex workers keep the proxy after the capability filter. `CORE_TOOL_NAMES` does not list it.
163163

164-
6. There is no static write-path declaration on packages or profiles (CL-6952 removed it — no shipped director ever set one). Instead, `task-tool.ts` tracks each running dispatch by cwd; a new dispatch that lands on the same cwd as a still-running lane records a `concurrent-lane-overlap` entry in `intervention-log.ts` (class `conflict`). This is advisory only — it never blocks the spawn, since cwd overlap does not prove the two lanes touch the same files.
164+
6. There is no static write-path declaration on packages or profiles (CL-6952 removed it — no shipped director ever set one). Instead, `agent-fleet.ts` tracks each running dispatch by cwd; a new dispatch that lands on the same cwd as a still-running lane records a `concurrent-lane-overlap` entry in `intervention-log.ts` (class `conflict`). This is advisory only — it never blocks the spawn, since cwd overlap does not prove the two lanes touch the same files.
165165
7. Spawn effort: pin > package `modelRole` default (`defaultEffortForDirector`; intern=low; plan/review/orchestrator=high; implement/explore/docs/test=medium) > orchestrator/worker binary > parent inheritance. Optional skills are listed in the identity header for awareness; workers do not mount `use_skill` (guidance is baked into package system prompts). Primary mounts `use_skill` for its own skill list.
166166

167-
Intent defaults: `intent=implement` → director `builder`; `explore``explorer`; `plan``counsel`; `review``critic`; general → error. Spawn: skywalker full fleet; greybeard intern/explorer/critic only; all other directors no `task`. Live `<env>` injects cwd, platform, arch, runtime, date, and git status on every chat and worker prompt.
167+
Intent defaults: `intent=implement` → director `builder`; `explore``explorer`; `plan``counsel`; `review``critic`; general → error. Spawn: skywalker full fleet; greybeard intern/explorer/critic only; all other directors mount no fleet tools. Live `<env>` injects cwd, platform, arch, runtime, date, and git status on every chat and worker prompt.
168168

169169
### Auto Mode
170170

@@ -187,7 +187,7 @@ Unmatched shell auto-allows, including contained non-force `git worktree add`/`r
187187

188188
`ChatInputProps` carries `isProcessing?: boolean` and `onInterrupt?: (message: string) => void`. When `isProcessing` is true, drain timing is **parent-idle** vs **session-idle**:
189189

190-
- **Enter** soft-steers while the parent is busy — enqueues kind `"steer"` and delivers at the next **parent** `tool.boundary` (the parent tool finishing, not a child). Does not interrupt. **Parent-idle** is when the primary Skywalker turn is not inside an in-flight parent tool; a long parent `run_shell` or awaiting `task()` is parent-busy and holds steers.
190+
- **Enter** soft-steers while the parent is busy — enqueues kind `"steer"` and delivers at the next **parent** `tool.boundary` (the parent tool finishing, not a child). Does not interrupt. **Parent-idle** is when the primary Skywalker turn is not inside an in-flight parent tool; a long parent `run_shell` or awaiting `wait_agents` is parent-busy and holds steers.
191191
- **Alt+Enter** queues a follow-up (kind `"queue"`) delivered only on **session-idle** — parent-idle **and** no live fleet lanes (`run` goes idle). Session-idle Alt+Enter is a no-op. **Ctrl+C** stops the run.
192192

193193
Idle-with-fleet is shipped: after a non-blocking `spawn_agent` dispatch the parent turn can settle while workers keep running. The runner emits a `fleet` event carrying the live-lane count; the bridge holds the run busy on that count, so mid-hold Enter upgrades to a new primary turn (sent immediately) instead of queueing a steer, follow-ups keep waiting for true session-idle, and any steer left pending at the hold's engagement delivers immediately — the parent it was steering has already stopped.
@@ -232,7 +232,7 @@ Provider and model configuration lives in JSON settings files. The global file h
232232
}
233233
```
234234

235-
- `timeoutMs` / `maxTimeoutMs` — outer execution watchdog around each tool `run()`. Unset leaves the watchdog unarmed; set these to arm it. `maxTimeoutMs` clamps non-shell tools when set and does not cap a longer requested `run_shell`. The `task` tool is always exempt: a dispatched sub-agent is bounded by stall, opt-in `deadlineMs`, and operator cancel, not the generic per-tool budget.
235+
- `timeoutMs` / `maxTimeoutMs` — outer execution watchdog around each tool `run()`. Unset leaves the watchdog unarmed; set these to arm it. `maxTimeoutMs` clamps non-shell tools when set and does not cap a longer requested `run_shell`. Fleet wait tools are exempt: a dispatched sub-agent is bounded by stall, opt-in `deadlineMs`, and operator cancel, not the generic per-tool budget.
236236
- `waitForApproval` (default **true** when unset) — freeze that budget while a permission prompt is open so a late approve still runs the tool. **Settings → Tools** toggles this live for the next tool call and persists it here. When **false**, the budget keeps ticking during the prompt; on expiry the tool is skipped and the modal is auto-dismissed. The freeze is bounded: after **30 minutes** with the prompt still unanswered the budget resumes ticking on its own, so a prompt that never becomes visible (overlay open, UI gone) cannot hang a tool run indefinitely.
237237

238238
Optional `mcp` block bounds MCP tool calls (`mcp__*` names) specifically — unlike `tools.*`, this arms **unconditionally** even with no settings at all, defaulting to **5 minutes**, since a wedged MCP server otherwise hangs a call forever with nothing to bound it (CL-6895):

docs/PLUGINS.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ export type PluginManifest = {
135135

136136
Workflow recipe names are **not** registered as top-level `/scope` slashes; an integration plugin owns the command prefix (e.g. a `kind: "workflow"` plugin → `/mywf scope`) and contributes workflow definitions beside the plugin under `plugins/<name>/src/workflows/`. Types live in `src/workflows/definition.ts`.
137137

138-
`agent` plugins contribute dispatchable profiles rather than commands. A command or workflow can still fan out to one subagent or a fleet through the normal `task` surface.
138+
`agent` plugins contribute dispatchable profiles rather than commands. A command or workflow can still fan out to one subagent or a fleet through `spawn_agent` and `wait_agents`.
139139

140140
The kind-specific export is the implementation hook:
141141

@@ -145,7 +145,7 @@ The kind-specific export is the implementation hook:
145145
| `command` | `commandPlugin` | slash-command registry | slash commands |
146146
| `workflow` | `workflowPlugin` + optional `commandPlugin` | workflow registry + slash-command registry | named workflow recipes behind an integration command prefix |
147147
| `tool` | `toolPlugin` (factory) | posix toolset | add new agent tools (highest trust) |
148-
| `agent` | `agentPlugin` | sub-agent profiles | contribute `task`-dispatchable agent profiles |
148+
| `agent` | `agentPlugin` | sub-agent profiles | contribute `spawn_agent`-dispatchable agent profiles |
149149

150150
A module with no valid manifest is ignored (not silently half-loaded).
151151

@@ -246,8 +246,8 @@ shape.
246246

247247
### Agent plugins
248248

249-
- `agent` plugins (`agentPlugin` export) contribute `AgentProfile`s that the
250-
`task` tool can dispatch to, resolved in `src/plugins/agent-plugins.ts` and
249+
- `agent` plugins (`agentPlugin` export) contribute `AgentProfile`s that
250+
`spawn_agent(agent=...)` can dispatch to, resolved in `src/plugins/agent-plugins.ts` and
251251
merged into the profile registry alongside local `.agents/agents/` profiles.
252252
- **Data-only agent plugins** — a directory with `agents/*.md` (or flat `*.md`)
253253
and optional `skills/<name>/SKILL.md` needs no `index.ts`; `loadDataOnlyAgentPlugin`

0 commit comments

Comments
 (0)