fix(runner): tell agents a comment on a running task waits for its next turn

A chat lead asked to change an existing website task whose assignee was mid-run
read comment_on_task's "without reopening or interrupting it" as "the worker
will never see it", then spent its turn inspecting the assignee's workspace and
considering writing the worker's input file directly. State the actual product
behavior: a comment on a running task is queued and delivered at the start of
the assignee's next turn, it is the way to route a changed requirement to an
existing task, and it should be reported as saved, not applied.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
DottaandClaude Opus 5.5 committed 2026-11-08 06:06:00 -06:00
1 parent 742ffb0a71
commit 152af6161c
2 files changed
+11 -1

No files matched your search

@@ -86,6 +86,16 @@ describe("Runner workspace bridge", () => {
expect(await readFile(join(directory, "result.txt"), "utf8")).toBe("hello");
});
it("tells agents that a comment on a running task waits for the assignee's next turn", () => {
// A chat lead routing a requirement change to busy work otherwise reads "without interrupting"
// as "never delivered" and reaches for the assignee's workspace or a duplicate task instead.
const comment = runnerBridgeDefinitions({ workspace: false, skills: false, api: true, mode: "standard" }).find(tool => tool.name === "comment_on_task");
expect(comment?.description).toContain("existing task's assignee a new or changed requirement");
expect(comment?.description).toContain("rather than creating a duplicate task or editing that task's workspace files");
expect(comment?.description).toContain("delivers it at the start of the assignee's next turn on that task");
expect(comment?.description).toContain("not as already applied");
});
it.skipIf(process.platform === "linux")("does not expose or execute commands without descendant containment", async () => {
const directory = await root();
expect(workspaceCommandSandboxAvailable()).toBe(false);
@@ -14,7 +14,7 @@ const specs = [
["get_identity", "Read your agent identity, responsible person, permissions and currently available tools.", z.object({}).strict(), "read"],
["list_people", "List active company people and their IDs for human assignment; roles identify the owner.", z.object({ after: z.string().optional(), limit: z.number().int().min(1).max(100).default(50) }).strict(), "read"],
["get_task", "Read another task through normal task permissions.", z.object({ taskId: z.uuid() }).strict(), "read"],
["comment_on_task", "Post an attributed comment on an authorized task, without reopening or interrupting it.", z.object({ taskId: z.uuid(), body: z.string().trim().min(1).max(20000) }).strict(), "mutation"],
["comment_on_task", "Post an attributed comment on an authorized task, without reopening or interrupting it. Use it to give an existing task's assignee a new or changed requirement, rather than creating a duplicate task or editing that task's workspace files. If the assignee is running on that task now, the comment does not reach the run in progress: Paperclip saves it in the task's queue and delivers it at the start of the assignee's next turn on that task. Report it as saved for that next turn, not as already applied.", z.object({ taskId: z.uuid(), body: z.string().trim().min(1).max(20000) }).strict(), "mutation"],
["list_task_documents", "List documents on an authorized task.", z.object({ taskId: z.uuid() }).strict(), "read"],
["read_task_document", "Read a document on an authorized task.", z.object({ taskId: z.uuid(), key: documentKey }).strict(), "read"],
["write_task_document", "Write a document on an authorized task using its current revision. Permissions and document locks apply.", z.object({ taskId: z.uuid(), key: documentKey, title: z.string().min(1).max(200), body: z.string().max(20000), baseRevisionId: z.uuid().nullable() }).strict(), "mutation"],