diff --git a/apps/desktop/src/state/host.test.ts b/apps/desktop/src/state/host.test.ts index 95ebfd082..411d0a31a 100644 --- a/apps/desktop/src/state/host.test.ts +++ b/apps/desktop/src/state/host.test.ts @@ -1,5 +1,23 @@ import { expect, test } from "bun:test"; -import { noProviderPullList } from "./host"; +import { type JsonObject, obj, str } from "../acp/jsonrpc"; +import { mergeResultNotice, noProviderPullList } from "./host"; +import { isContinueMessage, noticeLine } from "./thread"; + +test("background merge results are durable notices with the complete outcome for the agent", () => { + const results: JsonObject[] = [ + { state: "merged", merged: true, detail: "Squash-merged and the remote branch was deleted" }, + { state: "failing", merged: false, failing: ["Desktop"], detail: "Checks failed" }, + { error: { code: "failed", message: "The engine did not answer" } }, + ]; + for (const result of results) { + const text = mergeResultNotice(3792, result); + expect(isContinueMessage(text)).toBe(true); + expect(noticeLine(text)).toBe( + `Pull request #3792: ${str(result.detail) || str(obj(result.error)?.message)}`, + ); + expect(text).toContain(JSON.stringify(result)); + } +}); test("unsupported remote returns an empty pull request list with a note", () => { expect(noProviderPullList({ code: "no_provider" }, {})).toEqual({ diff --git a/apps/desktop/src/state/host.ts b/apps/desktop/src/state/host.ts index 266731f2d..e08d15361 100644 --- a/apps/desktop/src/state/host.ts +++ b/apps/desktop/src/state/host.ts @@ -258,6 +258,7 @@ import { type QueuedPrompt, type TranscriptItem, turnCompletion, + withPullMark, } from "./thread"; import { isRemoteThread, LOCAL_HOST, splitThreadKey, threadKey } from "./threadKeys"; import { orchestrationTool } from "./toolNames"; @@ -3221,9 +3222,7 @@ async function mergeTracked( }; }; if (call.number) { - void finishMerge().then((result) => - deliver(caller.id, `Pull request #${pull.number}: ${JSON.stringify(result)}`, "", ""), - ); + void finishMerge().then((result) => deliver(caller.id, mergeResultNotice(pull.number, result), "", "")); return { number: pull.number, state: "watching", @@ -3233,6 +3232,13 @@ async function mergeTracked( return finishMerge(); } +/** Keep the full result for the agent beneath the persistent, human-readable notice line. */ +export function mergeResultNotice(number: number, result: JsonObject): string { + const summary = + str(result.detail) || str(obj(result.error)?.message) || str(result.state) || "Merge failed"; + return withPullMark(`Pull request #${number}: ${summary}\n\n${JSON.stringify(result)}`); +} + /** * `cleanup_worktree`: removes a merged delegate's worktree and branch, then * settles it, after the engine confirms nothing unique is lost (git cherry,