pr-shepherd 0.35.0 → 0.37.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/README.md +32 -12
  3. package/bin/checks/conclusions.d.mts +6 -0
  4. package/bin/checks/conclusions.mjs +9 -0
  5. package/bin/checks/triage.mjs +11 -3
  6. package/bin/cli/args.mjs +1 -0
  7. package/bin/cli/default-poll.mjs +1 -0
  8. package/bin/cli/fix-formatter.mjs +4 -2
  9. package/bin/cli/help-command-pages.d.mts +1 -1
  10. package/bin/cli/help-iterate-poll-pages.d.mts +1 -1
  11. package/bin/cli/help-iterate-poll-pages.mjs +10 -5
  12. package/bin/cli/help-top-page.d.mts +1 -1
  13. package/bin/cli/help-top-page.mjs +2 -1
  14. package/bin/cli/help.d.mts +2 -2
  15. package/bin/cli/iterate-formatter.mjs +11 -2
  16. package/bin/cli/iterate-lean.mjs +1 -0
  17. package/bin/cli/poll-handler.mjs +7 -0
  18. package/bin/commands/check-annotations.d.mts +16 -3
  19. package/bin/commands/check-annotations.mjs +37 -1
  20. package/bin/commands/check.d.mts +1 -0
  21. package/bin/commands/check.mjs +35 -28
  22. package/bin/commands/commit-suggestion.mjs +11 -5
  23. package/bin/commands/iterate/fix-code.mjs +13 -6
  24. package/bin/commands/iterate/helpers.d.mts +1 -0
  25. package/bin/commands/iterate/helpers.mjs +15 -6
  26. package/bin/commands/iterate/index.mjs +5 -10
  27. package/bin/commands/iterate/render.mjs +9 -5
  28. package/bin/commands/iterate/stall.mjs +5 -0
  29. package/bin/commands/poll.d.mts +2 -0
  30. package/bin/commands/poll.mjs +51 -17
  31. package/bin/commands/ready-delay.mjs +3 -13
  32. package/bin/config/load.mjs +67 -25
  33. package/bin/github/batch-page-helpers.d.mts +45 -0
  34. package/bin/github/batch-page-helpers.mjs +63 -0
  35. package/bin/github/batch-page.d.mts +14 -0
  36. package/bin/github/batch-page.mjs +62 -0
  37. package/bin/github/batch-parse-suites.d.mts +4 -0
  38. package/bin/github/batch-parse-suites.mjs +25 -0
  39. package/bin/github/batch-parser-helpers.mjs +1 -0
  40. package/bin/github/batch-parsers-rules.d.mts +6 -0
  41. package/bin/github/batch-parsers-rules.mjs +122 -0
  42. package/bin/github/batch-parsers.mjs +6 -0
  43. package/bin/github/batch-raw-rules.d.mts +59 -0
  44. package/bin/github/batch-raw-rules.mjs +1 -0
  45. package/bin/github/batch-raw-types.d.mts +25 -11
  46. package/bin/github/batch.d.mts +2 -0
  47. package/bin/github/batch.mjs +14 -120
  48. package/bin/github/gql/batch-pr-page.gql +194 -0
  49. package/bin/github/gql/batch-pr.gql +79 -21
  50. package/bin/github/gql/commit-suggestion-thread.gql +40 -0
  51. package/bin/github/http.d.mts +2 -1
  52. package/bin/github/http.mjs +2 -1
  53. package/bin/github/pagination.d.mts +3 -2
  54. package/bin/github/pagination.mjs +3 -2
  55. package/bin/github/queries.d.mts +4 -0
  56. package/bin/github/queries.mjs +4 -0
  57. package/bin/github/rest-http.d.mts +6 -1
  58. package/bin/github/rest-http.mjs +25 -86
  59. package/bin/github/rest-text.d.mts +1 -0
  60. package/bin/github/rest-text.mjs +88 -0
  61. package/bin/github/suggestion-thread.d.mts +9 -0
  62. package/bin/github/suggestion-thread.mjs +45 -0
  63. package/bin/github/thread-comments.mjs +12 -8
  64. package/bin/merge-status/derive.mjs +2 -0
  65. package/bin/merge-status/requirements-format.d.mts +3 -0
  66. package/bin/merge-status/requirements-format.mjs +88 -0
  67. package/bin/merge-status/requirements.d.mts +2 -0
  68. package/bin/merge-status/requirements.mjs +51 -0
  69. package/bin/reporters/agent.mjs +0 -3
  70. package/bin/state/base.d.mts +9 -0
  71. package/bin/state/base.mjs +23 -0
  72. package/bin/state/bot-cr-seen.mjs +3 -13
  73. package/bin/state/fix-attempts.mjs +3 -13
  74. package/bin/state/iterate-stall.mjs +3 -13
  75. package/bin/state/seen-comments.mjs +6 -13
  76. package/bin/types/check-classification.d.mts +2 -2
  77. package/bin/types/github.d.mts +6 -7
  78. package/bin/types/iterate.d.mts +6 -7
  79. package/bin/types/merge-requirements.d.mts +82 -0
  80. package/bin/types/merge-requirements.mjs +2 -0
  81. package/bin/types/report.d.mts +5 -5
  82. package/bin/types.d.mts +1 -0
  83. package/bin/types.mjs +1 -0
  84. package/bin/util/path-segment.d.mts +2 -0
  85. package/bin/util/path-segment.mjs +2 -0
  86. package/bin/util/pool.d.mts +2 -0
  87. package/bin/util/pool.mjs +18 -0
  88. package/package.json +1 -1
  89. package/plugins/pr-shepherd/.codex-plugin/plugin.json +1 -1
  90. package/plugins/pr-shepherd/.codex.mcp.json +1 -1
  91. package/plugins/pr-shepherd/.mcp.json +1 -1
