diff --git a/packages/coding-agent/CHANGELOG.md b/packages/coding-agent/CHANGELOG.md index 6f32dc885..35edf381b 100644 --- a/packages/coding-agent/CHANGELOG.md +++ b/packages/coding-agent/CHANGELOG.md @@ -2,6 +2,10 @@ ## [Unreleased] +### Fixed + +- Fixed the `task` tool rejecting a valid batch `{ context, tasks[] }` call with the misleading `task must be a string (was missing)` when `task.batch` was disabled. The flat single-spawn wire schema strips `tasks`/`context` (arktype `"+": "delete"`) and then fails on the now-missing `task` in the agent loop, preempting the tool's own actionable shape check. The tool now uses lenient argument validation so those raw args reach `execute()`, which explains the real cause (`task.batch is disabled…`) ([#6039](https://github.com/can1357/oh-my-pi/issues/6039)). + ## [17.0.5] - 2026-07-18 ### Added diff --git a/packages/coding-agent/src/task/index.ts b/packages/coding-agent/src/task/index.ts index 3ffbe3c57..b1a546310 100644 --- a/packages/coding-agent/src/task/index.ts +++ b/packages/coding-agent/src/task/index.ts @@ -520,6 +520,17 @@ export class TaskTool implements AgentTool { ); expect(text).toContain("Duplicate task name"); }); + + it("marks lenientArgValidation so execute() surfaces the actionable shape error", async () => { + // Regression (#6039): the flat single-spawn wire schema carries + // `"+": "delete"`, so a batch `{ context, tasks[] }` payload is stripped + // by arktype and rejected as `task must be a string (was missing)` in the + // agent loop — preempting the tool's own actionable message. The lenient + // flag makes the loop forward the raw args to execute() on that failure. + mockDiscovery(); + const tool = await TaskTool.create(createSession({ settings: { "task.batch": false } })); + expect(tool.lenientArgValidation).toBe(true); + + // The raw batch payload the loop would forward reaches execute() and + // yields the actionable reason, never arktype's misleading missing-`task`. + const text = await executeText( + { context: "Background.", tasks: [{ name: "Alpha", task: "Work." }] }, + { "task.batch": false }, + ); + expect(text).toContain("task.batch is disabled"); + expect(text).not.toContain("was missing"); + }); }); describe("task.batch spawning", () => {