@@ -33,37 +33,42 @@ gh api "repos/${REPO}/pulls/${PR_NUMBER}" \
3333 | head -c 60000 > /tmp/pr_diff.txt
3434echo " Diff size: $( wc -c < /tmp/pr_diff.txt) bytes"
3535
36- # Parse diff to extract valid RIGHT-side line numbers per file .
37- # These are the only lines the PR Review API will accept for inline comments.
36+ # Parse diff to extract valid RIGHT-side line anchors with code content .
37+ # Format: file:line:type:code (type is "added" for + lines, "context" for unchanged)
3838echo " Extracting valid line anchors from diff..."
3939awk '
40- /^diff --git/ {
41- # Extract filename from +++ line (next after ---)
42- file = ""
43- }
44- /^\+\+\+ b\// {
45- file = substr($0, 7) # strip "+++ b/"
46- }
40+ /^diff --git/ { file = "" }
41+ /^\+\+\+ b\// { file = substr($0, 7) }
4742 /^@@ / {
48- # Parse new-file line number from @@ -old,len +new,len @@
4943 match($0, /\+([0-9]+)(,([0-9]+))?/, arr)
5044 start = arr[1] + 0
51- count = (arr[3] != "") ? arr[3] + 0 : 1
5245 line = start
5346 }
5447 file != "" && !/^diff --git/ && !/^---/ && !/^\+\+\+/ && !/^@@/ {
5548 if (/^-/) {
56- # Deleted line: not on RIGHT side, skip
49+ # Deleted line: skip (not on RIGHT side)
50+ } else if (/^\+/) {
51+ # Added line
52+ code = substr($0, 2) # strip leading +
53+ gsub(/\t/, " ", code)
54+ print file ":" line ":added:" code
55+ line++
5756 } else {
58- # Added (+) or context ( ) line: valid on RIGHT side
59- if (file != "" && line > 0) {
60- print file ":" line
61- }
57+ # Context line
58+ code = substr($0, 2) # strip leading space
59+ gsub(/\t/, " ", code)
60+ print file ":" line ":context:" code
6261 line++
6362 }
6463 }
65- ' /tmp/pr_diff.txt > /tmp/valid_anchors.txt
66- echo " Valid anchors: $( wc -l < /tmp/valid_anchors.txt) "
64+ ' /tmp/pr_diff.txt > /tmp/valid_anchors_full.txt
65+
66+ # Also create a plain file:line list for validation
67+ awk -F: ' {print $1 ":" $2}' /tmp/valid_anchors_full.txt > /tmp/valid_anchors.txt
68+
69+ ADDED_COUNT=$( grep -c ' :added:' /tmp/valid_anchors_full.txt || echo 0)
70+ CONTEXT_COUNT=$( grep -c ' :context:' /tmp/valid_anchors_full.txt || echo 0)
71+ echo " Valid anchors: ${ADDED_COUNT} added, ${CONTEXT_COUNT} context"
6772
6873# Step 3: Select perspectives based on changed paths
6974PERSPECTIVES=" reliability-engineer,test-engineer"
@@ -103,8 +108,27 @@ done
103108
104109DIFF_CONTENT=$( cat /tmp/pr_diff.txt)
105110
106- # Build the anchor list for the prompt (file:line pairs the LLM can reference)
107- ANCHOR_LIST=$( cat /tmp/valid_anchors.txt)
111+ # Build a structured anchor table for the prompt.
112+ # Show added lines prominently, include some context lines for reference.
113+ ANCHOR_TABLE=$( awk -F: '
114+ {
115+ file = $1; line = $2; type = $3
116+ # Rejoin remaining fields as code (code may contain colons)
117+ code = ""
118+ for (i = 4; i <= NF; i++) {
119+ if (i > 4) code = code ":"
120+ code = code $i
121+ }
122+ if (type == "added") {
123+ printf " + %s:%s %s\n", file, line, code
124+ }
125+ }
126+ ' /tmp/valid_anchors_full.txt)
127+
128+ # Also list context lines but more compactly (just file:line ranges)
129+ CONTEXT_SUMMARY=$( awk -F: '
130+ $3 == "context" { print $1 ":" $2 }
131+ ' /tmp/valid_anchors_full.txt | head -50)
108132
109133# Step 5: Review with each perspective, posting one PR review per perspective
110134TOTAL_FINDINGS=0
@@ -145,20 +169,32 @@ ${KNOWLEDGE_CTX}
145169PR Diff:
146170${DIFF_CONTENT}
147171
148- IMPORTANT: You must anchor findings to exact lines from this list of valid diff lines.
149- Each entry is file:line. Only use lines from this list:
172+ === ANCHORING INSTRUCTIONS ===
173+
174+ Each finding MUST be anchored to a specific line in the diff.
175+ Below are the ADDED lines (marked with +) that you can reference.
176+ Pick the most relevant added line for each finding.
177+
178+ ADDED LINES (preferred — use these):
179+ ${ANCHOR_TABLE}
180+
181+ CONTEXT LINES (also valid, but prefer added lines above):
182+ ${CONTEXT_SUMMARY}
183+
184+ For each finding, set "file" and "line" to an EXACT file:line pair from the lists above.
185+ Do NOT invent line numbers. Do NOT use line numbers that aren't listed.
150186
151- ${ANCHOR_LIST}
187+ === OUTPUT FORMAT ===
152188
153- Respond with a JSON array of findings . Each finding must have :
154- - "severity": one of "critical", "important", "suggestion"
155- - "title": a single sentence suitable as a heading
156- - "file": exact file path from the valid lines list above
157- - "line": exact line number from the valid lines list above, or null if no suitable anchor
158- - "body": 2-4 sentences explaining the issue in markdown
189+ Respond with a JSON array. Each finding:
190+ - "severity": "critical" | "important" | "suggestion"
191+ - "title": one- sentence heading
192+ - "file": exact file path from the anchor lists
193+ - "line": exact line number from the anchor lists
194+ - "body": 2-4 sentence explanation in markdown
159195
160- If you find no issues, return an empty array : []
161- Return ONLY valid JSON — no markdown fences, no extra text .
196+ If no issues found , return: []
197+ Return ONLY valid JSON — no markdown fences, no commentary .
162198PROMPT
163199
164200 PROMPT_CONTENT=$( cat /tmp/review_prompt.txt)
0 commit comments