fix(hooks-claude): build subagent payloads from base(), run SubagentStop in the child cwd, drop agentType
Address the D agentType removal + two #124 review findings on the CC bridge's subagent points: - **Payloads from base()**: `subagentStart/StopPayload` bypassed `base()`, so the SubagentStart/SubagentStop stdin payloads omitted the CC-promised `session_id` and `cwd`. Replaced both with a single `subagentPayload()` built from `base(child)` (the child's session_id/cwd when the child is available) + `agent_id` + `agent_type` (+ `stop_hook_active` on Stop). - **SubagentStop runs in the child cwd**: the listener called `runPoint(..., {})` with no agent, so the hook ran in the executor/server cwd. It now looks the child up via `ctx.get('agents').get(info.id)` — still recoverable because `subagent/end` fires from the service's detached `.then` BEFORE the tool caller disposes the child — and passes `{ agent: child }`, matching SubagentStart. New regression: server cwd ≠ child cwd, a `pwd` SubagentStop hook proves it ran in the CHILD workspace (proven red by neutering the lookup). - **agent_type is a constant**: `info.agentType` no longer exists (removed on the subagent branch); both points now report the `SUBAGENT_TYPE = "general-purpose"` constant (Claude Code's Task-tool default), so a hooks.json default/`*`/empty `agent_type` matcher fires. Updated the README matcher-subject note and the bridge/coverage tests (dropped their agentType emits). - **e2e comment**: hooks.e2e.ts said `./hooks.json` loads from the session cwd; corrected to process-level (server launch cwd), with the hook itself running in the session cwd.
This commit is contained in:
@@ -19,11 +19,14 @@ import {
|
||||
/**
|
||||
* With-key e2e: the Claude Code hook bridge running against the REAL acp-agent
|
||||
* subprocess and the REAL model. The example `cordis.yml` loads `dsh-hooks-claude`
|
||||
* pointed at `./hooks.json` in the session cwd; this test writes a `hooks.json`
|
||||
* with a PreToolUse hook that BLOCKS every bash command, then asks the live model
|
||||
* to write a file — and verifies the WORLD (the file never appears on disk),
|
||||
* with a PROCESS-LEVEL `configPath` of `./hooks.json`, resolved once at load
|
||||
* against the ACP server's launch cwd (NOT per-session); this test sets that
|
||||
* launch cwd to the temp workspace and writes a `hooks.json` there with a
|
||||
* PreToolUse hook that BLOCKS every bash command, then asks the live model to
|
||||
* write a file — and verifies the WORLD (the file never appears on disk),
|
||||
* proving the hook actually intercepted execution rather than the agent merely
|
||||
* claiming it couldn't. Key-gated; owns and disposes its subprocess.
|
||||
* claiming it couldn't. (The hook itself then runs in the session cwd.)
|
||||
* Key-gated; owns and disposes its subprocess.
|
||||
*
|
||||
* A keyless companion lives in acp.e2e.ts (stdout purity + session/new); the
|
||||
* full hook-fires-end-to-end transcript is the keyless `hook-prompt-block`
|
||||
|
||||
Reference in New Issue
Block a user