Repository navigation
feat: pr-lint asks GitHub which issues a PR closes instead of parsing Markdown - #113
Conversation
… Markdown The lint re-implemented CommonMark block parsing to decide which `Closes` lines count; nine review rounds on #96 left it still disagreeing with GitHub on nested containers, and three more simple cases turned up after v0.5.7 (#104). GitHub already exposes the answer: the pull request's closingIssuesReferences — closing keywords in prose as GitHub renders them, plus issues linked in the sidebar. run() now reads that field over GraphQL and lint() judges the references: exactly one, in this repository, the branch's, still open. The scanner and its tests are removed. The field lags a body edit by a few seconds (measured 1-9 s), so the lint reads until two reads 5 s apart agree, at most five times. Because it reads live state, "Re-run jobs" now re-checks the current body. On this repository, GitHub's own answer for the three deferred cases — a Setext heading, a fence on a list item's first line, a quote ending on a heading inside a list item — matched CommonMark in all three, where the scanner got all three wrong. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8003baa48c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…ng closingIssuesReferences Two equal reads inside the field's lag window (measured up to 9 s) could both be stale. run() now waits until the PR's updated_at from the event is at least 15 s old before the first read, then keeps the two-read agreement. Runs that start later than that do not wait. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f100be075e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
A sidebar (Development) link can be added or removed without any pull_request event, so a check that accepted it could stay green after the link changed. The query now passes excludeUserLinked: true — GitHub's own list of issues the body closes — and the docs and failure message say a sidebar-only link does not count. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: cf9077da68
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
… settle on a stale answer A manual re-run replays the original event, whose updated_at predates any later body edit, while the references are read live. The query now also returns the pull request's updatedAt, and the lint waits until the later of the two is 15 s old before settling. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
🤖 I have created a release *beep* *boop* --- ## [0.6.0](v0.5.8...v0.6.0) (2026-09-29) ### Features * check-tool-versions reads adopter-owned pins from an optional scripts/tool-pins.extra ([#112](#112)) ([5e37f0b](5e37f0b)) * pr-lint asks GitHub which issues a PR closes instead of parsing Markdown ([#113](#113)) ([02b4138](02b4138)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Summary
scripts/pr-lint.jsdecided which issues a PR closes by re-implementing CommonMark block parsing. Nine review rounds on #96 still left it disagreeing with GitHub whenever containers nest, and three more simple cases turned up after v0.5.7. GitHub already exposes the ground truth: the pull request'sclosingIssuesReferencesfield, read withexcludeUserLinked: trueso it lists exactly the issues the body closes, with keywords in prose as GitHub renders them.run()reads that field over GraphQL.lint()checks the result: exactly one issue, in this repository, the branch's, and still open. Branch grammar and the bot exemptions are unchanged.ci.ymlcomment that said it replays the old payload is corrected.Checking GitHub against CommonMark. I put the three cases deferred to this issue into an open PR's body and read the field:
Heading\n=======\n Closes #104- item\n > quote\n # heading\n\n Closes #107Sidebar links do not count. Adding or removing an issue link in the PR's sidebar fires no
pull_requestevent, so accepting it would let a green check go stale; the lint reads only what the body closes, and AGENTS.md step 4,skills/pr-authoringrule 5 and the architecture ledger say so. Before the first read, the lint also waits until the triggering edit is 15 s old, so two agreeing reads cannot both be stale.Downstream: the kit's
pr-lint.jsandpr-lint.test.jschange shape completely; adopters replace both files whole. The workflow step is unchanged, and so are the job permissions:issues: readandpull-requests: readwere already there.Related issue
Closes #104
Validation
Pick validation depth by blast radius. A level that applies but could not run becomes a
RISK:line below. See AGENTS.md for the validation ladder.make lintmake check(scripts/pr-lint.test.js, 14 pass: lint rules, settle logic with a lagging and a flapping field,run()with a GraphQL stub, 403 and other failures)closingRefs()against live PRs here: docs: AGENTS.md names docs/template-drift.md as the record of deliberate differences from the template #111 → [105], feat: check-tool-versions reads adopter-owned pins from an optional scripts/tool-pins.extra #112 → [107], docs: the upgrade recipe fetches the template's tags into refs/template-tags/ #91 → [88, CLOSED], release PR chore: release 0.5.6 #94 → []cirun executes the new lint against this PRRisk / rollback
Checklist
Before merging:
<type>: <description>)*.local.mdfiles committed