fix: verify scraped PR URLs against the git platform before pr_opened - #561
Merged
Conversation
A /pull/N URL matching the task's repo in agent output was trusted as proof that the task opened a PR — including example URLs echoed straight from the prompt. Before transitioning to pr_opened, ask the platform (GitHub/GitLab/CodeCommit via the GitPlatform abstraction) whether an open PR exists for the task's deterministic branch (optio/task-<id>): - verified: use the canonical PR URL from the platform - no PR on the branch: ignore the scraped URL (logged) and clear any prUrl persisted mid-stream, so the task escalates to needs_attention (completed_without_pr) instead of pr_opened - platform unavailable (no token / API error): fall back to the previous trust-the-logs behavior Fixes #531
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #531 — PR detection accepted any same-repo
/pull/NURL in agent output as the task's opened PR, even when no PR was opened. As @genisd noted, even a PR URL pasted into the prompt (and echoed back by the agent) would immediately flip the task topr_opened, pointing at a PR that may not exist or belongs to someone else.Root cause
task-workerscans streamed agent output for PR/MR URLs and, at exec end, trusted any candidate that merely matched the task's repo (capturedPrUrl/ persistedtasks.prUrl/ raw-log fallback) — no check that the PR exists, is open, or was created from the task's branch.Fix — verify against the platform before trusting the URL
Task branches are deterministic (
optio/task-<taskId>), so the platform's answer for that branch is a strong, authoritative signal. Before thepr_openedtransition, the worker now calls the existingGitPlatform.listOpenPullRequests(ri, { branch })(already implemented with head/source-branch filtering for GitHub, GitLab, and CodeCommit) via a newverifyTaskPr():pr_openedusing the canonical URL from the platform (wins over the scraped URL, which may be truncated or wrong).prUrlpersisted mid-stream is cleared (clearTaskPr). The task then flows toneeds_attentionwith reasoncompleted_without_pr— the behavior the issue expected. The verification result is reused so the existing API-fallback path doesn't repeat the same platform call.checkExistingPr(pre-agent short-circuit, API fallbacks, reconciliation) is now a thin wrapper oververifyTaskPr, so all platform lookups share one implementation.Changes
apps/api/src/services/pr-detection-service.ts— newverifyTaskPr()(discriminatedverified/no_pr/unavailableresult) and pureresolveDetectedPrUrl()decision helper;checkExistingPr()refactored on topapps/api/src/workers/task-worker.ts— verify scraped URL before thepr_openedtransition; skip redundant API-fallback calls when the platform already reported no PRapps/api/src/services/task-service.ts—clearTaskPr()to remove a bogusprUrl/prNumberpersisted during streamingapps/api/src/services/pr-detection-service.test.ts— tests: prompt-echoed URL rejected when no PR exists on the branch; genuine PR with matching head branch accepted; canonical-URL preference; unavailable-platform fallbackTesting
pnpm turbo typecheck— 12/12 packages passapps/apivitest suite — 122 files, 2156 tests pass (includes new verification tests)pnpm format:check— clean