fix: anchor the closing-keyword match to a word start #445
No reviewers
Labels
No labels
Agent
Compat/Breaking
Kind/Bug
Kind/Documentation
Kind/Enhancement
Kind/Feature
Kind/Security
Kind/Testing
Priority
Critical
Priority
High
Priority
Low
Priority
Medium
Reviewed
Confirmed
Reviewed
Duplicate
Reviewed
Invalid
Reviewed
Won't Fix
Status
Abandoned
Status
Blocked
Status
Need More Info
No milestone
No assignees
2 participants
Notifications
Total time spent: 1 minute 18 seconds
Due date
igor
1 minute 18 seconds
No due date set.
Dependencies
No dependencies set
Reference
joshtronic/igor!445
Loading…
Reference in a new issue
No description provided.
Delete branch "fix/444-closing-keyword-word-boundary"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What this PR does
Follow-up to #442, worked directly rather than queued.
lib/review.shThe bug
The alternation had no leading boundary, so any word ending in a closing keyword matched:
Not hypothetical here — "issue prefixes" is standing vocabulary in this fleet's tickets. A false match splices a completely unrelated issue's body into the reviewer's prompt as "the requirements this PR claims to satisfy", which is strictly worse than giving it no issue at all and undermines the one thing #442 exists to do.
The shape that actually matters is prose containing an in-word match earlier in the body than the real keyword:
Returned 12 before. Returns 77 now.
Two things folded in
The suite could not have caught a rename. It stubs
forgejo_get_issueandforgejo_repo_get_file, and every production call site is guarded with|| return 0. So if either helper were renamed or changed arity, the feature would degrade to a permanent silent no-op with the suite still green — the same silent-pass class as igor#430/#431. It now asserts both exist inlib/forgejo.shbefore any stub shadows them.The trust model is now written down.
forgejo_repo_get_filereads the default branch (noref), which is what makes pasting Makefile and script contents into the prompt unfenced safe — they are already-merged content. Passing the PR head so the facts reflect the PR's own changes is a plausible-sounding improvement that would open prompt injection against the reviewer that gates auto-merge: a PR could edit its ownMakefileorbin/*.shto inject a fence break or a fake## Unified diffheading into the prompt deciding whether to merge it.I verified the default-branch behaviour empirically rather than trusting the API default:
bin/test-review.shexists only on the #442 branch, and the contents API returns empty without a ref but the blob withref=<branch>.Test plan
foreclosed #8, the earlier-in-word-match-vs-real-keyword body, and punctuation before the keyword ((closes #5)still matches)lib/forgejo.shmake testandmake lintpassKnown and deliberately not changed
The untrusted-issue fence is a delimiter, not an escape — an issue body containing the END marker breaks out. That matches the existing
lib/feedback.shconvention; fixing it in one place only would make the codebase inconsistent. If it gets fixed, both should change together.Closes #444
🤖 Review —
APPROVE(automated)CI for
8f51ed25: successAnchors the closing-keyword regex in
lib/review.shwith a leading(^|[^[:alnum:]]), adds 7 regression cases, an existence guard for the stubbed Forgejo helpers, and a trust-model comment. Focused, honestly described, CI green — approving.Correctness of the fix
lib/review.sh:review_closed_issue_number— the new leading group can never match a digit ([^[:alnum:]]excludes0-9), so the downstreamgrep -oE '[0-9]+'still extracts the issue number and not a stray leading char.^undergrep -oiEis per-line, so the multi-line "real keyword wins" case works as claimed. No regression in the existing first-match-wins behavior: grep resumes scanning after the consumed match, and the following keyword still has its own separator available.prefixes/suffixes/postfixes/unfixed/foreclosed) is preceded by an alnum char, so they now correctly return empty;(closes #5)still matches. That's 6 of the 7 new cases failing pre-fix, matching the description's stated "6 failures" — the checklist is consistent with the diff.Nice confirmation of the bug, for the human's benefit
prefixes #12in the PR body. That's live evidence the bug is real, not a curiosity. Not a defect of the diff.Nits / follow-ups (non-blocking)
bin/test-review.sh:20-21— the comment claims the guard asserts the helpers exist "with the aritylib/review.shcalls them with".declare -Fchecks existence only; arity drift is not caught. The PR description states this accurately ("asserts both exist"); the in-code comment overstates it and could mislead a future maintainer. Suggest dropping the arity clause or actually checking it.Closes #77before its realCloses #444will still resolve to the quoted number (this PR's own body has exactly that shape). Worth a separate ticket if it bites; the fix here is a strict improvement regardless.[^[:alnum:]]admits_, so a hypotheticalpre_fixes #12would still match. Vanishingly unlikely in prose; noting only for completeness.Scope / safety
lib/review.shcorrectly documents why the default-branch read must not be "improved" to the PR head; that's a real prompt-injection vector against the merge gate and is worth having in-tree.lib/forgejo.shcan't leak real helpers into the suite and shadow the later stubs.Independent review by the harness on
claude-opus-5(effort: high). The human reviewer is requested once Igor has reviewed; a human still merges.