From fad95fd3a5b337e1a2314fecbe26139515553f45 Mon Sep 17 00:00:00 2001 From: Alessandro Pogliaghi Date: Thu, 30 Apr 2026 15:03:00 +0100 Subject: [PATCH 1/2] fix(agent): allow no-repo cloud runs to clone repos --- .../agent/src/server/agent-server.test.ts | 33 +++++++++++++++++++ packages/agent/src/server/agent-server.ts | 18 ++++++++-- 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/packages/agent/src/server/agent-server.test.ts b/packages/agent/src/server/agent-server.test.ts index f18e4ebb7..a90791c0b 100644 --- a/packages/agent/src/server/agent-server.test.ts +++ b/packages/agent/src/server/agent-server.test.ts @@ -639,6 +639,39 @@ describe("AgentServer HTTP Mode", () => { expect(prompt).toContain("stop with local changes ready for review"); }); + it("allows explicit clone and PR work in no-repository mode", () => { + const s = createServer({ repositoryPath: undefined }); + const prompt = (s as unknown as TestableServer).buildCloudSystemPrompt(); + expect(prompt).toContain("Cloud Task Execution — No Repository Mode"); + expect(prompt).toContain( + "Clone the repository into /tmp/workspace/repos//", + ); + expect(prompt).toContain( + "gh repo clone / /tmp/workspace/repos//", + ); + expect(prompt).toContain( + "If the user explicitly asks you to open or update a pull request", + ); + expect(prompt).toContain("open a draft pull request"); + expect(prompt).toContain("unless the user explicitly asks"); + expect(prompt).toContain("Generated-By: PostHog Code"); + expect(prompt).toContain("Task-Id: test-task-id"); + }); + + it("keeps publish disabled in no-repository mode when createPr is false", () => { + const s = createServer({ repositoryPath: undefined, createPr: false }); + const prompt = (s as unknown as TestableServer).buildCloudSystemPrompt(); + expect(prompt).toContain("Cloud Task Execution — No Repository Mode"); + expect(prompt).toContain( + "You may clone a repository and make local edits in that clone", + ); + expect(prompt).toContain( + "Do NOT create branches, commits, push changes, or open pull requests in this run", + ); + expect(prompt).not.toContain("open a draft pull request"); + expect(prompt).not.toContain("gh pr create --draft"); + }); + it("returns auto-PR prompt for Slack-origin runs", () => { process.env.POSTHOG_CODE_INTERACTION_ORIGIN = "slack"; const s = createServer(); diff --git a/packages/agent/src/server/agent-server.ts b/packages/agent/src/server/agent-server.ts index 8e949b8c8..18acf4506 100644 --- a/packages/agent/src/server/agent-server.ts +++ b/packages/agent/src/server/agent-server.ts @@ -1605,6 +1605,19 @@ ${attributionInstructions} } if (!this.config.repositoryPath) { + const publishInstructions = + this.config.createPr === false + ? ` +When the user asks for code changes: +- You may clone a repository and make local edits in that clone +- Do NOT create branches, commits, push changes, or open pull requests in this run` + : ` +When the user explicitly asks to clone or work in a GitHub repository: +- Clone the repository into /tmp/workspace/repos// using \`gh repo clone / /tmp/workspace/repos//\` +- Work from inside that cloned repository for follow-up code changes +- If the user explicitly asks you to open or update a pull request, create a branch, commit the requested changes, push it, and open a draft pull request from inside the clone +- Do NOT create branches, commits, push changes, or open pull requests unless the user explicitly asks for that`; + return ` # Cloud Task Execution — No Repository Mode @@ -1617,11 +1630,12 @@ When the user asks about analytics, data, metrics, events, funnels, dashboards, When the user asks for code changes or software engineering tasks: - Let them know you can help but don't have a repository connected for this session -- Offer to write code snippets, scripts, or provide guidance +- If they have not specified a repository to clone, offer to write code snippets, scripts, or provide guidance +${publishInstructions} Important: -- Do NOT create branches, commits, or pull requests in this mode. - Prefer using MCP tools to answer questions with real data over giving generic advice. +${attributionInstructions} `; } From 9f57557afa9f8f24600003b1c30cfdb2c8e6f1f8 Mon Sep 17 00:00:00 2001 From: Alessandro Pogliaghi Date: Thu, 30 Apr 2026 17:27:25 +0100 Subject: [PATCH 2/2] test(agent): parameterize no-repo prompt cases --- .../agent/src/server/agent-server.test.ts | 74 +++++++++++-------- 1 file changed, 42 insertions(+), 32 deletions(-) diff --git a/packages/agent/src/server/agent-server.test.ts b/packages/agent/src/server/agent-server.test.ts index a90791c0b..c487f8a35 100644 --- a/packages/agent/src/server/agent-server.test.ts +++ b/packages/agent/src/server/agent-server.test.ts @@ -639,38 +639,48 @@ describe("AgentServer HTTP Mode", () => { expect(prompt).toContain("stop with local changes ready for review"); }); - it("allows explicit clone and PR work in no-repository mode", () => { - const s = createServer({ repositoryPath: undefined }); - const prompt = (s as unknown as TestableServer).buildCloudSystemPrompt(); - expect(prompt).toContain("Cloud Task Execution — No Repository Mode"); - expect(prompt).toContain( - "Clone the repository into /tmp/workspace/repos//", - ); - expect(prompt).toContain( - "gh repo clone / /tmp/workspace/repos//", - ); - expect(prompt).toContain( - "If the user explicitly asks you to open or update a pull request", - ); - expect(prompt).toContain("open a draft pull request"); - expect(prompt).toContain("unless the user explicitly asks"); - expect(prompt).toContain("Generated-By: PostHog Code"); - expect(prompt).toContain("Task-Id: test-task-id"); - }); - - it("keeps publish disabled in no-repository mode when createPr is false", () => { - const s = createServer({ repositoryPath: undefined, createPr: false }); - const prompt = (s as unknown as TestableServer).buildCloudSystemPrompt(); - expect(prompt).toContain("Cloud Task Execution — No Repository Mode"); - expect(prompt).toContain( - "You may clone a repository and make local edits in that clone", - ); - expect(prompt).toContain( - "Do NOT create branches, commits, push changes, or open pull requests in this run", - ); - expect(prompt).not.toContain("open a draft pull request"); - expect(prompt).not.toContain("gh pr create --draft"); - }); + it.each([ + { + label: "createPr unset", + config: { repositoryPath: undefined }, + shouldContain: [ + "Cloud Task Execution — No Repository Mode", + "Clone the repository into /tmp/workspace/repos//", + "gh repo clone / /tmp/workspace/repos//", + "If the user explicitly asks you to open or update a pull request", + "open a draft pull request", + "unless the user explicitly asks", + "Generated-By: PostHog Code", + "Task-Id: test-task-id", + ], + shouldNotContain: [], + }, + { + label: "createPr false", + config: { repositoryPath: undefined, createPr: false }, + shouldContain: [ + "Cloud Task Execution — No Repository Mode", + "You may clone a repository and make local edits in that clone", + "Do NOT create branches, commits, push changes, or open pull requests in this run", + ], + shouldNotContain: ["open a draft pull request", "gh pr create --draft"], + }, + ])( + "returns no-repository prompt for $label", + ({ config, shouldContain, shouldNotContain }) => { + const s = createServer(config); + const prompt = ( + s as unknown as TestableServer + ).buildCloudSystemPrompt(); + + for (const text of shouldContain) { + expect(prompt).toContain(text); + } + for (const text of shouldNotContain) { + expect(prompt).not.toContain(text); + } + }, + ); it("returns auto-PR prompt for Slack-origin runs", () => { process.env.POSTHOG_CODE_INTERACTION_ORIGIN = "slack";