Skip to content
This repository was archived by the owner on Aug 6, 2026. It is now read-only.

Commit 5252ab2

Browse files
authored
fix(signals): pr attribution for bots (#3302)
1 parent e92cea4 commit 5252ab2

2 files changed

Lines changed: 22 additions & 5 deletions

File tree

packages/agent/src/server/agent-server.test.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2113,8 +2113,22 @@ describe("AgentServer HTTP Mode", () => {
21132113
expect(s.detectedPrUrl).toBeNull();
21142114
});
21152115

2116-
it("fails closed when the run's GitHub identity cannot be resolved", async () => {
2117-
const s = setup(justNow());
2116+
it("attributes a recent PR when the identity is a GitHub App installation (gh api user unavailable)", async () => {
2117+
// Cloud runs authenticate with a GitHub App installation token, for which
2118+
// `gh api user` returns 403 → ghLogin is null. The PR is authored by the
2119+
// app bot (e.g. "app/posthog"); recency alone must carry attribution.
2120+
const s = setup(justNow(), "app/posthog");
2121+
s.fetchGhLogin = vi.fn(async () => null);
2122+
s.maybeAttachCreatedPr(payload, terminalUpdate(PR_URL));
2123+
await flush();
2124+
expect(s.posthogAPI.updateTaskRun).toHaveBeenCalledWith("t", "r", {
2125+
output: { pr_url: PR_URL, pr_urls: [PR_URL] },
2126+
});
2127+
expect(s.detectedPrUrl).toBe(PR_URL);
2128+
});
2129+
2130+
it("still rejects an old PR when the identity cannot be resolved (recency guards)", async () => {
2131+
const s = setup(longAgo, "app/posthog");
21182132
s.fetchGhLogin = vi.fn(async () => null);
21192133
s.maybeAttachCreatedPr(payload, terminalUpdate(PR_URL));
21202134
await flush();

packages/agent/src/server/agent-server.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3500,10 +3500,13 @@ ${signedCommitInstructions}${prLinkInstructions}${shellEfficiencyInstructions}
35003500
return;
35013501
}
35023502

3503-
// Only attribute PRs created during this run by this run's own GitHub
3504-
// identity — not ones the agent merely viewed.
3503+
// Only attribute PRs created during this run — not ones the agent merely
3504+
// viewed. GitHub App installation tokens (all cloud runs) can't read
3505+
// `gh api user`, so ghLogin is null there; enforce the author match only when
3506+
// we resolved our own identity, otherwise the recency gate alone scopes
3507+
// attribution to PRs created during this run.
35053508
if (!wasCreatedRecently(attribution.createdAt, Date.now())) return;
3506-
if (!wasCreatedByLogin(attribution.author, ghLogin)) return;
3509+
if (ghLogin && !wasCreatedByLogin(attribution.author, ghLogin)) return;
35073510

35083511
this.detectedPrUrl = prUrl;
35093512

0 commit comments

Comments
 (0)