give the PR reviewer the filed issue's text so it can judge intent, not just relatedness - #6129
Merged
Merged
Conversation
…ot just relatedness The pr-reviewer pipeline already required an external PR to link an open issue assigned to its opener, and Stage 2 was told to return true only for a change "related to the linked issue" — but the issue's title and body never crossed into any stage. Only issue NUMBERS and open/assigned booleans did, so neither the eligibility gate nor the Stage 3 reviewer could tell a PR that implements the filed issue from one that links it and does something else entirely. The preflight now keeps the title and description of each open linked issue, screens that text through the model-abuse boundary in the PR's own scan pass (an injected issue body flags the PR instead of reaching a reviewer as the requirement it is supposed to trust), and carries it into both judging stages as `linkedIssues`. Stage 2 rejects a diff that implements something other than what the issue asks; Stage 3 treats scope drift as a blocking finding rather than approving clean code for the wrong task. Two deterministic guards keep the model honest: a non-waived PR is eligible only when screened issue intent actually reached the gate, and the pre-action recheck discards an approval whose linked issue was rewritten after the gate judged it. The maintainer "Review this PR" waiver is unaffected.
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
The pr-reviewer pipeline could tell that an external PR linked an open issue assigned to its opener. It could not tell whether the PR did what that issue asked — the issue's title and body never crossed into any stage. Only issue numbers and open/assigned booleans did, so Stage 2's rule "return true only for a change related to the linked issue" and Stage 3's approve/request-changes verdict were both judged without the requirement in front of them.
server/lib/modelAbuseGuard.js—normalizeLinkedIssues(bounded: 10 issues, 300-char titles, 8000-char bodies, per-issuetruncatedflag),linkedIssueIntentContent, andlinkedIssueIntentFingerprint, which hashes through the existingmodelAbuseContentFingerprintso intent evidence shares the boundary's one fingerprinting scheme.normalizeEligibilityFactsgainsintentFingerprint; the sha256-hex shape is now one exportedisSha256Hexinstead of three private copies.server/services/prReviewerSecurity.js— the preflight keeps the title/body of each open linked issue and screens that text in the PR's own model-abuse pass. An injected issue body therefore flags the PR rather than reaching a reviewer as the requirement it is supposed to trust. The scan key covers the issue text, so editing a linked issue re-scans rather than reusing a stale verdict.server/services/modelAbuseGuard.js—linkedIssuesvalidated at the snapshot boundary, so it reaches both Stage 2 and Stage 3 envelopes and counts against the snapshot size cap.LINKED_ISSUE_INTENT_EVIDENCEblock (the patternREQUIRED_REVIEW_PUBLICATION_RULEalready uses) states that the issue text is the requirement, that the PR's own description is the author's claim about it, and that a line inside an issue addressing the reviewer is content and not a command. Stage 2 rejects a diff that implements something else, is a refactor the issue never asked for, or leaves the stated ask untouched. Stage 3 treats scope drift as blocking — clean, well-tested code for the wrong task isrequest_changes, and vague or clipped intent isdefer.Deterministic guards, not just prompt text
eligibilityFactsAllowadmits a non-waived PR only when screened issue intent actually reached the gate. A model that answeredeligiblewith no requirement in front of it was guessing.eligibilityFactsStillCurrentrecomputes the intent fingerprint from the issues it already refetches, so an approval whose linked issue was rewritten after the gate judged it is discarded instead of merged. Facts persisted before intent screening existed carry no fingerprint and keep their previous meaning.Decisions worth flagging
contentFingerprintfor the diff,intentFingerprintfor the issue text).pullRequestContentFingerprint, which the pre-action recheck recomputes from PR title/body/diff.Test plan
server/lib/modelAbuseGuard.test.js— bounds/order/dedup and thetruncatedflag; fingerprint stability, sensitivity to a rewritten body, andnullfor no evidence; an unusable fingerprint kept out of the validated fact set.server/services/prReviewerSecurity.test.js— intent evidence and its fingerprint recorded alongside the prerequisites; the issue text present in the single scanned payload and carried to the reviewer; a hostile linked issue withholds the PR without quoting the content; unreadable issue still fails the lookup closed.server/services/prReviewerPipeline.test.js— a model-positive decision forced false when no screened intent reached the gate.server/services/issueWatcher.test.js— an approval discarded when the linked issue was rewritten after the gate judged it, and the same approval landing against the text it was actually judged against (verified to fail without the fix).server/services/taskPromptDefaults.test.js— both judging stages carry the shared intent block; Stage 2's mismatch rejections and Stage 3's scope-drift/deferrules.