pr-shepherd 0.56.6 → 0.57.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 (420) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/README.md +44 -27
  3. package/bin/api.d.mts +25 -3
  4. package/bin/api.mjs +51 -13
  5. package/bin/checks/classify.d.mts +1 -0
  6. package/bin/checks/classify.mjs +1 -1
  7. package/bin/checks/conclusions.d.mts +5 -1
  8. package/bin/checks/conclusions.mjs +8 -2
  9. package/bin/checks/superseded.d.mts +8 -2
  10. package/bin/checks/superseded.mjs +24 -7
  11. package/bin/classify/loader.d.mts +2 -0
  12. package/bin/classify/loader.mjs +15 -0
  13. package/bin/classify/standard/author.d.mts +3 -0
  14. package/bin/classify/standard/author.mjs +10 -0
  15. package/bin/classify/standard/codecov-report.d.mts +4 -0
  16. package/bin/classify/standard/codecov-report.mjs +10 -0
  17. package/bin/classify/standard/coderabbit-notices.d.mts +8 -0
  18. package/bin/classify/standard/coderabbit-notices.mjs +38 -0
  19. package/bin/classify/standard/coderabbit-review-summary.d.mts +8 -0
  20. package/bin/classify/standard/coderabbit-review-summary.mjs +37 -0
  21. package/bin/classify/standard/codex-notices.d.mts +7 -0
  22. package/bin/classify/standard/codex-notices.mjs +36 -0
  23. package/bin/classify/standard/codex-review-summary.d.mts +7 -0
  24. package/bin/classify/standard/codex-review-summary.mjs +20 -0
  25. package/bin/classify/standard/dependabot-notices.d.mts +4 -0
  26. package/bin/classify/standard/dependabot-notices.mjs +15 -0
  27. package/bin/classify/standard/gemini-notices.d.mts +4 -0
  28. package/bin/classify/standard/gemini-notices.mjs +13 -0
  29. package/bin/classify/standard/index.d.mts +4 -0
  30. package/bin/classify/standard/index.mjs +22 -0
  31. package/bin/classify/standard/kilo-no-issues.d.mts +4 -0
  32. package/bin/classify/standard/kilo-no-issues.mjs +17 -0
  33. package/bin/classify/standard/sourcery-notices.d.mts +8 -0
  34. package/bin/classify/standard/sourcery-notices.mjs +20 -0
  35. package/bin/cli/api-usage-formatter.mjs +6 -1
  36. package/bin/cli/apply-merge-handler.d.mts +3 -0
  37. package/bin/cli/apply-merge-handler.mjs +73 -0
  38. package/bin/cli/arg-flags.d.mts +2 -0
  39. package/bin/cli/arg-flags.mjs +47 -0
  40. package/bin/cli/args.mjs +10 -41
  41. package/bin/cli/clean-handler.d.mts +1 -0
  42. package/bin/cli/clean-handler.mjs +71 -0
  43. package/bin/cli/default-poll.mjs +3 -0
  44. package/bin/cli/event-state-scope.d.mts +19 -0
  45. package/bin/cli/event-state-scope.mjs +60 -0
  46. package/bin/cli/fix-formatter.mjs +5 -11
  47. package/bin/cli/handlers.d.mts +0 -1
  48. package/bin/cli/handlers.mjs +8 -64
  49. package/bin/cli/help-command-pages.d.mts +62 -18
  50. package/bin/cli/help-command-pages.mjs +59 -15
  51. package/bin/cli/help-iterate-poll-pages.d.mts +2 -2
  52. package/bin/cli/help-iterate-poll-pages.mjs +6 -0
  53. package/bin/cli/help-log-file-page.d.mts +1 -1
  54. package/bin/cli/help-log-file-page.mjs +4 -1
  55. package/bin/cli/help-top-page.d.mts +1 -1
  56. package/bin/cli/help-top-page.mjs +5 -0
  57. package/bin/cli/help.d.mts +63 -19
  58. package/bin/cli/help.mjs +2 -0
  59. package/bin/cli/iterate-branch-segment.d.mts +2 -0
  60. package/bin/cli/iterate-branch-segment.mjs +12 -7
  61. package/bin/cli/iterate-flags.d.mts +7 -1
  62. package/bin/cli/iterate-flags.mjs +38 -0
  63. package/bin/cli/iterate-formatter.d.mts +6 -6
  64. package/bin/cli/iterate-formatter.mjs +56 -22
  65. package/bin/cli/iterate-instructions.mjs +45 -15
  66. package/bin/cli/iterate-lean.mjs +39 -14
  67. package/bin/cli/iterate-merge-formatter.d.mts +6 -0
  68. package/bin/cli/iterate-merge-formatter.mjs +24 -14
  69. package/bin/cli/iterate-verbose.mjs +3 -6
  70. package/bin/cli/list-formatters.mjs +3 -1
  71. package/bin/cli/mutate-formatter.mjs +10 -5
  72. package/bin/cli/next-check-format.d.mts +7 -0
  73. package/bin/cli/next-check-format.mjs +10 -0
  74. package/bin/cli/playbook-handler.d.mts +5 -0
  75. package/bin/cli/playbook-handler.mjs +40 -0
  76. package/bin/cli/poll-handler.mjs +7 -6
  77. package/bin/cli/poll-summary-formatter.mjs +11 -2
  78. package/bin/cli/poll-targets.mjs +2 -0
  79. package/bin/cli/resolve-validators.mjs +2 -2
  80. package/bin/cli/runner.mjs +6 -1
  81. package/bin/cli/stack-layer-view.d.mts +33 -0
  82. package/bin/cli/stack-layer-view.mjs +1 -0
  83. package/bin/cli/stack-overview.d.mts +10 -28
  84. package/bin/cli/stack-overview.mjs +39 -14
  85. package/bin/cli/transport-args.d.mts +5 -0
  86. package/bin/cli/transport-args.mjs +23 -0
  87. package/bin/cli/transport-formatter.d.mts +9 -0
  88. package/bin/cli/transport-formatter.mjs +13 -0
  89. package/bin/cli-parser.mjs +62 -7
  90. package/bin/commands/apply-merge-options.d.mts +4 -0
  91. package/bin/commands/apply-merge-options.mjs +34 -0
  92. package/bin/commands/apply-merge-output.d.mts +7 -0
  93. package/bin/commands/apply-merge-output.mjs +20 -0
  94. package/bin/commands/apply-merge-pull.d.mts +20 -0
  95. package/bin/commands/apply-merge-pull.mjs +15 -0
  96. package/bin/commands/apply-merge.d.mts +18 -0
  97. package/bin/commands/apply-merge.mjs +126 -0
  98. package/bin/commands/apply-queue-removal.mjs +7 -0
  99. package/bin/commands/check-annotations.mjs +28 -18
  100. package/bin/commands/check-execution-context.d.mts +5 -0
  101. package/bin/commands/check-execution-context.mjs +16 -1
  102. package/bin/commands/check-fingerprint.d.mts +26 -2
  103. package/bin/commands/check-fingerprint.mjs +64 -28
  104. package/bin/commands/check-terminal-report.mjs +11 -1
  105. package/bin/commands/check-unreported.d.mts +6 -2
  106. package/bin/commands/check-unreported.mjs +32 -12
  107. package/bin/commands/check-wait-detectors.d.mts +35 -0
  108. package/bin/commands/check-wait-detectors.mjs +107 -0
  109. package/bin/commands/check.d.mts +4 -2
  110. package/bin/commands/check.mjs +130 -40
  111. package/bin/commands/event-instructions.d.mts +11 -0
  112. package/bin/commands/event-instructions.mjs +27 -0
  113. package/bin/commands/event-mode.d.mts +14 -0
  114. package/bin/commands/event-mode.mjs +138 -0
  115. package/bin/commands/iterate/api-usage.mjs +4 -2
  116. package/bin/commands/iterate/base.mjs +4 -0
  117. package/bin/commands/iterate/check-blocker-gate.mjs +14 -2
  118. package/bin/commands/iterate/check-instructions.d.mts +9 -10
  119. package/bin/commands/iterate/check-instructions.mjs +23 -22
  120. package/bin/commands/iterate/classify.mjs +19 -5
  121. package/bin/commands/iterate/escalate.mjs +13 -3
  122. package/bin/commands/iterate/fix-code.mjs +26 -9
  123. package/bin/commands/iterate/fix-instruction-threads.d.mts +0 -8
  124. package/bin/commands/iterate/fix-instruction-threads.mjs +0 -16
  125. package/bin/commands/iterate/fix-loop-instruction.d.mts +9 -0
  126. package/bin/commands/iterate/fix-loop-instruction.mjs +35 -0
  127. package/bin/commands/iterate/helpers.mjs +15 -2
  128. package/bin/commands/iterate/index.mjs +26 -4
  129. package/bin/commands/iterate/mark-ready.mjs +50 -10
  130. package/bin/commands/iterate/merge-plan.d.mts +19 -0
  131. package/bin/commands/iterate/merge-plan.mjs +88 -0
  132. package/bin/commands/iterate/merge-state.mjs +3 -0
  133. package/bin/commands/iterate/merge.d.mts +4 -15
  134. package/bin/commands/iterate/merge.mjs +18 -51
  135. package/bin/commands/iterate/merged-base-pull-requests.d.mts +2 -6
  136. package/bin/commands/iterate/merged-base-pull-requests.mjs +15 -11
  137. package/bin/commands/iterate/native-stack-rebase.mjs +11 -0
  138. package/bin/commands/iterate/render.d.mts +8 -2
  139. package/bin/commands/iterate/render.mjs +28 -42
  140. package/bin/commands/iterate/stack-trunk-conflict.mjs +17 -1
  141. package/bin/commands/iterate/stale-ancestry.mjs +4 -1
  142. package/bin/commands/iterate/stall.d.mts +5 -1
  143. package/bin/commands/iterate/stall.mjs +19 -7
  144. package/bin/commands/iterate/thread-mutation-routing.d.mts +1 -0
  145. package/bin/commands/iterate/thread-mutation-routing.mjs +4 -2
  146. package/bin/commands/iterate/unreported-required.mjs +5 -2
  147. package/bin/commands/mark-files-as-viewed.mjs +7 -0
  148. package/bin/commands/next-check.d.mts +31 -0
  149. package/bin/commands/next-check.mjs +46 -0
  150. package/bin/commands/playbook.d.mts +13 -0
  151. package/bin/commands/playbook.mjs +48 -0
  152. package/bin/commands/poll-mode.d.mts +8 -0
  153. package/bin/commands/poll-mode.mjs +14 -0
  154. package/bin/commands/poll-progress.d.mts +1 -0
  155. package/bin/commands/poll-progress.mjs +6 -3
  156. package/bin/commands/poll-quota.d.mts +3 -2
  157. package/bin/commands/poll-quota.mjs +7 -3
  158. package/bin/commands/poll-summary-explicit-instructions.d.mts +2 -0
  159. package/bin/commands/poll-summary-explicit-instructions.mjs +10 -1
  160. package/bin/commands/poll-summary-instructions.mjs +16 -17
  161. package/bin/commands/poll-summary.mjs +42 -17
  162. package/bin/commands/poll.d.mts +0 -1
  163. package/bin/commands/poll.mjs +11 -19
  164. package/bin/commands/quota-selection.d.mts +2 -1
  165. package/bin/commands/quota-selection.mjs +12 -7
  166. package/bin/commands/resolve-mutate.mjs +33 -5
  167. package/bin/commands/rest-stack-merge-readiness.d.mts +4 -0
  168. package/bin/commands/rest-stack-merge-readiness.mjs +74 -0
  169. package/bin/commands/rule-auto-resolve.mjs +9 -3
  170. package/bin/commands/shepherd-journal.d.mts +5 -4
  171. package/bin/commands/shepherd-journal.mjs +9 -8
  172. package/bin/commands/stack-drain.d.mts +1 -9
  173. package/bin/commands/stack-drain.mjs +50 -37
  174. package/bin/commands/stack-handoffs.d.mts +10 -0
  175. package/bin/commands/stack-handoffs.mjs +25 -0
  176. package/bin/commands/stack-stall.d.mts +5 -0
  177. package/bin/commands/stack-stall.mjs +11 -0
  178. package/bin/commands/stack-work.d.mts +5 -0
  179. package/bin/commands/stack-work.mjs +32 -0
  180. package/bin/comments/existing-reply-scan.d.mts +17 -0
  181. package/bin/comments/existing-reply-scan.mjs +41 -0
  182. package/bin/comments/rate-limit.mjs +2 -2
  183. package/bin/comments/resolve.d.mts +7 -1
  184. package/bin/comments/resolve.mjs +108 -18
  185. package/bin/comments/rest-reply.d.mts +9 -0
  186. package/bin/comments/rest-reply.mjs +95 -0
  187. package/bin/comments/rest-review-mutations.d.mts +22 -0
  188. package/bin/comments/rest-review-mutations.mjs +125 -0
  189. package/bin/comments/review-visibility.d.mts +1 -1
  190. package/bin/comments/review-visibility.mjs +3 -2
  191. package/bin/comments/sha-poll.mjs +7 -3
  192. package/bin/comments/thread-visibility.mjs +10 -5
  193. package/bin/comments/uncertain-replies.d.mts +11 -0
  194. package/bin/comments/uncertain-replies.mjs +121 -0
  195. package/bin/comments/uncertain-reply-guards.d.mts +10 -0
  196. package/bin/comments/uncertain-reply-guards.mjs +94 -0
  197. package/bin/comments/visible-comments.d.mts +1 -1
  198. package/bin/comments/visible-comments.mjs +4 -2
  199. package/bin/config/load.d.mts +37 -1
  200. package/bin/config/load.mjs +73 -1
  201. package/bin/config.json +6 -2
  202. package/bin/exit-codes.d.mts +3 -0
  203. package/bin/exit-codes.mjs +8 -0
  204. package/bin/github/api-telemetry-aggregate.d.mts +15 -4
  205. package/bin/github/api-telemetry-aggregate.mjs +57 -18
  206. package/bin/github/api-telemetry.d.mts +4 -0
  207. package/bin/github/api-telemetry.mjs +22 -8
  208. package/bin/github/apply-review-preflight.d.mts +20 -0
  209. package/bin/github/apply-review-preflight.mjs +61 -0
  210. package/bin/github/base-behind-cache.d.mts +15 -0
  211. package/bin/github/base-behind-cache.mjs +18 -0
  212. package/bin/github/batch-parse-suites.d.mts +4 -2
  213. package/bin/github/batch-parse-suites.mjs +6 -1
  214. package/bin/github/batch-parser-helpers.mjs +40 -2
  215. package/bin/github/batch-parsers.mjs +1 -0
  216. package/bin/github/batch-raw-rules.d.mts +26 -0
  217. package/bin/github/batch-raw-types.d.mts +8 -6
  218. package/bin/github/batch-stack-evidence.d.mts +28 -0
  219. package/bin/github/batch-stack-evidence.mjs +62 -0
  220. package/bin/github/batch.d.mts +15 -2
  221. package/bin/github/batch.mjs +34 -17
  222. package/bin/github/check-annotations-batch.d.mts +0 -5
  223. package/bin/github/check-annotations-batch.mjs +25 -4
  224. package/bin/github/check-annotations.mjs +3 -1
  225. package/bin/github/client.d.mts +8 -19
  226. package/bin/github/client.mjs +45 -13
  227. package/bin/github/fingerprint-fields.d.mts +8 -0
  228. package/bin/github/fingerprint-fields.mjs +6 -1
  229. package/bin/github/fingerprint.d.mts +4 -2
  230. package/bin/github/fingerprint.mjs +6 -38
  231. package/bin/github/github-fetch.d.mts +2 -0
  232. package/bin/github/github-fetch.mjs +19 -0
  233. package/bin/github/gql/base-behind.gql +3 -0
  234. package/bin/github/gql/batch-pr-page.gql +16 -0
  235. package/bin/github/gql/batch-pr.gql +57 -0
  236. package/bin/github/gql/commit-check-contexts.gql +17 -0
  237. package/bin/github/gql/get-pr-body.gql +1 -0
  238. package/bin/github/gql/poll-stack-summary.gql +1 -0
  239. package/bin/github/gql/poll-summary-check-contexts.gql +5 -0
  240. package/bin/github/gql/poll-summary-fragment.gql +65 -15
  241. package/bin/github/gql/stack-handoff-check-runs.gql +42 -0
  242. package/bin/github/graphql-http.mjs +9 -4
  243. package/bin/github/graphql-internal-retry.d.mts +2 -0
  244. package/bin/github/graphql-internal-retry.mjs +1 -1
  245. package/bin/github/graphql-quota-probe.d.mts +6 -0
  246. package/bin/github/graphql-quota-probe.mjs +56 -0
  247. package/bin/github/graphql-session-refusal.d.mts +8 -0
  248. package/bin/github/graphql-session-refusal.mjs +14 -0
  249. package/bin/github/http-request.d.mts +1 -1
  250. package/bin/github/http-request.mjs +22 -6
  251. package/bin/github/http-utils.mjs +6 -0
  252. package/bin/github/merge-target-rules.d.mts +12 -3
  253. package/bin/github/merge-target-rules.mjs +71 -34
  254. package/bin/github/mutation-policy.d.mts +6 -0
  255. package/bin/github/mutation-policy.mjs +21 -0
  256. package/bin/github/poll-summary-annotation-probe.mjs +17 -10
  257. package/bin/github/poll-summary-check-blockers.d.mts +1 -1
  258. package/bin/github/poll-summary-check-blockers.mjs +2 -2
  259. package/bin/github/poll-summary-check-hydration.mjs +25 -10
  260. package/bin/github/poll-summary-checks.d.mts +2 -2
  261. package/bin/github/poll-summary-checks.mjs +9 -6
  262. package/bin/github/poll-summary-command.d.mts +2 -0
  263. package/bin/github/poll-summary-command.mjs +24 -0
  264. package/bin/github/poll-summary-fingerprint.d.mts +1 -1
  265. package/bin/github/poll-summary-fingerprint.mjs +4 -2
  266. package/bin/github/poll-summary-handoff-fields.d.mts +3 -0
  267. package/bin/github/poll-summary-handoff-fields.mjs +73 -0
  268. package/bin/github/poll-summary-projector.d.mts +1 -1
  269. package/bin/github/poll-summary-projector.mjs +17 -24
  270. package/bin/github/poll-summary-raw.d.mts +70 -10
  271. package/bin/github/poll-summary-readiness.mjs +4 -1
  272. package/bin/github/poll-summary-rest-queue.d.mts +3 -0
  273. package/bin/github/poll-summary-rest-queue.mjs +12 -0
  274. package/bin/github/poll-summary-review.d.mts +1 -1
  275. package/bin/github/poll-summary-review.mjs +23 -11
  276. package/bin/github/poll-summary-route.mjs +19 -3
  277. package/bin/github/poll-summary-stack-page.d.mts +11 -0
  278. package/bin/github/poll-summary-stack-page.mjs +27 -0
  279. package/bin/github/poll-summary-unreported.d.mts +3 -1
  280. package/bin/github/poll-summary-unreported.mjs +6 -3
  281. package/bin/github/poll-summary.d.mts +4 -1
  282. package/bin/github/poll-summary.mjs +47 -33
  283. package/bin/github/queries.d.mts +7 -3
  284. package/bin/github/queries.mjs +8 -4
  285. package/bin/github/rate-limit-sample.d.mts +7 -0
  286. package/bin/github/rate-limit-sample.mjs +12 -0
  287. package/bin/github/reply-recovery-read.d.mts +50 -0
  288. package/bin/github/reply-recovery-read.mjs +118 -0
  289. package/bin/github/reply-thread-transcripts.d.mts +0 -1
  290. package/bin/github/reply-thread-transcripts.mjs +24 -1
  291. package/bin/github/rest-annotation-read.d.mts +5 -0
  292. package/bin/github/rest-annotation-read.mjs +44 -0
  293. package/bin/github/rest-batch-read.d.mts +12 -0
  294. package/bin/github/rest-batch-read.mjs +57 -0
  295. package/bin/github/rest-batch-snapshot.d.mts +30 -0
  296. package/bin/github/rest-batch-snapshot.mjs +115 -0
  297. package/bin/github/rest-batch-unavailable.d.mts +5 -0
  298. package/bin/github/rest-batch-unavailable.mjs +16 -0
  299. package/bin/github/rest-check-read.d.mts +34 -0
  300. package/bin/github/rest-check-read.mjs +124 -0
  301. package/bin/github/rest-comment-authorship.d.mts +7 -0
  302. package/bin/github/rest-comment-authorship.mjs +11 -0
  303. package/bin/github/rest-conditional-scope.d.mts +20 -0
  304. package/bin/github/rest-conditional-scope.mjs +44 -0
  305. package/bin/github/rest-explicit-summary-read.d.mts +3 -0
  306. package/bin/github/rest-explicit-summary-read.mjs +8 -0
  307. package/bin/github/rest-feedback-read.d.mts +36 -0
  308. package/bin/github/rest-feedback-read.mjs +147 -0
  309. package/bin/github/rest-feedback-validation.d.mts +5 -0
  310. package/bin/github/rest-feedback-validation.mjs +28 -0
  311. package/bin/github/rest-http.d.mts +12 -0
  312. package/bin/github/rest-http.mjs +108 -23
  313. package/bin/github/rest-identities.d.mts +22 -0
  314. package/bin/github/rest-identities.mjs +134 -0
  315. package/bin/github/rest-merge-stack-guard.d.mts +14 -0
  316. package/bin/github/rest-merge-stack-guard.mjs +41 -0
  317. package/bin/github/rest-merge.d.mts +29 -0
  318. package/bin/github/rest-merge.mjs +56 -0
  319. package/bin/github/rest-merged-base-read.d.mts +9 -0
  320. package/bin/github/rest-merged-base-read.mjs +48 -0
  321. package/bin/github/rest-pr-core.d.mts +52 -0
  322. package/bin/github/rest-pr-core.mjs +60 -0
  323. package/bin/github/rest-reader-core.d.mts +16 -0
  324. package/bin/github/rest-reader-core.mjs +154 -0
  325. package/bin/github/rest-review-read.d.mts +11 -0
  326. package/bin/github/rest-review-read.mjs +47 -0
  327. package/bin/github/rest-rules-read.d.mts +9 -0
  328. package/bin/github/rest-rules-read.mjs +154 -0
  329. package/bin/github/rest-session-refusal.d.mts +5 -0
  330. package/bin/github/rest-session-refusal.mjs +21 -0
  331. package/bin/github/rest-snapshot-context.d.mts +10 -0
  332. package/bin/github/rest-snapshot-context.mjs +1 -0
  333. package/bin/github/rest-stack-read.d.mts +21 -0
  334. package/bin/github/rest-stack-read.mjs +47 -0
  335. package/bin/github/rest-stack-summary.d.mts +8 -0
  336. package/bin/github/rest-stack-summary.mjs +62 -0
  337. package/bin/github/rest-summary-read.d.mts +7 -0
  338. package/bin/github/rest-summary-read.mjs +112 -0
  339. package/bin/github/rest-terminal-batch.d.mts +14 -0
  340. package/bin/github/rest-terminal-batch.mjs +45 -0
  341. package/bin/github/rest-text.mjs +7 -3
  342. package/bin/github/rest-thread-read.d.mts +4 -0
  343. package/bin/github/rest-thread-read.mjs +35 -0
  344. package/bin/github/rest-viewer-read.d.mts +2 -0
  345. package/bin/github/rest-viewer-read.mjs +41 -0
  346. package/bin/github/stack-bottom.d.mts +3 -0
  347. package/bin/github/stack-bottom.mjs +14 -0
  348. package/bin/github/stack-handoff-context.d.mts +25 -0
  349. package/bin/github/stack-handoff-context.mjs +12 -0
  350. package/bin/github/stack-handoff-page.d.mts +17 -0
  351. package/bin/github/stack-handoff-page.mjs +306 -0
  352. package/bin/github/stack-handoff.d.mts +16 -0
  353. package/bin/github/stack-handoff.mjs +115 -0
  354. package/bin/github/stack-order.d.mts +6 -0
  355. package/bin/github/stack-order.mjs +13 -0
  356. package/bin/github/stack-read.d.mts +7 -5
  357. package/bin/github/stack-read.mjs +22 -24
  358. package/bin/github/stack-size-hint.d.mts +3 -0
  359. package/bin/github/stack-size-hint.mjs +14 -0
  360. package/bin/github/suggestion-thread.mjs +27 -1
  361. package/bin/github/thread-comments.mjs +9 -1
  362. package/bin/github/transport-evidence.d.mts +20 -0
  363. package/bin/github/transport-evidence.mjs +26 -0
  364. package/bin/github/transport-mode.d.mts +2 -0
  365. package/bin/github/transport-mode.mjs +5 -0
  366. package/bin/github/transport.d.mts +19 -0
  367. package/bin/github/transport.mjs +126 -0
  368. package/bin/github/unsupported-rest.d.mts +4 -0
  369. package/bin/github/unsupported-rest.mjs +7 -0
  370. package/bin/mcp/server.mjs +52 -3
  371. package/bin/merge-status/derive.d.mts +2 -0
  372. package/bin/merge-status/derive.mjs +17 -13
  373. package/bin/merge-status/required-check-requirements.d.mts +7 -0
  374. package/bin/merge-status/required-check-requirements.mjs +15 -0
  375. package/bin/merge-status/requirements-format.d.mts +5 -0
  376. package/bin/merge-status/requirements-format.mjs +41 -12
  377. package/bin/merge-status/requirements.mjs +18 -7
  378. package/bin/state/base.mjs +41 -0
  379. package/bin/state/durable-state.d.mts +6 -0
  380. package/bin/state/durable-state.mjs +41 -0
  381. package/bin/state/graphql-quota-policy.mjs +23 -16
  382. package/bin/state/merge-request.d.mts +25 -0
  383. package/bin/state/merge-request.mjs +145 -0
  384. package/bin/state/pr-fingerprint.d.mts +15 -0
  385. package/bin/state/pr-fingerprint.mjs +22 -7
  386. package/bin/state/rest-cache.d.mts +3 -0
  387. package/bin/state/rest-cache.mjs +1 -0
  388. package/bin/state/rest-snapshot-report.d.mts +21 -0
  389. package/bin/state/rest-snapshot-report.mjs +52 -0
  390. package/bin/state/seen-comments.d.mts +3 -0
  391. package/bin/state/seen-comments.mjs +18 -0
  392. package/bin/types/api-usage.d.mts +9 -1
  393. package/bin/types/escalate.d.mts +1 -1
  394. package/bin/types/github.d.mts +23 -9
  395. package/bin/types/iterate.d.mts +24 -2
  396. package/bin/types/merge-action.d.mts +1 -1
  397. package/bin/types/merge-requirements.d.mts +7 -7
  398. package/bin/types/next-check.d.mts +12 -0
  399. package/bin/types/next-check.mjs +1 -0
  400. package/bin/types/poll-summary.d.mts +21 -0
  401. package/bin/types/report.d.mts +13 -1
  402. package/bin/types/review-thread.d.mts +1 -1
  403. package/bin/types.d.mts +1 -0
  404. package/bin/types.mjs +1 -0
  405. package/package.json +3 -2
  406. package/plugins/pr-shepherd/.codex-plugin/plugin.json +1 -1
  407. package/plugins/pr-shepherd/.codex.mcp.json +1 -1
  408. package/plugins/pr-shepherd/.mcp.json +1 -1
  409. package/plugins/pr-shepherd/skills/mark-files-as-viewed/SKILL.md +1 -1
  410. package/plugins/pr-shepherd/skills/pr-shepherd/SKILL.md +14 -51
  411. package/plugins/pr-shepherd/skills/pr-shepherd/references/ci-failure-triage.md +12 -16
  412. package/plugins/pr-shepherd/skills/pr-shepherd/references/cloud-event-loop.md +14 -0
  413. package/plugins/pr-shepherd/skills/pr-shepherd/references/create-pr.md +10 -0
  414. package/plugins/pr-shepherd/skills/pr-shepherd/references/fix-code-loop.md +10 -0
  415. package/plugins/pr-shepherd/skills/pr-shepherd/references/mcp-fallback.md +9 -0
  416. package/plugins/pr-shepherd/skills/reduce-pr-noise/references/classifiers.md +2 -0
  417. package/bin/github/gql/pr-fingerprint.gql +0 -75
  418. package/plugins/pr-shepherd/skills/pr-shepherd/references/journal.md +0 -7
  419. package/plugins/pr-shepherd/skills/pr-shepherd/references/review-mutations.md +0 -9
  420. package/plugins/pr-shepherd/skills/pr-shepherd/references/stack-merge.md +0 -7
