fix(coding-agent): kept todo active for prewalk subagents and fixed prewalk gate deadlock

- Updated prewalk gating in `AgentSession` to key the todo gate on active tools instead of registry presence, so deactivated todo tools no longer block prewalk handoff.
- Changed subprocess tool filtering so `todo` is stripped for normal subagents but retained when prewalk is armed, and propagated the prewalk state through tool-session setup.
- Added regression tests for restricted active-tool slates and prewalk/non-prewalk subagent tool propagation to verify todo is handled correctly in each case.
This commit is contained in:
can1357
2026-07-15 05:45:59 +02:00
parent b31eccbc21
commit c32ea55ba3
9 changed files with 106 additions and 16 deletions
+6 -3
View File
@@ -2575,9 +2575,12 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
});
}
// Todos are parent-owned bookkeeping and stripped from subagents —
// except under prewalk, whose plan nudge + todo gate require the
// subagent to commit its own todo list before the hand-off.
const isParentOwnedTool = (name: string): boolean => !prewalk && name === "todo";
const subagentToolNames = session.getActiveToolNames();
const parentOwnedToolNames = new Set(["todo"]);
const filteredSubagentTools = subagentToolNames.filter(name => !parentOwnedToolNames.has(name));
const filteredSubagentTools = subagentToolNames.filter(name => !isParentOwnedTool(name));
if (filteredSubagentTools.length !== subagentToolNames.length) {
await awaitAbortable(session.setActiveToolsByName(filteredSubagentTools));
}
@@ -2635,7 +2638,7 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
getActiveTools: () => session.getActiveToolNames(),
getAllTools: () => session.getAllToolNames(),
setActiveTools: (toolNames: string[]) =>
session.setActiveToolsByName(toolNames.filter(name => !parentOwnedToolNames.has(name))),
session.setActiveToolsByName(toolNames.filter(name => !isParentOwnedTool(name))),
getCommands: () => getSessionSlashCommands(session),
setModel: model => runExtensionSetModel(session, model),
getThinkingLevel: () => session.thinkingLevel,