@@ -1,134 +1,28 @@
1
- import { graphql, graphqlWithRateLimit } from "./client.mjs";
2
- import { paginateForward, paginateBackward } from "./pagination.mjs";
1
+ import { graphqlWithRateLimit } from "./client.mjs";
3
2
  import { hydrateThreadCommentPages } from "./thread-comments.mjs";
4
3
  import { BATCH_PR_QUERY } from "./queries.mjs";
5
4
  import { parseRawPr } from "./batch-parsers.mjs";
6
- import { requireContextNodes, requireRawPr } from "./batch-response.mjs";
5
+ import { parseCheckSuitesComplete, parseSuiteStartupFailures } from "./batch-parse-suites.mjs";
6
+ import { mergeStartupFailureChecks } from "../checks/startup-failures.mjs";
7
+ import { paginateBatchConnections } from "./batch-page.mjs";
8
+ import { requireRawPr } from "./batch-response.mjs";
7
9
  /**
8
10
  * Fetch all PR data needed for a `shepherd check` in one (or a few, if paginating) GraphQL requests.
9
11
  */
10
12
  export async function fetchPrBatch(pr, repo, opts = {}) {
11
- // First page: no cursor variables.
12
13
  const result = await graphqlWithRateLimit(BATCH_PR_QUERY, {
13
14
  owner: repo.owner,
14
15
  repo: repo.name,
15
16
  pr,
16
17
  });
17
18
  const raw = requireRawPr(result.data, pr, repo);
18
- // Paginate reviewThreads backward if the first page is incomplete.
19
- let rawThreadPages = raw.reviewThreads.nodes;
20
- if (raw.reviewThreads.pageInfo.hasPreviousPage && raw.reviewThreads.pageInfo.startCursor) {
21
- // Pass startCursor so paginateBackward fetches pages *before* the already-
22
- // fetched first page instead of re-fetching it from the start.
23
- const extra = await paginateBackward(async (cursor) => {
24
- const res = await graphql(BATCH_PR_QUERY, {
25
- owner: repo.owner,
26
- repo: repo.name,
27
- pr,
28
- ...(cursor ? { threadsCursor: cursor } : {}),
29
- });
30
- const pr2 = requireRawPr(res.data, pr, repo);
31
- return pr2.reviewThreads;
32
- }, raw.reviewThreads.pageInfo.startCursor);
33
- // extra contains pages before the first page.
34
- rawThreadPages = [...extra, ...rawThreadPages];
35
- }
36
- rawThreadPages = await hydrateThreadCommentPages(rawThreadPages);
37
- // Paginate comments backward if the first page is incomplete.
38
- let rawCommentNodes = raw.comments.nodes;
39
- if (raw.comments.pageInfo.hasPreviousPage && raw.comments.pageInfo.startCursor) {
40
- const extra = await paginateBackward(async (cursor) => {
41
- const res = await graphql(BATCH_PR_QUERY, {
42
- owner: repo.owner,
43
- repo: repo.name,
44
- pr,
45
- ...(cursor ? { commentsCursor: cursor } : {}),
46
- });
47
- const pr2 = requireRawPr(res.data, pr, repo);
48
- return pr2.comments;
49
- }, raw.comments.pageInfo.startCursor);
50
- rawCommentNodes = [...extra, ...rawCommentNodes];
51
- }
52
- // Paginate CHANGES_REQUESTED reviews backward if the first page is incomplete.
53
- let rawReviewNodes = raw.changesRequestedReviews.nodes;
54
- if (raw.changesRequestedReviews.pageInfo.hasPreviousPage &&
55
- raw.changesRequestedReviews.pageInfo.startCursor) {
56
- const extra = await paginateBackward(async (cursor) => {
57
- const res = await graphql(BATCH_PR_QUERY, {
58
- owner: repo.owner,
59
- repo: repo.name,
60
- pr,
61
- ...(cursor ? { changesRequestedCursor: cursor } : {}),
62
- });
63
- const pr2 = requireRawPr(res.data, pr, repo);
64
- return pr2.changesRequestedReviews;
65
- }, raw.changesRequestedReviews.pageInfo.startCursor);
66
- rawReviewNodes = [...extra, ...rawReviewNodes];
67
- }
68
- // Paginate COMMENTED review summaries backward if the first page is incomplete.
69
- let rawReviewSummaryNodes = raw.reviewSummaries.nodes;
70
- if (raw.reviewSummaries.pageInfo.hasPreviousPage && raw.reviewSummaries.pageInfo.startCursor) {
71
- const extra = await paginateBackward(async (cursor) => {
72
- const res = await graphql(BATCH_PR_QUERY, {
73
- owner: repo.owner,
74
- repo: repo.name,
75
- pr,
76
- ...(cursor ? { reviewSummariesCursor: cursor } : {}),
77
- });
78
- const pr2 = requireRawPr(res.data, pr, repo);
79
- return pr2.reviewSummaries;
80
- }, raw.reviewSummaries.pageInfo.startCursor);
81
- rawReviewSummaryNodes = [...extra, ...rawReviewSummaryNodes];
82
- }
83
- // Paginate APPROVED reviews backward if the first page is incomplete — gated behind
84
- // `paginateApprovedReviews` because approvals minimization is opt-in. See FetchPrBatchOptions.
85
- let rawApprovedReviewNodes = raw.approvedReviews.nodes;
86
- if (opts.paginateApprovedReviews &&
87
- raw.approvedReviews.pageInfo.hasPreviousPage &&
88
- raw.approvedReviews.pageInfo.startCursor) {
89
- const extra = await paginateBackward(async (cursor) => {
90
- const res = await graphql(BATCH_PR_QUERY, {
91
- owner: repo.owner,
92
- repo: repo.name,
93
- pr,
94
- ...(cursor ? { approvedReviewsCursor: cursor } : {}),
95
- });
96
- const pr2 = requireRawPr(res.data, pr, repo);
97
- return pr2.approvedReviews;
98
- }, raw.approvedReviews.pageInfo.startCursor);
99
- rawApprovedReviewNodes = [...extra, ...rawApprovedReviewNodes];
100
- }
101
- // Paginate check contexts forward if the first page is incomplete.
102
- let rawCheckNodes = requireContextNodes(raw.commits.nodes[0]?.commit.statusCheckRollup?.contexts.nodes ?? []);
103
- const checksPageInfo = raw.commits.nodes[0]?.commit.statusCheckRollup?.contexts.pageInfo;
104
- const firstOid = raw.commits.nodes[0]?.commit.oid;
105
- if (checksPageInfo?.hasNextPage && checksPageInfo.endCursor) {
106
- // Pass endCursor so paginateForward fetches pages *after* the already-
107
- // fetched first page instead of re-fetching it from the start.
108
- let pageCount = 0;
109
- const extra = await paginateForward(async (cursor) => {
110
- const res = await graphql(BATCH_PR_QUERY, {
111
- owner: repo.owner,
112
- repo: repo.name,
113
- pr,
114
- ...(cursor ? { checksCursor: cursor } : {}),
115
- });
116
- const pr2 = requireRawPr(res.data, pr, repo);
117
- if (!pr2?.commits.nodes[0]?.commit.statusCheckRollup) {
118
- throw new Error(`Check-context pagination interrupted: statusCheckRollup disappeared on page ${pageCount + 2} (possible force-push race). Retry after the push stabilizes.`);
119
- }
120
- const currentOid = pr2.commits.nodes[0]?.commit.oid;
121
- if (firstOid !== undefined && currentOid !== undefined && currentOid !== firstOid) {
122
- throw new Error(`Check-context pagination interrupted: head commit changed from ${firstOid} to ${currentOid} between pages (force-push race). Retry.`);
123
- }
124
- pageCount++;
125
- const ctxs = pr2.commits.nodes[0]?.commit.statusCheckRollup?.contexts;
126
- if (!ctxs)
127
- return { pageInfo: { hasNextPage: false, endCursor: null }, nodes: [] };
128
- return { ...ctxs, nodes: requireContextNodes(ctxs.nodes) };
129
- }, checksPageInfo.endCursor);
130
- rawCheckNodes = [...rawCheckNodes, ...extra];
131
- }
132
- const data = parseRawPr(raw, rawThreadPages, rawCommentNodes, rawReviewNodes, rawReviewSummaryNodes, rawApprovedReviewNodes, rawCheckNodes);
133
- return { data, rateLimit: result.rateLimit };
19
+ const paged = await paginateBatchConnections(pr, repo, raw, opts, result.rateLimit);
20
+ const rawThreadPages = await hydrateThreadCommentPages(paged.threads);
21
+ const data = parseRawPr(raw, rawThreadPages, paged.comments, paged.changesRequested, paged.reviewSummaries, paged.approvedReviews, paged.checks);
22
+ data.checks = mergeStartupFailureChecks(data.checks, parseSuiteStartupFailures(raw));
23
+ return {
24
+ data,
25
+ rateLimit: paged.rateLimit ?? result.rateLimit,
26
+ ...(parseCheckSuitesComplete(raw) && { checkSuitesComplete: true }),
27
+ };
134
28
  }
