fix(subagent-acp): resolve child cwd from the parent session
The ACP backend resolved an unset cwd to the harness process's launch directory, so a delegated child ran — and announced its ACP session — in the server's cwd instead of the delegating session's workspace. Resolve the working directory explicitly: the config cwd override (made absolute and validated at load), else the parent session header's cwd (validated at start), failing loud before spawning when neither exists.
This commit is contained in:
@@ -4,7 +4,9 @@ The ACP provider runs each subagent in a fresh subprocess and drives it as an Ag
|
||||
|
||||
## Start and ownership
|
||||
|
||||
`start(request)` performs `spawn` → ACP `initialize` → `newSession` before it fulfills. Fulfillment therefore means a remote session is ready and ownership has transferred to the caller. A spawn, initialization, new-session, or pre-publication cancellation failure rejects only after the subprocess has been reaped.
|
||||
`start(request)` resolves the child's working directory, then performs `spawn` → ACP `initialize` → `newSession` before it fulfills. Fulfillment therefore means a remote session is ready and ownership has transferred to the caller. A spawn, initialization, new-session, or pre-publication cancellation failure rejects only after the subprocess has been reaped; a working-directory resolution failure rejects before anything is spawned.
|
||||
|
||||
The working directory is the configured `cwd` override when set, else the delegating parent session's cwd — never the server process's own cwd, because one server process serves sessions from many workspaces. The parent-derived value must be an absolute path naming an existing directory, and the same resolved path becomes both the subprocess cwd and the ACP `session/new` workspace.
|
||||
|
||||
The returned run id is minted in the parent namespace. The child server's session id remains private to ACP wire calls because ACP guarantees it only within that fresh child process; using it as the parent lifecycle id could collide with another remote run or a local agent.
|
||||
|
||||
@@ -14,7 +16,7 @@ After publication, the provider sends the prompt and collects streamed `agent_me
|
||||
|
||||
## Capabilities and context
|
||||
|
||||
ACP advertises no start-time capabilities because this process cannot enforce the remote child's depth, tool filter, persona, or structured-output runtime. It also reports `inheritsParentContext: false`: the remote session starts fresh and ignores `request.parent` beyond the seam's required attribution field.
|
||||
ACP advertises no start-time capabilities because this process cannot enforce the remote child's depth, tool filter, persona, or structured-output runtime. It also reports `inheritsParentContext: false`: the remote session starts fresh, and the only parent-derived input is the workspace cwd described above — no conversation context crosses the process boundary.
|
||||
|
||||
## Configuration
|
||||
|
||||
@@ -23,7 +25,7 @@ ACP advertises no start-time capabilities because this process cannot enforce th
|
||||
| `providerName` | `acp` | Registry name on `ctx.subagents`. |
|
||||
| `command` | required | Executable spawned for each run. |
|
||||
| `args` | `[]` | Command arguments. |
|
||||
| `cwd` | process cwd | Child process and ACP session working directory. |
|
||||
| `cwd` | parent session cwd | Working-directory override for the child process and its ACP session; a relative value resolves against the harness launch directory at load and must name an existing directory. |
|
||||
| `permission` | `reject` | Auto-answer permission requests by rejecting or choosing the first allow-shaped option. |
|
||||
| `env` | `{}` | Explicit child environment layered over a credential-scrubbed parent environment. |
|
||||
| `disposeEofGraceMs` | `6000` | Grace after stdin EOF before SIGTERM. |
|
||||
@@ -76,6 +78,7 @@ Keyless tests drive a scripted ACP subprocess over real stdio. The with-key e2e
|
||||
## Known Limitations and Deferred Work
|
||||
|
||||
- **A fresh process per run** — persistent-process pooling is a future optimization ([the seam RFC](../../../docs/rfc/implemented/feature/2026-06-21-subagent-capability-seam.md)).
|
||||
- **Local workspaces only** — the resolved cwd is a local path handed to a child on the same machine; workspace mapping for a remote ACP agent would need its own backend capability and is not designed here.
|
||||
- **No optional start-time capabilities** — this provider cannot apply the local harness's `outputSchema`, depth cap, tool filter, or persona inside the remote process, so it advertises none and the service rejects requests that require them.
|
||||
- **Only `agent_message_chunk` text is collected** — the child's tool-call activity, thought chunks, and plan updates are not surfaced to the parent.
|
||||
- **Permission prompts are auto-answered** (`permission: allow | reject`) — no human is surfaced a child's `session/request_permission` in this cut.
|
||||
|
||||
Reference in New Issue
Block a user