@@ -1,3 +1,5 @@
1
+ import { githubOperation } from "./transport.mjs";
2
+ import { readRestAnnotationCounts } from "./rest-check-read.mjs";
1
3
  import { graphqlWithRateLimit } from "./client.mjs";
2
4
  import { isCurrentSummaryReady } from "./poll-summary-readiness.mjs";
3
5
  import { summarizePollSummaryChecks } from "./poll-summary-checks.mjs";
@@ -78,16 +80,21 @@ async function collectProbePages(oid, repo) {
78
80
  }
79
81
  async function fetchProbePage(oid, repo, before) {
80
82
  try {
81
- const { data } = await graphqlWithRateLimit(POLL_SUMMARY_ANNOTATION_PROBE_QUERY, {
82
- owner: repo.owner,
83
- repo: repo.name,
84
- oid,
85
- before,
86
- });
87
- const object = data.repository?.object;
88
- if (object?.__typename !== "Commit" || object.oid !== oid)
89
- return null;
90
- return object.statusCheckRollup?.contexts ?? null;
83
+ return await githubOperation("PollSummaryAnnotationProbe", async () => {
84
+ const { data } = await graphqlWithRateLimit(POLL_SUMMARY_ANNOTATION_PROBE_QUERY, {
85
+ owner: repo.owner,
86
+ repo: repo.name,
87
+ oid,
88
+ before,
89
+ });
90
+ const object = data.repository?.object;
91
+ if (object?.__typename !== "Commit" || object.oid !== oid)
92
+ return null;
93
+ return object.statusCheckRollup?.contexts ?? null;
94
+ }, async () => ({
95
+ pageInfo: { hasPreviousPage: false, startCursor: null },
96
+ nodes: await readRestAnnotationCounts(oid, repo),
97
+ }));
91
98
  }
92
99
  catch {
93
100
  return null;
@@ -10,7 +10,7 @@ type Routed = Pick<PollSummaryItem, "action" | "reasons">;
10
10
  export declare function applyOpenCheckBlockers(raw: RawSummaryPr, repo: {
11
11
  owner: string;
12
12
  name: string;
13
- }, routed: Routed, checks: PollSummaryChecks, review: PollSummaryReview, stack: boolean): Promise<Routed & {
13
+ }, routed: Routed, checks: PollSummaryChecks, review: PollSummaryReview, stack: boolean, requiredContexts?: readonly string[]): Promise<Routed & {
14
14
  pollProbe?: true;
15
15
  }>;
16
16
  export {};
@@ -6,12 +6,12 @@ import { failingSummaryCheckNames } from "./poll-summary-checks.mjs";
6
6
  * deferred stay on the routed action. Stack rows are probed so the planner
7
7
  * does not start a one-PR session for a wait it would otherwise shepherd.
8
8
  */
9
- export async function applyOpenCheckBlockers(raw, repo, routed, checks, review, stack) {
9
+ export async function applyOpenCheckBlockers(raw, repo, routed, checks, review, stack, requiredContexts) {
10
10
  if (routed.action !== "fix_code" || !routed.reasons.includes("failing-checks"))
11
11
  return routed;
12
12
  if ((review.actionable ?? 0) > 0 || checks.incomplete)
13
13
  return routed;
14
- const names = failingSummaryCheckNames(raw);
14
+ const names = failingSummaryCheckNames(raw, requiredContexts);
15
15
  if (names.length === 0)
16
16
  return routed;
17
17
  const gate = await resolveCheckBlockerGate({ owner: repo.owner, repo: repo.name, pr: raw.number }, names.map((name) => ({ name })));
@@ -1,3 +1,5 @@
1
+ import { githubOperation } from "./transport.mjs";
2
+ import { readRestCommitChecks } from "./rest-check-read.mjs";
1
3
  import { graphqlWithRateLimit } from "./client.mjs";
2
4
  import { POLL_SUMMARY_CHECK_PAGE_QUERY } from "./queries.mjs";
3
5
  /**
@@ -27,7 +29,10 @@ async function hydrateCommitContexts(commit, repo) {
27
29
  const older = await fetchOlderContexts(commit.oid, pageInfo.startCursor, repo);
28
30
  if (!older)
29
31
  break;
30
- nodes.unshift(...older.nodes);
32
+ if (older.fullSnapshot)
33
+ nodes.splice(0, nodes.length, ...older.nodes);
34
+ else
35
+ nodes.unshift(...older.nodes);
31
36
  pageInfo = older.pageInfo;
32
37
  }
33
38
  // A window that shifted between pages can repeat or skip contexts; the
@@ -42,14 +47,24 @@ async function hydrateCommitContexts(commit, repo) {
42
47
  };
43
48
  }
44
49
  async function fetchOlderContexts(oid, before, repo) {
45
- const { data } = await graphqlWithRateLimit(POLL_SUMMARY_CHECK_PAGE_QUERY, {
46
- owner: repo.owner,
47
- repo: repo.name,
48
- oid,
49
- before,
50
+ return githubOperation("PollSummaryCheckPage", async () => {
51
+ const { data } = await graphqlWithRateLimit(POLL_SUMMARY_CHECK_PAGE_QUERY, {
52
+ owner: repo.owner,
53
+ repo: repo.name,
54
+ oid,
55
+ before,
56
+ });
57
+ const object = data.repository?.object;
58
+ if (object?.__typename !== "Commit" || object.oid !== oid)
59
+ return null;
60
+ return object.statusCheckRollup?.contexts ?? null;
61
+ }, async () => {
62
+ const checks = await readRestCommitChecks(oid, repo);
63
+ return {
64
+ fullSnapshot: true,
65
+ totalCount: checks.nodes.length,
66
+ pageInfo: { hasPreviousPage: false },
67
+ nodes: checks.nodes,
68
+ };
50
69
  });
51
- const object = data.repository?.object;
52
- if (object?.__typename !== "Commit" || object.oid !== oid)
53
- return null;
54
- return object.statusCheckRollup?.contexts ?? null;
55
70
  }
@@ -1,5 +1,5 @@
1
1
  import type { PollSummaryChecks } from "../types.mts";
2
2
  import type { RawSummaryPr } from "./poll-summary-raw.mts";
3
- export declare function summarizePollSummaryChecks(raw: RawSummaryPr): PollSummaryChecks;
3
+ export declare function summarizePollSummaryChecks(raw: RawSummaryPr, requiredContexts?: readonly string[]): PollSummaryChecks;
4
4
  /** Names of failing checks in the loaded summary rollup. */
5
- export declare function failingSummaryCheckNames(raw: RawSummaryPr): string[];
5
+ export declare function failingSummaryCheckNames(raw: RawSummaryPr, requiredContexts?: readonly string[]): string[];
@@ -1,9 +1,9 @@
1
1
  import { classifyChecks } from "../checks/classify.mjs";
2
2
  import { parseCreatedAt } from "./batch-parser-helpers.mjs";
3
- export function summarizePollSummaryChecks(raw) {
3
+ export function summarizePollSummaryChecks(raw, requiredContexts) {
4
4
  const rollups = summaryRollups(raw);
5
5
  const counts = {};
6
- for (const check of classifiedSummaryChecks(raw)) {
6
+ for (const check of classifiedSummaryChecks(raw, requiredContexts)) {
7
7
  const key = {
8
8
  passed: "passing",
9
9
  failing: "failing",
@@ -22,8 +22,8 @@ export function summarizePollSummaryChecks(raw) {
22
22
  return summary;
23
23
  }
24
24
  /** Names of failing checks in the loaded summary rollup. */
25
- export function failingSummaryCheckNames(raw) {
26
- return classifiedSummaryChecks(raw)
25
+ export function failingSummaryCheckNames(raw, requiredContexts) {
26
+ return classifiedSummaryChecks(raw, requiredContexts)
27
27
  .filter((check) => check.category === "failing")
28
28
  .map((check) => check.name);
29
29
  }
@@ -36,9 +36,12 @@ function summaryRollups(raw) {
36
36
  },
37
37
  ].flatMap(({ rollup, scope }) => (rollup ? [{ rollup, scope }] : []));
38
38
  }
39
- function classifiedSummaryChecks(raw) {
39
+ function classifiedSummaryChecks(raw, requiredContexts) {
40
40
  // A successful check on the queue commit cannot cover a PR-head cancellation, or vice versa.
41
- return summaryRollups(raw).flatMap(({ rollup, scope }) => classifyChecks(checkRuns(rollup, scope), scope === "merge_group" ? { additionalRelevantEvents: ["merge_group"] } : {}));
41
+ return summaryRollups(raw).flatMap(({ rollup, scope }) => classifyChecks(checkRuns(rollup, scope), {
42
+ ...(scope === "merge_group" && { additionalRelevantEvents: ["merge_group"] }),
43
+ ...(requiredContexts && { requiredContexts }),
44
+ }));
42
45
  }
43
46
  function checkRuns(rollup, scope) {
44
47
  return rollup.contexts.nodes.map((context) => {
@@ -0,0 +1,2 @@
1
+ import type { PollSummaryCommandOptions, PollSummaryItem } from "../types.mts";
2
+ export declare function pollCommandFields(repo: string, pr: number, isDraft: boolean, opts: PollSummaryCommandOptions): Pick<PollSummaryItem, "pollCommand" | "pollProbe">;
@@ -0,0 +1,24 @@
1
+ import { loadConfig } from "../config/load.mjs";
2
+ import { formatPrUrl } from "../pr-reference.mjs";
3
+ import { buildPrShepherdCommand } from "../cli/runner.mjs";
4
+ export function pollCommandFields(repo, pr, isDraft, opts) {
5
+ const autoMarkReadyDisabled = opts.noAutoMarkReady || loadConfig().actions.autoMarkReady === false;
6
+ const boundedDraft = isDraft && autoMarkReadyDisabled;
7
+ const args = boundedDraft
8
+ ? [formatPrUrl(repo, pr), "--timeout", "1s", "--debounce", "0s", "--no-auto-mark-ready"]
9
+ : [formatPrUrl(repo, pr), "--until-terminal"];
10
+ if (opts.merge && opts.stackPrNumber === undefined)
11
+ args.push("--merge");
12
+ if (opts.readyDelaySeconds !== undefined)
13
+ args.push("--ready-delay", `${opts.readyDelaySeconds}s`);
14
+ if (opts.stallTimeoutSeconds !== undefined)
15
+ args.push("--stall-timeout", `${opts.stallTimeoutSeconds}s`);
16
+ if (opts.instructions)
17
+ args.push("--instructions", opts.instructions);
18
+ if (opts.pollMode === "event")
19
+ args.push("--poll-mode", "event");
20
+ if (opts.noAutoMarkReady && !boundedDraft)
21
+ args.push("--no-auto-mark-ready");
22
+ const pollCommand = buildPrShepherdCommand(args).text;
23
+ return boundedDraft ? { pollCommand, pollProbe: true } : { pollCommand };
24
+ }
@@ -5,4 +5,4 @@ import type { RawSummaryPr } from "./poll-summary-raw.mts";
5
5
  * computed merge state are checked separately: including them here would
6
6
  * invalidate a READY receipt merely because a ready PR entered the queue.
7
7
  */
8
- export declare function fingerprintRawSummaryPr(raw: RawSummaryPr): string | null;
8
+ export declare function fingerprintRawSummaryPr(summary: RawSummaryPr): string | null;
@@ -1,11 +1,13 @@
1
1
  import { createHash } from "node:crypto";
2
+ import { withoutHandoffFields } from "./poll-summary-handoff-fields.mjs";
2
3
  /**
3
4
  * Bind receipts to the review and head-commit CI evidence shared by one-PR
4
5
  * completion and stack reconciliation. Queue entry, queue checks, and GitHub's
5
6
  * computed merge state are checked separately: including them here would
6
7
  * invalidate a READY receipt merely because a ready PR entered the queue.
7
8
  */
8
- export function fingerprintRawSummaryPr(raw) {
9
+ export function fingerprintRawSummaryPr(summary) {
10
+ const raw = withoutHandoffFields(summary);
9
11
  if (!raw.updatedAt || !raw.headRefOid || !raw.baseRefOid)
10
12
  return null;
11
13
  const reviewTruncated = raw.comments.pageInfo.hasPreviousPage ||
@@ -13,6 +15,7 @@ export function fingerprintRawSummaryPr(raw) {
13
15
  raw.reviewThreads.pageInfo.hasPreviousPage ||
14
16
  raw.reviewThreads.nodes.some((thread) => thread.comments.pageInfo.hasPreviousPage);
15
17
  const evidence = {
18
+ ...(raw.transport === "rest" && { transport: "rest" }),
16
19
  number: raw.number,
17
20
  state: raw.state,
18
21
  lifecycleEvents: raw.lifecycleEvents,
@@ -32,7 +35,6 @@ export function fingerprintRawSummaryPr(raw) {
32
35
  ...raw.reviewThreads,
33
36
  nodes: raw.reviewThreads.nodes.map((thread) => ({
34
37
  ...thread,
35
- rootComments: thread.rootComments && hideBodies(thread.rootComments),
36
38
  comments: hideBodies(thread.comments),
37
39
  })),
38
40
  },
@@ -0,0 +1,3 @@
1
+ import type { RawSummaryPr } from "./poll-summary-raw.mts";
2
+ /** `raw` without the fields only the handoff reads. */
3
+ export declare function withoutHandoffFields(raw: RawSummaryPr): RawSummaryPr;
@@ -0,0 +1,73 @@
1
+ /**
2
+ * The GraphQL summary selects these fields only so a routed stack layer's first
3
+ * tick can skip `BatchPr` (see `stack-handoff.mts`). They are not readiness
4
+ * evidence, and some (an edited hidden comment's `updatedAt`) change after a PR
5
+ * settles, so READY-receipt fingerprints leave them out. REST summaries never
6
+ * carry them. A thread comment's `isMinimized` stays: the fingerprint hides
7
+ * minimized bodies, as it already did for comments and reviews.
8
+ */
9
+ const COMMENT = ["viewerCanMinimize", "createdAt", "updatedAt"];
10
+ const REVIEW = [...COMMENT, "url", "commit"];
11
+ const THREAD = ["viewerCanReply", "viewerCanResolve", "line", "startLine"];
12
+ const THREAD_COMMENT = ["pullRequestReview", "path", "line", "startLine", "createdAt", "updatedAt"];
13
+ const STATUS_CONTEXT = ["createdAt", "targetUrl", "description"];
14
+ function omit(value, keys) {
15
+ const copy = { ...value };
16
+ for (const key of keys)
17
+ delete copy[key];
18
+ return copy;
19
+ }
20
+ function omitEach(connection, keys) {
21
+ return { ...connection, nodes: connection.nodes.map((node) => omit(node, keys)) };
22
+ }
23
+ /** `raw` without the fields only the handoff reads. */
24
+ export function withoutHandoffFields(raw) {
25
+ if (raw.transport === "rest")
26
+ return raw;
27
+ return {
28
+ ...raw,
29
+ ...(raw.reviewRequests && {
30
+ reviewRequests: {
31
+ nodes: raw.reviewRequests.nodes.map(({ requestedReviewer }) => ({
32
+ requestedReviewer: requestedReviewer && omit(requestedReviewer, ["name"]),
33
+ })),
34
+ },
35
+ }),
36
+ comments: omitEach(raw.comments, COMMENT),
37
+ reviews: omitEach(raw.reviews, REVIEW),
38
+ reviewThreads: {
39
+ ...raw.reviewThreads,
40
+ nodes: raw.reviewThreads.nodes.map((thread) => ({
41
+ ...omit(thread, THREAD),
42
+ comments: omitEach(thread.comments, THREAD_COMMENT),
43
+ })),
44
+ },
45
+ commits: {
46
+ ...omit(raw.commits, ["totalCount"]),
47
+ nodes: raw.commits.nodes.map(({ commit }) => {
48
+ const rollup = commit.statusCheckRollup;
49
+ return {
50
+ commit: {
51
+ ...commit,
52
+ statusCheckRollup: rollup && {
53
+ ...omit(rollup, ["state"]),
54
+ contexts: {
55
+ ...rollup.contexts,
56
+ nodes: rollup.contexts.nodes.map((node) => node.__typename === "StatusContext"
57
+ ? omit(node, STATUS_CONTEXT)
58
+ : {
59
+ ...node,
60
+ checkSuite: node.checkSuite && {
61
+ ...omit(node.checkSuite, ["updatedAt"]),
62
+ workflowRun: node.checkSuite.workflowRun &&
63
+ omit(node.checkSuite.workflowRun, ["updatedAt"]),
64
+ },
65
+ }),
66
+ },
67
+ },
68
+ },
69
+ };
70
+ }),
71
+ },
72
+ };
73
+ }
@@ -1,4 +1,4 @@
1
1
  import type { PollSummaryCommandOptions, PollSummaryItem } from "../types.mts";
2
2
  import type { RepoInfo } from "./client.mts";
3
3
  import type { RawSummaryPr } from "./poll-summary-raw.mts";
4
- export declare function summarizePollSummaryPr(raw: RawSummaryPr, repo: RepoInfo, opts: PollSummaryCommandOptions, viewerCanAdminister?: boolean, mergeTargetContexts?: readonly string[], viewerLogin?: string | null): Promise<PollSummaryItem>;
4
+ export declare function summarizePollSummaryPr(raw: RawSummaryPr, repo: RepoInfo, opts: PollSummaryCommandOptions, viewerCanAdminister?: boolean | undefined, mergeTargetContexts?: readonly string[], viewerLogin?: string | null): Promise<PollSummaryItem>;
@@ -1,7 +1,7 @@
1
+ import { pollCommandFields } from "./poll-summary-command.mjs";
1
2
  import { loadConfig } from "../config/load.mjs";
2
3
  import { updateReadyDelay } from "../commands/ready-delay.mjs";
3
4
  import { formatPrUrl } from "../pr-reference.mjs";
4
- import { buildPrShepherdCommand } from "../cli/runner.mjs";
5
5
  import { loadSeenMap } from "../state/seen-comments.mjs";
6
6
  import { isReadyReceiptCurrent, readReadyReceipt } from "../state/ready-receipts.mjs";
7
7
  import { summarizePollSummaryChecks } from "./poll-summary-checks.mjs";
@@ -11,12 +11,16 @@ import { isCurrentSummaryReady } from "./poll-summary-readiness.mjs";
11
11
  import { applyOpenCheckBlockers } from "./poll-summary-check-blockers.mjs";
12
12
  import { normalizePollSummaryState, routePollSummary } from "./poll-summary-route.mjs";
13
13
  import { hydrateReadyAnnotationProbe, readyFingerprint } from "./poll-summary-annotation-probe.mjs";
14
- import { applyUnreportedRequiredChecks } from "./poll-summary-unreported.mjs";
15
- export async function summarizePollSummaryPr(raw, repo, opts, viewerCanAdminister = false, mergeTargetContexts, viewerLogin = null) {
14
+ import { applyUnreportedRequiredChecks, summaryRequiredContexts, } from "./poll-summary-unreported.mjs";
15
+ import { aliasThreadSeenMarkers } from "./rest-identities.mjs";
16
+ import { restQueueRequirement } from "./poll-summary-rest-queue.mjs";
17
+ export async function summarizePollSummaryPr(raw, repo, opts, viewerCanAdminister = undefined, mergeTargetContexts, viewerLogin = null) {
16
18
  const repoName = `${repo.owner}/${repo.name}`;
17
19
  const seen = await loadSeenMap({ owner: repo.owner, repo: repo.name, pr: raw.number });
18
- const checks = summarizePollSummaryChecks(raw);
19
- applyUnreportedRequiredChecks(raw, checks, mergeTargetContexts);
20
+ await aliasThreadSeenMarkers(repo, raw.number, raw.reviewThreads.nodes.map(({ id }) => id), seen);
21
+ const required = summaryRequiredContexts(raw, mergeTargetContexts);
22
+ const checks = summarizePollSummaryChecks(raw, required);
23
+ applyUnreportedRequiredChecks(raw, checks, required);
20
24
  const review = await summarizePollSummaryReview(raw, seen, viewerCanAdminister);
21
25
  const blockingReviewerInProgress = detectBlockingReviewer(raw);
22
26
  const removalEvent = currentQueueRemovalEvent(raw);
@@ -74,12 +78,15 @@ export async function summarizePollSummaryPr(raw, repo, opts, viewerCanAdministe
74
78
  : removalEvent
75
79
  ? projectQueueRemoval(removalEvent)
76
80
  : undefined;
77
- const blocked = await applyOpenCheckBlockers(raw, repo, { action, reasons }, checks, review, opts.stackPrNumber !== undefined);
81
+ const blocked = await applyOpenCheckBlockers(raw, repo, { action, reasons }, checks, review, opts.stackPrNumber !== undefined, required);
78
82
  action = blocked.action;
79
83
  reasons = blocked.reasons;
84
+ const requiresMergeQueue = raw.transport === "rest" ? restQueueRequirement(raw) : undefined;
80
85
  return {
81
86
  pr: raw.number,
82
87
  repo: repoName,
88
+ ...(raw.transport && { transport: raw.transport }),
89
+ ...(raw.transportUnavailable?.length && { transportUnavailable: raw.transportUnavailable }),
83
90
  title: raw.title,
84
91
  url: raw.url || formatPrUrl(repoName, raw.number),
85
92
  ...(raw.author?.login && { authorLogin: raw.author.login }),
@@ -97,6 +104,7 @@ export async function summarizePollSummaryPr(raw, repo, opts, viewerCanAdministe
97
104
  baseRefName: raw.baseRefName,
98
105
  ...(raw.isDraft && { isDraft: true }),
99
106
  ...(raw.isInMergeQueue && { isInMergeQueue: true }),
107
+ ...(requiresMergeQueue !== undefined && { requiresMergeQueue }),
100
108
  ...(queueRemoval && { queueRemoval }),
101
109
  ...(blockingReviewerInProgress && { blockingReviewerInProgress: true }),
102
110
  ...(remainingSeconds !== undefined && { remainingSeconds }),
@@ -125,24 +133,9 @@ function projectQueueRemoval(removal) {
125
133
  }
126
134
  function detectBlockingReviewer(raw) {
127
135
  const prefixes = (loadConfig().mergeStatus?.blockingReviewerLogins ?? []).map((login) => login.toLowerCase());
128
- const matches = (author) => author !== null && prefixes.some((prefix) => author.login.toLowerCase().startsWith(prefix));
136
+ // A team reviewer has a name, not a login, so it never matches a login prefix.
137
+ const matches = (author) => typeof author?.login === "string" &&
138
+ prefixes.some((prefix) => author.login.toLowerCase().startsWith(prefix));
129
139
  return ((raw.reviewRequests?.nodes ?? []).some((request) => matches(request.requestedReviewer)) ||
130
140
  (raw.latestReviews?.nodes ?? []).some((review) => review.state === "PENDING" && matches(review.author)));
131
141
  }
132
- function pollCommandFields(repo, pr, isDraft, opts) {
133
- const autoMarkReadyDisabled = opts.noAutoMarkReady || loadConfig().actions.autoMarkReady === false;
134
- const boundedDraft = isDraft && autoMarkReadyDisabled;
135
- const args = boundedDraft
136
- ? [formatPrUrl(repo, pr), "--timeout", "1s", "--debounce", "0s", "--no-auto-mark-ready"]
137
- : [formatPrUrl(repo, pr), "--until-terminal"];
138
- if (opts.merge && opts.stackPrNumber === undefined)
139
- args.push("--merge");
140
- if (opts.readyDelaySeconds !== undefined)
141
- args.push("--ready-delay", `${opts.readyDelaySeconds}s`);
142
- if (opts.stallTimeoutSeconds !== undefined)
143
- args.push("--stall-timeout", `${opts.stallTimeoutSeconds}s`);
144
- if (opts.noAutoMarkReady && !boundedDraft)
145
- args.push("--no-auto-mark-ready");
146
- const pollCommand = buildPrShepherdCommand(args).text;
147
- return boundedDraft ? { pollCommand, pollProbe: true } : { pollCommand };
148
- }
@@ -1,4 +1,5 @@
1
1
  import type { RawBaseRef } from "./batch-raw-rules.mts";
2
+ import type { AutoMergeRequestStatus } from "../types/merge-requirements.mts";
2
3
  export interface RawAuthor {
3
4
  __typename?: string;
4
5
  login: string;
@@ -6,11 +7,24 @@ export interface RawAuthor {
6
7
  interface RawSummaryComment {
7
8
  id: string;
8
9
  body: string;
9
- isMinimized: boolean;
10
+ isMinimized?: boolean;
10
11
  viewerDidAuthor?: boolean;
11
12
  authorAssociation?: string;
12
13
  url?: string;
13
14
  author: RawAuthor | null;
15
+ /** GraphQL handoff fields; absent on REST summaries. */
16
+ viewerCanMinimize?: boolean;
17
+ createdAt?: string;
18
+ updatedAt?: string;
19
+ pullRequestReview?: {
20
+ id: string;
21
+ } | null;
22
+ path?: string | null;
23
+ line?: number | null;
24
+ startLine?: number | null;
25
+ commit?: {
26
+ oid: string;
27
+ } | null;
14
28
  }
15
29
  interface SummaryConnection<T> {
16
30
  totalCount: number;
@@ -25,7 +39,7 @@ type RawCheckContext = {
25
39
  name: string;
26
40
  status: string;
27
41
  conclusion: string | null;
28
- detailsUrl?: string;
42
+ detailsUrl?: string | null;
29
43
  startedAt?: string | null;
30
44
  completedAt?: string | null;
31
45
  annotations?: {
@@ -33,10 +47,12 @@ type RawCheckContext = {
33
47
  };
34
48
  checkSuite: {
35
49
  createdAt?: string | null;
50
+ updatedAt?: string | null;
36
51
  workflowRun: {
37
52
  databaseId?: string | number;
38
53
  event: string;
39
54
  createdAt?: string | null;
55
+ updatedAt?: string | null;
40
56
  workflow?: {
41
57
  name: string;
42
58
  databaseId: string | number;
@@ -47,6 +63,9 @@ type RawCheckContext = {
47
63
  __typename: "StatusContext";
48
64
  context: string;
49
65
  state: string;
66
+ createdAt?: string;
67
+ targetUrl?: string | null;
68
+ description?: string | null;
50
69
  };
51
70
  interface RawCheckContexts {
52
71
  totalCount: number;
@@ -58,6 +77,7 @@ interface RawCheckContexts {
58
77
  nodes: RawCheckContext[];
59
78
  }
60
79
  export interface RawCheckRollup {
80
+ state?: string | null;
61
81
  contexts: RawCheckContexts;
62
82
  }
63
83
  /** A commit whose status contexts the compact summary reads. */
@@ -66,16 +86,47 @@ export interface RawSummaryCommit {
66
86
  committedDate?: string;
67
87
  statusCheckRollup: RawCheckRollup | null;
68
88
  checkSuites?: {
89
+ pageInfo?: {
90
+ hasNextPage: boolean;
91
+ };
69
92
  nodes: Array<{
93
+ id?: string;
70
94
  status?: string | null;
71
95
  conclusion: string | null;
72
96
  workflowRun: {
97
+ databaseId?: number | null;
73
98
  event: string | null;
99
+ url?: string | null;
100
+ workflow?: {
101
+ name: string | null;
102
+ } | null;
74
103
  } | null;
75
104
  }>;
76
105
  } | null;
77
106
  }
78
107
  export interface RawSummaryPr {
108
+ transport?: "rest";
109
+ transportUnavailable?: Array<{
110
+ field: string;
111
+ reason: string;
112
+ }>;
113
+ /** GraphQL handoff fields (see `stack-handoff.mts`); absent on REST summaries. */
114
+ id?: string;
115
+ viewerDidAuthor?: boolean;
116
+ viewerCanEnableAutoMerge?: boolean;
117
+ viewerCanEditFiles?: boolean;
118
+ headRepository?: {
119
+ nameWithOwner: string;
120
+ viewerPermission: string | null;
121
+ } | null;
122
+ isMergeQueueEnabled?: boolean;
123
+ batchAutoMergeRequest?: {
124
+ enabledAt: string;
125
+ mergeMethod: string;
126
+ enabledBy?: {
127
+ login: string;
128
+ } | null;
129
+ } | null;
79
130
  number: number;
80
131
  title: string;
81
132
  url: string;
@@ -91,7 +142,7 @@ export interface RawSummaryPr {
91
142
  }>;
92
143
  } | null;
93
144
  isDraft: boolean;
94
- viewerCanUpdate: boolean;
145
+ viewerCanUpdate?: boolean;
95
146
  headRefName: string;
96
147
  headRefOid: string;
97
148
  baseRefOid: string;
@@ -102,7 +153,9 @@ export interface RawSummaryPr {
102
153
  reviewDecision: string | null;
103
154
  reviewRequests?: {
104
155
  nodes: Array<{
105
- requestedReviewer: RawAuthor | null;
156
+ requestedReviewer: (Partial<RawAuthor> & {
157
+ name?: string;
158
+ }) | null;
106
159
  }>;
107
160
  };
108
161
  latestReviews?: {
@@ -111,7 +164,8 @@ export interface RawSummaryPr {
111
164
  author: RawAuthor | null;
112
165
  }>;
113
166
  };
114
- isInMergeQueue: boolean;
167
+ isInMergeQueue?: boolean;
168
+ autoMergeRequest?: AutoMergeRequestStatus | null;
115
169
  mergeQueueAdditions?: {
116
170
  nodes: Array<{
117
171
  createdAt: string;
@@ -158,15 +212,21 @@ export interface RawSummaryPr {
158
212
  }>;
159
213
  reviewThreads: SummaryConnection<{
160
214
  id: string;
161
- isResolved: boolean;
162
- isOutdated: boolean;
215
+ isResolved?: boolean;
216
+ isOutdated?: boolean;
217
+ viewerCanReply?: boolean;
218
+ viewerCanResolve?: boolean;
163
219
  path: string | null;
164
- rootComments?: {
165
- nodes: RawSummaryComment[];
166
- };
220
+ line?: number | null;
221
+ startLine?: number | null;
222
+ /**
223
+ * The first comments from the root. `pageInfo.hasPreviousPage` is GraphQL's
224
+ * `hasNextPage` (aliased): true when comments exist outside this window.
225
+ */
167
226
  comments: SummaryConnection<RawSummaryComment>;
168
227
  }>;
169
228
  commits: {
229
+ totalCount?: number;
170
230
  nodes: Array<{
171
231
  commit: RawSummaryCommit;
172
232
  }>;
@@ -1,6 +1,7 @@
1
1
  import { summarizePollSummaryChecks } from "./poll-summary-checks.mjs";
2
2
  import { parseBranchRules } from "./batch-parsers-rules.mjs";
3
3
  import { rulesComplete } from "./fingerprint-fields.mjs";
4
+ import { isKnownMergeStateStatus, transportReadinessGaps } from "./transport-evidence.mjs";
4
5
  /** Fresh compact evidence required before a READY receipt can be used. */
5
6
  export function isCurrentSummaryReady(raw, checks, review, options = {}) {
6
7
  const queued = options.allowQueuedProgress === true && raw.isInMergeQueue;
@@ -16,7 +17,9 @@ export function isCurrentSummaryReady(raw, checks, review, options = {}) {
16
17
  // satisfied. BLOCKED is not conversation-specific, and queue progress
17
18
  // alone is not that proof.
18
19
  const requiresConversationResolution = parseBranchRules(raw.baseRef).requiresConversationResolution;
19
- return (checks.incomplete !== true &&
20
+ return (isKnownMergeStateStatus(raw.mergeStateStatus) &&
21
+ transportReadinessGaps(raw, raw.mergeStateStatus).length === 0 &&
22
+ checks.incomplete !== true &&
20
23
  sourceChecks.incomplete !== true &&
21
24
  (review.incomplete !== true ||
22
25
  raw.mergeStateStatus === "CLEAN" ||
@@ -0,0 +1,3 @@
1
+ import type { RawSummaryPr } from "./poll-summary-raw.mts";
2
+ /** Positive rules remain authoritative even when other branch policy is unavailable. */
3
+ export declare function restQueueRequirement(raw: Pick<RawSummaryPr, "baseRef" | "transportUnavailable">): boolean | undefined;
@@ -0,0 +1,12 @@
1
+ import { parseBranchRules } from "./batch-parsers-rules.mjs";
2
+ /** Positive rules remain authoritative even when other branch policy is unavailable. */
3
+ export function restQueueRequirement(raw) {
4
+ if (parseBranchRules(raw.baseRef).requiresMergeQueue)
5
+ return true;
6
+ if (!raw.baseRef?.rules ||
7
+ raw.baseRef.rules.pageInfo?.hasNextPage !== false ||
8
+ raw.baseRef.branchProtectionRule !== null ||
9
+ raw.transportUnavailable?.some(({ field }) => ["branchProtection", "branchRules"].includes(field)))
10
+ return undefined;
11
+ return false;
12
+ }
@@ -1,4 +1,4 @@
1
1
  import { type SeenMarker } from "../state/seen-comments.mts";
2
2
  import type { PollSummaryReview } from "../types.mts";
3
3
  import type { RawSummaryPr } from "./poll-summary-raw.mts";
4
- export declare function summarizePollSummaryReview(raw: RawSummaryPr, seen: Map<string, SeenMarker>, viewerCanAdminister: boolean): Promise<PollSummaryReview>;
4
+ export declare function summarizePollSummaryReview(raw: RawSummaryPr, seen: Map<string, SeenMarker>, viewerCanAdminister: boolean | undefined): Promise<PollSummaryReview>;