@@ -0,0 +1,194 @@
1
+ # Follow-up pages only — skipped connections are omitted via @include so extra
2
+ # pages do not re-pay the full batch-pr.gql node cost. Outstanding cursors are
3
+ # sent together in one request.
4
+ query BatchPrPage(
5
+ $owner: String!
6
+ $repo: String!
7
+ $pr: Int!
8
+ $includeThreads: Boolean!
9
+ $threadsCursor: String
10
+ $includeComments: Boolean!
11
+ $commentsCursor: String
12
+ $includeChangesRequested: Boolean!
13
+ $changesRequestedCursor: String
14
+ $includeReviewSummaries: Boolean!
15
+ $reviewSummariesCursor: String
16
+ $includeApprovedReviews: Boolean!
17
+ $approvedReviewsCursor: String
18
+ $includeChecks: Boolean!
19
+ $checksCursor: String
20
+ ) {
21
+ repository(owner: $owner, name: $repo) {
22
+ pullRequest(number: $pr) {
23
+ reviewThreads(last: 100, before: $threadsCursor) @include(if: $includeThreads) {
24
+ pageInfo {
25
+ hasPreviousPage
26
+ startCursor
27
+ }
28
+ nodes {
29
+ id
30
+ isResolved
31
+ isOutdated
32
+ path
33
+ line
34
+ startLine
35
+ comments(first: 100) {
36
+ pageInfo {
37
+ hasNextPage
38
+ endCursor
39
+ }
40
+ nodes {
41
+ id
42
+ isMinimized
43
+ url
44
+ authorAssociation
45
+ author {
46
+ __typename
47
+ login
48
+ }
49
+ pullRequestReview {
50
+ id
51
+ }
52
+ body
53
+ path
54
+ line
55
+ startLine
56
+ createdAt
57
+ }
58
+ }
59
+ }
60
+ }
61
+ comments(last: 100, before: $commentsCursor) @include(if: $includeComments) {
62
+ pageInfo {
63
+ hasPreviousPage
64
+ startCursor
65
+ }
66
+ nodes {
67
+ id
68
+ isMinimized
69
+ url
70
+ authorAssociation
71
+ author {
72
+ __typename
73
+ login
74
+ }
75
+ body
76
+ createdAt
77
+ }
78
+ }
79
+ changesRequestedReviews: reviews(
80
+ states: CHANGES_REQUESTED
81
+ last: 50
82
+ before: $changesRequestedCursor
83
+ ) @include(if: $includeChangesRequested) {
84
+ pageInfo {
85
+ hasPreviousPage
86
+ startCursor
87
+ }
88
+ nodes {
89
+ id
90
+ authorAssociation
91
+ author {
92
+ __typename
93
+ login
94
+ }
95
+ body
96
+ createdAt
97
+ commit {
98
+ oid
99
+ }
100
+ }
101
+ }
102
+ reviewSummaries: reviews(states: COMMENTED, last: 50, before: $reviewSummariesCursor)
103
+ @include(if: $includeReviewSummaries) {
104
+ pageInfo {
105
+ hasPreviousPage
106
+ startCursor
107
+ }
108
+ nodes {
109
+ id
110
+ isMinimized
111
+ authorAssociation
112
+ author {
113
+ __typename
114
+ login
115
+ }
116
+ body
117
+ createdAt
118
+ }
119
+ }
120
+ approvedReviews: reviews(states: APPROVED, last: 50, before: $approvedReviewsCursor)
121
+ @include(if: $includeApprovedReviews) {
122
+ pageInfo {
123
+ hasPreviousPage
124
+ startCursor
125
+ }
126
+ nodes {
127
+ id
128
+ isMinimized
129
+ authorAssociation
130
+ author {
131
+ __typename
132
+ login
133
+ }
134
+ body
135
+ createdAt
136
+ }
137
+ }
138
+ commits(last: 1) @include(if: $includeChecks) {
139
+ nodes {
140
+ commit {
141
+ oid
142
+ statusCheckRollup {
143
+ contexts(first: 100, after: $checksCursor) {
144
+ pageInfo {
145
+ hasNextPage
146
+ endCursor
147
+ }
148
+ nodes {
149
+ __typename
150
+ ... on CheckRun {
151
+ id
152
+ name
153
+ status
154
+ conclusion
155
+ detailsUrl
156
+ completedAt
157
+ startedAt
158
+ title
159
+ summary
160
+ annotations(first: 1) {
161
+ nodes {
162
+ message
163
+ }
164
+ }
165
+ checkSuite {
166
+ createdAt
167
+ updatedAt
168
+ workflowRun {
169
+ event
170
+ createdAt
171
+ updatedAt
172
+ workflow {
173
+ name
174
+ databaseId
175
+ }
176
+ }
177
+ }
178
+ }
179
+ ... on StatusContext {
180
+ context
181
+ state
182
+ createdAt
183
+ targetUrl
184
+ description
185
+ }
186
+ }
187
+ }
188
+ }
189
+ }
190
+ }
191
+ }
192
+ }
193
+ }
194
+ }
@@ -1,14 +1,6 @@
1
- query BatchPr(
2
- $owner: String!
3
- $repo: String!
4
- $pr: Int!
5
- $threadsCursor: String
6
- $checksCursor: String
7
- $commentsCursor: String
8
- $changesRequestedCursor: String
9
- $reviewSummariesCursor: String
10
- $approvedReviewsCursor: String
11
- ) {
1
+ # First page only. Extra pages use batch-pr-page.gql so follow-ups do not
2
+ # re-select every connection (GraphQL points scale with possible nodes).
3
+ query BatchPr($owner: String!, $repo: String!, $pr: Int!) {
12
4
  repository(owner: $owner, name: $repo) {
13
5
  pullRequest(number: $pr) {
14
6
  id
@@ -24,13 +16,62 @@ query BatchPr(
24
16
  nameWithOwner
25
17
  }
26
18
  baseRefName
19
+ isInMergeQueue
20
+ isMergeQueueEnabled
21
+ mergeQueueEntry {
22
+ position
23
+ state
24
+ estimatedTimeToMerge
25
+ }
26
+ stack {
27
+ number
28
+ size
29
+ baseRefName
30
+ }
31
+ stackEntry {
32
+ position
33
+ }
27
34
  baseRef {
28
35
  branchProtectionRule {
29
36
  requiresApprovingReviews
30
37
  requiredApprovingReviewCount
31
38
  requiresConversationResolution
39
+ requiresCodeOwnerReviews
40
+ requireLastPushApproval
41
+ requiresCommitSignatures
42
+ requiresLinearHistory
32
43
  requiresStatusChecks
33
44
  requiredStatusCheckContexts
45
+ requiresStrictStatusChecks
46
+ requiresDeployments
47
+ requiredDeploymentEnvironments
48
+ }
49
+ rules(first: 100) {
50
+ nodes {
51
+ type
52
+ parameters {
53
+ ... on PullRequestParameters {
54
+ requiredApprovingReviewCount
55
+ requiredReviewThreadResolution
56
+ requireCodeOwnerReview
57
+ requireLastPushApproval
58
+ }
59
+ ... on RequiredStatusChecksParameters {
60
+ strictRequiredStatusChecksPolicy
61
+ requiredStatusChecks {
62
+ context
63
+ }
64
+ }
65
+ ... on RequiredDeploymentsParameters {
66
+ requiredDeploymentEnvironments
67
+ }
68
+ ... on CodeScanningParameters {
69
+ codeScanningTools {
70
+ tool
71
+ }
72
+ }
73
+ }
74
+ }
34
75
  }
35
76
  }
36
77
  # Not paginated — capped at 50; PRs with more pending reviewers truncate silently.
@@ -61,7 +102,7 @@ query BatchPr(
61
102
  state
62
103
  }
63
104
  }
64
- reviewThreads(last: 100, before: $threadsCursor) {
105
+ reviewThreads(last: 100) {
65
106
  pageInfo {
66
107
  hasPreviousPage
67
108
  startCursor
@@ -99,7 +140,7 @@ query BatchPr(
99
140
  }
100
141
  }
101
142
  }
102
- comments(last: 100, before: $commentsCursor) {
143
+ comments(last: 100) {
103
144
  pageInfo {
104
145
  hasPreviousPage
105
146
  startCursor
@@ -117,11 +158,7 @@ query BatchPr(
117
158
  createdAt
118
159
  }
119
160
  }
120
- changesRequestedReviews: reviews(
121
- states: CHANGES_REQUESTED
122
- last: 50
123
- before: $changesRequestedCursor
124
- ) {
161
+ changesRequestedReviews: reviews(states: CHANGES_REQUESTED, last: 50) {
125
162
  pageInfo {
126
163
  hasPreviousPage
127
164
  startCursor
@@ -140,7 +177,7 @@ query BatchPr(
140
177
  }
141
178
  }
142
179
  }
143
- reviewSummaries: reviews(states: COMMENTED, last: 50, before: $reviewSummariesCursor) {
180
+ reviewSummaries: reviews(states: COMMENTED, last: 50) {
144
181
  pageInfo {
145
182
  hasPreviousPage
146
183
  startCursor
@@ -160,7 +197,7 @@ query BatchPr(
160
197
  allReviews: reviews(last: 1) {
161
198
  totalCount
162
199
  }
163
- approvedReviews: reviews(states: APPROVED, last: 50, before: $approvedReviewsCursor) {
200
+ approvedReviews: reviews(states: APPROVED, last: 50) {
164
201
  pageInfo {
165
202
  hasPreviousPage
166
203
  startCursor
@@ -183,8 +220,24 @@ query BatchPr(
183
220
  commit {
184
221
  oid
185
222
  committedDate
223
+ checkSuites(first: 50) {
224
+ pageInfo {
225
+ hasNextPage
226
+ }
227
+ nodes {
228
+ conclusion
229
+ workflowRun {
230
+ databaseId
231
+ event
232
+ url
233
+ workflow {
234
+ name
235
+ }
236
+ }
237
+ }
238
+ }
186
239
  statusCheckRollup {
187
- contexts(first: 100, after: $checksCursor) {
240
+ contexts(first: 100) {
188
241
  pageInfo {
189
242
  hasNextPage
190
243
  endCursor
@@ -201,6 +254,11 @@ query BatchPr(
201
254
  startedAt
202
255
  title
203
256
  summary
257
+ annotations(first: 1) {
258
+ nodes {
259
+ message
260
+ }
261
+ }
204
262
  checkSuite {
205
263
  createdAt
206
264
  updatedAt
@@ -0,0 +1,40 @@
1
+ query CommitSuggestionThread($owner: String!, $repo: String!, $pr: Int!, $threadId: ID!) {
2
+ repository(owner: $owner, name: $repo) {
3
+ pullRequest(number: $pr) {
4
+ headRefOid
5
+ headRefName
6
+ headRepository {
7
+ nameWithOwner
8
+ }
9
+ }
10
+ }
11
+ node(id: $threadId) {
12
+ ... on PullRequestReviewThread {
13
+ id
14
+ isResolved
15
+ isOutdated
16
+ path
17
+ line
18
+ startLine
19
+ pullRequest {
20
+ number
21
+ }
22
+ comments(first: 1) {
23
+ nodes {
24
+ isMinimized
25
+ url
26
+ authorAssociation
27
+ author {
28
+ __typename
29
+ login
30
+ }
31
+ body
32
+ path
33
+ line
34
+ startLine
35
+ createdAt
36
+ }
37
+ }
38
+ }
39
+ }
40
+ }
@@ -1,5 +1,6 @@
1
1
  export { GitHubRequestError } from "./errors.mts";
2
2
  export { _resetTokenCache } from "./http-auth.mts";
3
3
  export { graphql, graphqlWithRateLimit } from "./graphql-http.mts";
4
- export { rest, restText } from "./rest-http.mts";
4
+ export { rest, restWithRateLimit } from "./rest-http.mts";
5
+ export { restText } from "./rest-text.mts";
5
6
  export type { RateLimitInfo } from "./http-utils.mts";
@@ -1,4 +1,5 @@
1
1
  export { GitHubRequestError } from "./errors.mjs";
2
2
  export { _resetTokenCache } from "./http-auth.mjs";
3
3
  export { graphql, graphqlWithRateLimit } from "./graphql-http.mjs";
4
- export { rest, restText } from "./rest-http.mjs";
4
+ export { rest, restWithRateLimit } from "./rest-http.mjs";
5
+ export { restText } from "./rest-text.mjs";
@@ -6,8 +6,9 @@
6
6
  * that returns pages of fake data.
7
7
  *
8
8
  * GitHub's GraphQL connections support two cursor directions:
9
- * - Forward (`after` + `first`) — used by check contexts.
10
- * - Backward (`before` + `last`) — used by reviewThreads (default GitHub order).
9
+ * - Forward (`after` + `first`) — used by check contexts and nested thread comments.
10
+ * - Backward (`before` + `last`) — used by reviewThreads/comments/reviews extra pages
11
+ * (combined in `batch-page.mts`; `paginateBackward` remains the generic primitive).
11
12
  */
12
13
  interface PageInfo {
13
14
  hasNextPage?: boolean;
@@ -6,8 +6,9 @@
6
6
  * that returns pages of fake data.
7
7
  *
8
8
  * GitHub's GraphQL connections support two cursor directions:
9
- * - Forward (`after` + `first`) — used by check contexts.
10
- * - Backward (`before` + `last`) — used by reviewThreads (default GitHub order).
9
+ * - Forward (`after` + `first`) — used by check contexts and nested thread comments.
10
+ * - Backward (`before` + `last`) — used by reviewThreads/comments/reviews extra pages
11
+ * (combined in `batch-page.mts`; `paginateBackward` remains the generic primitive).
11
12
  */
12
13
  /**
13
14
  * Paginate forward through a GraphQL connection (`first` / `after` cursors).
@@ -8,6 +8,10 @@
8
8
  */
9
9
  /** The primary batch query that fetches CI + comments + merge status in one round-trip. */
10
10
  export declare const BATCH_PR_QUERY: string;
11
+ /** Slim @include follow-up for outstanding batch-query connections. */
12
+ export declare const BATCH_PR_PAGE_QUERY: string;
13
+ /** PR head fields plus a single review thread for `commit-suggestion`. */
14
+ export declare const COMMIT_SUGGESTION_THREAD_QUERY: string;
11
15
  /** Fetches additional comments for a single review thread when its nested connection paginates. */
12
16
  export declare const REVIEW_THREAD_COMMENTS_QUERY: string;
13
17
  /** Fetch inline annotations for a single CheckRun by node ID. */
@@ -11,6 +11,10 @@ import { join } from "node:path";
11
11
  const gql = (name) => readFileSync(join(import.meta.dirname, "gql", name), "utf8");
12
12
  /** The primary batch query that fetches CI + comments + merge status in one round-trip. */
13
13
  export const BATCH_PR_QUERY = gql("batch-pr.gql");
14
+ /** Slim @include follow-up for outstanding batch-query connections. */
15
+ export const BATCH_PR_PAGE_QUERY = gql("batch-pr-page.gql");
16
+ /** PR head fields plus a single review thread for `commit-suggestion`. */
17
+ export const COMMIT_SUGGESTION_THREAD_QUERY = gql("commit-suggestion-thread.gql");
14
18
  /** Fetches additional comments for a single review thread when its nested connection paginates. */
15
19
  export const REVIEW_THREAD_COMMENTS_QUERY = gql("review-thread-comments.gql");
16
20
  /** Fetch inline annotations for a single CheckRun by node ID. */
@@ -1,2 +1,7 @@
1
+ import { type RateLimitInfo } from "./http-utils.mts";
2
+ export interface RestResult<T = unknown> {
3
+ data: T;
4
+ rateLimit?: RateLimitInfo;
5
+ }
1
6
  export declare function rest<T = unknown>(method: string, path: string, body?: unknown): Promise<T>;
2
- export declare function restText(path: string): Promise<string>;
7
+ export declare function restWithRateLimit<T = unknown>(method: string, path: string, body?: unknown): Promise<RestResult<T>>;