pr-shepherd 0.56.5 → 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 (423) 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 +40 -19
  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.d.mts +6 -5
  138. package/bin/commands/iterate/native-stack-rebase.mjs +24 -7
  139. package/bin/commands/iterate/render.d.mts +8 -2
  140. package/bin/commands/iterate/render.mjs +28 -42
  141. package/bin/commands/iterate/stack-trunk-conflict.d.mts +4 -2
  142. package/bin/commands/iterate/stack-trunk-conflict.mjs +44 -19
  143. package/bin/commands/iterate/stale-ancestry.mjs +4 -1
  144. package/bin/commands/iterate/stall.d.mts +5 -1
  145. package/bin/commands/iterate/stall.mjs +19 -7
  146. package/bin/commands/iterate/thread-mutation-routing.d.mts +1 -0
  147. package/bin/commands/iterate/thread-mutation-routing.mjs +4 -2
  148. package/bin/commands/iterate/unreported-required.mjs +5 -2
  149. package/bin/commands/mark-files-as-viewed.mjs +7 -0
  150. package/bin/commands/next-check.d.mts +31 -0
  151. package/bin/commands/next-check.mjs +46 -0
  152. package/bin/commands/playbook.d.mts +13 -0
  153. package/bin/commands/playbook.mjs +48 -0
  154. package/bin/commands/poll-mode.d.mts +8 -0
  155. package/bin/commands/poll-mode.mjs +14 -0
  156. package/bin/commands/poll-progress.d.mts +1 -0
  157. package/bin/commands/poll-progress.mjs +6 -3
  158. package/bin/commands/poll-quota.d.mts +3 -2
  159. package/bin/commands/poll-quota.mjs +7 -3
  160. package/bin/commands/poll-summary-explicit-instructions.d.mts +2 -0
  161. package/bin/commands/poll-summary-explicit-instructions.mjs +10 -1
  162. package/bin/commands/poll-summary-instructions.mjs +16 -17
  163. package/bin/commands/poll-summary.mjs +42 -17
  164. package/bin/commands/poll.d.mts +0 -1
  165. package/bin/commands/poll.mjs +11 -19
  166. package/bin/commands/quota-selection.d.mts +2 -1
  167. package/bin/commands/quota-selection.mjs +12 -7
  168. package/bin/commands/resolve-mutate.mjs +33 -5
  169. package/bin/commands/rest-stack-merge-readiness.d.mts +4 -0
  170. package/bin/commands/rest-stack-merge-readiness.mjs +74 -0
  171. package/bin/commands/rule-auto-resolve.mjs +9 -3
  172. package/bin/commands/shepherd-journal.d.mts +5 -4
  173. package/bin/commands/shepherd-journal.mjs +9 -8
  174. package/bin/commands/stack-drain.d.mts +1 -9
  175. package/bin/commands/stack-drain.mjs +50 -37
  176. package/bin/commands/stack-handoffs.d.mts +10 -0
  177. package/bin/commands/stack-handoffs.mjs +25 -0
  178. package/bin/commands/stack-stall.d.mts +5 -0
  179. package/bin/commands/stack-stall.mjs +11 -0
  180. package/bin/commands/stack-work.d.mts +5 -0
  181. package/bin/commands/stack-work.mjs +32 -0
  182. package/bin/comments/existing-reply-scan.d.mts +17 -0
  183. package/bin/comments/existing-reply-scan.mjs +41 -0
  184. package/bin/comments/rate-limit.mjs +2 -2
  185. package/bin/comments/resolve.d.mts +7 -1
  186. package/bin/comments/resolve.mjs +108 -18
  187. package/bin/comments/rest-reply.d.mts +9 -0
  188. package/bin/comments/rest-reply.mjs +95 -0
  189. package/bin/comments/rest-review-mutations.d.mts +22 -0
  190. package/bin/comments/rest-review-mutations.mjs +125 -0
  191. package/bin/comments/review-visibility.d.mts +1 -1
  192. package/bin/comments/review-visibility.mjs +3 -2
  193. package/bin/comments/sha-poll.mjs +7 -3
  194. package/bin/comments/thread-visibility.mjs +10 -5
  195. package/bin/comments/uncertain-replies.d.mts +11 -0
  196. package/bin/comments/uncertain-replies.mjs +121 -0
  197. package/bin/comments/uncertain-reply-guards.d.mts +10 -0
  198. package/bin/comments/uncertain-reply-guards.mjs +94 -0
  199. package/bin/comments/visible-comments.d.mts +1 -1
  200. package/bin/comments/visible-comments.mjs +4 -2
  201. package/bin/config/load.d.mts +37 -1
  202. package/bin/config/load.mjs +73 -1
  203. package/bin/config.json +6 -2
  204. package/bin/exit-codes.d.mts +3 -0
  205. package/bin/exit-codes.mjs +8 -0
  206. package/bin/github/api-telemetry-aggregate.d.mts +15 -4
  207. package/bin/github/api-telemetry-aggregate.mjs +57 -18
  208. package/bin/github/api-telemetry.d.mts +4 -0
  209. package/bin/github/api-telemetry.mjs +22 -8
  210. package/bin/github/apply-review-preflight.d.mts +20 -0
  211. package/bin/github/apply-review-preflight.mjs +61 -0
  212. package/bin/github/base-behind-cache.d.mts +15 -0
  213. package/bin/github/base-behind-cache.mjs +18 -0
  214. package/bin/github/batch-parse-suites.d.mts +4 -2
  215. package/bin/github/batch-parse-suites.mjs +6 -1
  216. package/bin/github/batch-parser-helpers.mjs +40 -2
  217. package/bin/github/batch-parsers.mjs +1 -0
  218. package/bin/github/batch-raw-rules.d.mts +26 -0
  219. package/bin/github/batch-raw-types.d.mts +8 -6
  220. package/bin/github/batch-stack-evidence.d.mts +28 -0
  221. package/bin/github/batch-stack-evidence.mjs +62 -0
  222. package/bin/github/batch.d.mts +15 -2
  223. package/bin/github/batch.mjs +34 -17
  224. package/bin/github/check-annotations-batch.d.mts +0 -5
  225. package/bin/github/check-annotations-batch.mjs +25 -4
  226. package/bin/github/check-annotations.mjs +3 -1
  227. package/bin/github/client.d.mts +8 -19
  228. package/bin/github/client.mjs +45 -13
  229. package/bin/github/fingerprint-fields.d.mts +8 -0
  230. package/bin/github/fingerprint-fields.mjs +6 -1
  231. package/bin/github/fingerprint.d.mts +4 -2
  232. package/bin/github/fingerprint.mjs +6 -38
  233. package/bin/github/github-fetch.d.mts +2 -0
  234. package/bin/github/github-fetch.mjs +19 -0
  235. package/bin/github/gql/base-behind.gql +3 -0
  236. package/bin/github/gql/batch-pr-page.gql +16 -0
  237. package/bin/github/gql/batch-pr.gql +57 -0
  238. package/bin/github/gql/commit-check-contexts.gql +17 -0
  239. package/bin/github/gql/get-pr-body.gql +1 -0
  240. package/bin/github/gql/poll-stack-summary.gql +1 -0
  241. package/bin/github/gql/poll-summary-check-contexts.gql +5 -0
  242. package/bin/github/gql/poll-summary-fragment.gql +65 -15
  243. package/bin/github/gql/stack-handoff-check-runs.gql +42 -0
  244. package/bin/github/gql/upper-layer-conflict-target.gql +0 -15
  245. package/bin/github/graphql-http.mjs +9 -4
  246. package/bin/github/graphql-internal-retry.d.mts +2 -0
  247. package/bin/github/graphql-internal-retry.mjs +1 -1
  248. package/bin/github/graphql-quota-probe.d.mts +6 -0
  249. package/bin/github/graphql-quota-probe.mjs +56 -0
  250. package/bin/github/graphql-session-refusal.d.mts +8 -0
  251. package/bin/github/graphql-session-refusal.mjs +14 -0
  252. package/bin/github/http-request.d.mts +1 -1
  253. package/bin/github/http-request.mjs +22 -6
  254. package/bin/github/http-utils.mjs +6 -0
  255. package/bin/github/merge-target-rules.d.mts +16 -3
  256. package/bin/github/merge-target-rules.mjs +79 -44
  257. package/bin/github/mutation-policy.d.mts +6 -0
  258. package/bin/github/mutation-policy.mjs +21 -0
  259. package/bin/github/poll-summary-annotation-probe.mjs +17 -10
  260. package/bin/github/poll-summary-check-blockers.d.mts +1 -1
  261. package/bin/github/poll-summary-check-blockers.mjs +2 -2
  262. package/bin/github/poll-summary-check-hydration.mjs +25 -10
  263. package/bin/github/poll-summary-checks.d.mts +2 -2
  264. package/bin/github/poll-summary-checks.mjs +9 -6
  265. package/bin/github/poll-summary-command.d.mts +2 -0
  266. package/bin/github/poll-summary-command.mjs +24 -0
  267. package/bin/github/poll-summary-fingerprint.d.mts +1 -1
  268. package/bin/github/poll-summary-fingerprint.mjs +4 -2
  269. package/bin/github/poll-summary-handoff-fields.d.mts +3 -0
  270. package/bin/github/poll-summary-handoff-fields.mjs +73 -0
  271. package/bin/github/poll-summary-projector.d.mts +1 -1
  272. package/bin/github/poll-summary-projector.mjs +17 -24
  273. package/bin/github/poll-summary-raw.d.mts +70 -10
  274. package/bin/github/poll-summary-readiness.mjs +4 -1
  275. package/bin/github/poll-summary-rest-queue.d.mts +3 -0
  276. package/bin/github/poll-summary-rest-queue.mjs +12 -0
  277. package/bin/github/poll-summary-review.d.mts +1 -1
  278. package/bin/github/poll-summary-review.mjs +23 -11
  279. package/bin/github/poll-summary-route.mjs +19 -3
  280. package/bin/github/poll-summary-stack-page.d.mts +11 -0
  281. package/bin/github/poll-summary-stack-page.mjs +27 -0
  282. package/bin/github/poll-summary-unreported.d.mts +6 -3
  283. package/bin/github/poll-summary-unreported.mjs +15 -7
  284. package/bin/github/poll-summary.d.mts +4 -1
  285. package/bin/github/poll-summary.mjs +48 -34
  286. package/bin/github/queries.d.mts +9 -5
  287. package/bin/github/queries.mjs +10 -6
  288. package/bin/github/rate-limit-sample.d.mts +7 -0
  289. package/bin/github/rate-limit-sample.mjs +12 -0
  290. package/bin/github/reply-recovery-read.d.mts +50 -0
  291. package/bin/github/reply-recovery-read.mjs +118 -0
  292. package/bin/github/reply-thread-transcripts.d.mts +0 -1
  293. package/bin/github/reply-thread-transcripts.mjs +24 -1
  294. package/bin/github/rest-annotation-read.d.mts +5 -0
  295. package/bin/github/rest-annotation-read.mjs +44 -0
  296. package/bin/github/rest-batch-read.d.mts +12 -0
  297. package/bin/github/rest-batch-read.mjs +57 -0
  298. package/bin/github/rest-batch-snapshot.d.mts +30 -0
  299. package/bin/github/rest-batch-snapshot.mjs +115 -0
  300. package/bin/github/rest-batch-unavailable.d.mts +5 -0
  301. package/bin/github/rest-batch-unavailable.mjs +16 -0
  302. package/bin/github/rest-check-read.d.mts +34 -0
  303. package/bin/github/rest-check-read.mjs +124 -0
  304. package/bin/github/rest-comment-authorship.d.mts +7 -0
  305. package/bin/github/rest-comment-authorship.mjs +11 -0
  306. package/bin/github/rest-conditional-scope.d.mts +20 -0
  307. package/bin/github/rest-conditional-scope.mjs +44 -0
  308. package/bin/github/rest-explicit-summary-read.d.mts +3 -0
  309. package/bin/github/rest-explicit-summary-read.mjs +8 -0
  310. package/bin/github/rest-feedback-read.d.mts +36 -0
  311. package/bin/github/rest-feedback-read.mjs +147 -0
  312. package/bin/github/rest-feedback-validation.d.mts +5 -0
  313. package/bin/github/rest-feedback-validation.mjs +28 -0
  314. package/bin/github/rest-http.d.mts +12 -0
  315. package/bin/github/rest-http.mjs +108 -23
  316. package/bin/github/rest-identities.d.mts +22 -0
  317. package/bin/github/rest-identities.mjs +134 -0
  318. package/bin/github/rest-merge-stack-guard.d.mts +14 -0
  319. package/bin/github/rest-merge-stack-guard.mjs +41 -0
  320. package/bin/github/rest-merge.d.mts +29 -0
  321. package/bin/github/rest-merge.mjs +56 -0
  322. package/bin/github/rest-merged-base-read.d.mts +9 -0
  323. package/bin/github/rest-merged-base-read.mjs +48 -0
  324. package/bin/github/rest-pr-core.d.mts +52 -0
  325. package/bin/github/rest-pr-core.mjs +60 -0
  326. package/bin/github/rest-reader-core.d.mts +16 -0
  327. package/bin/github/rest-reader-core.mjs +154 -0
  328. package/bin/github/rest-review-read.d.mts +11 -0
  329. package/bin/github/rest-review-read.mjs +47 -0
  330. package/bin/github/rest-rules-read.d.mts +9 -0
  331. package/bin/github/rest-rules-read.mjs +154 -0
  332. package/bin/github/rest-session-refusal.d.mts +5 -0
  333. package/bin/github/rest-session-refusal.mjs +21 -0
  334. package/bin/github/rest-snapshot-context.d.mts +10 -0
  335. package/bin/github/rest-snapshot-context.mjs +1 -0
  336. package/bin/github/rest-stack-read.d.mts +21 -0
  337. package/bin/github/rest-stack-read.mjs +47 -0
  338. package/bin/github/rest-stack-summary.d.mts +8 -0
  339. package/bin/github/rest-stack-summary.mjs +62 -0
  340. package/bin/github/rest-summary-read.d.mts +7 -0
  341. package/bin/github/rest-summary-read.mjs +112 -0
  342. package/bin/github/rest-terminal-batch.d.mts +14 -0
  343. package/bin/github/rest-terminal-batch.mjs +45 -0
  344. package/bin/github/rest-text.mjs +7 -3
  345. package/bin/github/rest-thread-read.d.mts +4 -0
  346. package/bin/github/rest-thread-read.mjs +35 -0
  347. package/bin/github/rest-viewer-read.d.mts +2 -0
  348. package/bin/github/rest-viewer-read.mjs +41 -0
  349. package/bin/github/stack-bottom.d.mts +3 -0
  350. package/bin/github/stack-bottom.mjs +14 -0
  351. package/bin/github/stack-handoff-context.d.mts +25 -0
  352. package/bin/github/stack-handoff-context.mjs +12 -0
  353. package/bin/github/stack-handoff-page.d.mts +17 -0
  354. package/bin/github/stack-handoff-page.mjs +306 -0
  355. package/bin/github/stack-handoff.d.mts +16 -0
  356. package/bin/github/stack-handoff.mjs +115 -0
  357. package/bin/github/stack-order.d.mts +6 -0
  358. package/bin/github/stack-order.mjs +13 -0
  359. package/bin/github/stack-read.d.mts +7 -3
  360. package/bin/github/stack-read.mjs +22 -11
  361. package/bin/github/stack-size-hint.d.mts +3 -0
  362. package/bin/github/stack-size-hint.mjs +14 -0
  363. package/bin/github/suggestion-thread.mjs +27 -1
  364. package/bin/github/thread-comments.mjs +9 -1
  365. package/bin/github/transport-evidence.d.mts +20 -0
  366. package/bin/github/transport-evidence.mjs +26 -0
  367. package/bin/github/transport-mode.d.mts +2 -0
  368. package/bin/github/transport-mode.mjs +5 -0
  369. package/bin/github/transport.d.mts +19 -0
  370. package/bin/github/transport.mjs +126 -0
  371. package/bin/github/unsupported-rest.d.mts +4 -0
  372. package/bin/github/unsupported-rest.mjs +7 -0
  373. package/bin/mcp/server.mjs +52 -3
  374. package/bin/merge-status/derive.d.mts +2 -0
  375. package/bin/merge-status/derive.mjs +17 -13
  376. package/bin/merge-status/required-check-requirements.d.mts +7 -0
  377. package/bin/merge-status/required-check-requirements.mjs +15 -0
  378. package/bin/merge-status/requirements-format.d.mts +5 -0
  379. package/bin/merge-status/requirements-format.mjs +41 -12
  380. package/bin/merge-status/requirements.mjs +18 -7
  381. package/bin/state/base.mjs +41 -0
  382. package/bin/state/durable-state.d.mts +6 -0
  383. package/bin/state/durable-state.mjs +41 -0
  384. package/bin/state/graphql-quota-policy.mjs +23 -16
  385. package/bin/state/merge-request.d.mts +25 -0
  386. package/bin/state/merge-request.mjs +145 -0
  387. package/bin/state/pr-fingerprint.d.mts +15 -0
  388. package/bin/state/pr-fingerprint.mjs +22 -7
  389. package/bin/state/rest-cache.d.mts +3 -0
  390. package/bin/state/rest-cache.mjs +1 -0
  391. package/bin/state/rest-snapshot-report.d.mts +21 -0
  392. package/bin/state/rest-snapshot-report.mjs +52 -0
  393. package/bin/state/seen-comments.d.mts +3 -0
  394. package/bin/state/seen-comments.mjs +18 -0
  395. package/bin/types/api-usage.d.mts +9 -1
  396. package/bin/types/escalate.d.mts +1 -1
  397. package/bin/types/github.d.mts +23 -9
  398. package/bin/types/iterate.d.mts +24 -2
  399. package/bin/types/merge-action.d.mts +1 -1
  400. package/bin/types/merge-requirements.d.mts +7 -7
  401. package/bin/types/next-check.d.mts +12 -0
  402. package/bin/types/next-check.mjs +1 -0
  403. package/bin/types/poll-summary.d.mts +21 -0
  404. package/bin/types/report.d.mts +13 -1
  405. package/bin/types/review-thread.d.mts +1 -1
  406. package/bin/types.d.mts +1 -0
  407. package/bin/types.mjs +1 -0
  408. package/package.json +3 -2
  409. package/plugins/pr-shepherd/.codex-plugin/plugin.json +1 -1
  410. package/plugins/pr-shepherd/.codex.mcp.json +1 -1
  411. package/plugins/pr-shepherd/.mcp.json +1 -1
  412. package/plugins/pr-shepherd/skills/mark-files-as-viewed/SKILL.md +1 -1
  413. package/plugins/pr-shepherd/skills/pr-shepherd/SKILL.md +14 -51
  414. package/plugins/pr-shepherd/skills/pr-shepherd/references/ci-failure-triage.md +12 -16
  415. package/plugins/pr-shepherd/skills/pr-shepherd/references/cloud-event-loop.md +14 -0
  416. package/plugins/pr-shepherd/skills/pr-shepherd/references/create-pr.md +10 -0
  417. package/plugins/pr-shepherd/skills/pr-shepherd/references/fix-code-loop.md +10 -0
  418. package/plugins/pr-shepherd/skills/pr-shepherd/references/mcp-fallback.md +9 -0
  419. package/plugins/pr-shepherd/skills/reduce-pr-noise/references/classifiers.md +2 -0
  420. package/bin/github/gql/pr-fingerprint.gql +0 -75
  421. package/plugins/pr-shepherd/skills/pr-shepherd/references/journal.md +0 -7
  422. package/plugins/pr-shepherd/skills/pr-shepherd/references/review-mutations.md +0 -9
  423. package/plugins/pr-shepherd/skills/pr-shepherd/references/stack-merge.md +0 -7
@@ -0,0 +1,112 @@
1
+ export function restSummary(data, pull, feedback, checks, baseRef) {
2
+ const connection = (nodes) => ({
3
+ nodes,
4
+ totalCount: nodes.length,
5
+ pageInfo: { hasPreviousPage: false },
6
+ });
7
+ const comments = feedback.comments.map((comment) => ({
8
+ id: comment.id,
9
+ body: comment.body,
10
+ author: { login: comment.author, __typename: comment.authorType },
11
+ url: comment.url,
12
+ authorAssociation: comment.authorAssociation,
13
+ }));
14
+ return {
15
+ number: pull.number,
16
+ title: pull.title,
17
+ url: pull.html_url,
18
+ author: pull.user,
19
+ state: data.state,
20
+ isDraft: data.isDraft,
21
+ ...(data.autoMergeRequest && { autoMergeRequest: data.autoMergeRequest }),
22
+ updatedAt: pull.updated_at,
23
+ headRefName: data.headRefName,
24
+ headRefOid: data.headRefOid,
25
+ baseRefOid: pull.base.sha,
26
+ baseRefName: data.baseRefName,
27
+ ...(baseRef && { baseRef }),
28
+ mergeable: data.mergeable,
29
+ mergeStateStatus: data.mergeStateStatus,
30
+ reviewDecision: null,
31
+ reviewRequests: {
32
+ nodes: data.reviewRequests.map((request) => ({ requestedReviewer: request })),
33
+ },
34
+ latestReviews: {
35
+ nodes: data.latestReviews.map((review) => ({
36
+ state: review.state,
37
+ author: { login: review.login },
38
+ })),
39
+ },
40
+ mergeQueueEntry: null,
41
+ stack: data.stack
42
+ ? { number: data.stack.number, size: data.stack.size, baseRefName: data.stack.baseRefName }
43
+ : null,
44
+ stackEntry: data.stack ? { position: data.stack.position } : null,
45
+ comments: connection(comments),
46
+ reviews: connection(feedback.reviews.map((review) => ({
47
+ id: review.node_id,
48
+ body: review.body ?? "",
49
+ state: review.state,
50
+ author: review.user ? { login: review.user.login, __typename: review.user.type } : null,
51
+ authorAssociation: review.author_association,
52
+ url: review.html_url,
53
+ }))),
54
+ reviewThreads: connection(data.reviewThreads.map((thread) => ({
55
+ id: thread.id,
56
+ ...(thread.isResolved !== undefined && { isResolved: thread.isResolved }),
57
+ ...(thread.isOutdated !== undefined && { isOutdated: thread.isOutdated }),
58
+ path: thread.path,
59
+ comments: connection((thread.comments ?? []).map((comment) => ({
60
+ id: comment.id,
61
+ ...(comment.viewerDidAuthor === true && { viewerDidAuthor: true }),
62
+ body: comment.body,
63
+ author: { login: comment.author, __typename: comment.authorType },
64
+ url: comment.url,
65
+ authorAssociation: comment.authorAssociation,
66
+ }))),
67
+ }))),
68
+ commits: {
69
+ nodes: [
70
+ {
71
+ commit: {
72
+ oid: data.headRefOid,
73
+ statusCheckRollup: {
74
+ contexts: connection(checks.nodes.map((check) => check.__typename === "CheckRun"
75
+ ? {
76
+ ...check,
77
+ detailsUrl: check.detailsUrl ?? undefined,
78
+ annotations: { totalCount: check.annotations.totalCount },
79
+ checkSuite: check.checkSuite
80
+ ? {
81
+ ...check.checkSuite,
82
+ workflowRun: check.checkSuite.workflowRun
83
+ ? {
84
+ ...check.checkSuite.workflowRun,
85
+ workflow: check.checkSuite.workflowRun.workflow
86
+ ? {
87
+ ...check.checkSuite.workflowRun.workflow,
88
+ databaseId: check.checkSuite.workflowRun.workflow.databaseId,
89
+ }
90
+ : null,
91
+ }
92
+ : null,
93
+ }
94
+ : null,
95
+ }
96
+ : check)),
97
+ },
98
+ checkSuites: {
99
+ nodes: checks.suites.map((suite) => ({
100
+ status: suite.status.toUpperCase(),
101
+ conclusion: suite.conclusion?.toUpperCase() ?? null,
102
+ workflowRun: checks.workflowRuns.find((run) => run.check_suite_id === suite.id) ?? null,
103
+ })),
104
+ },
105
+ },
106
+ },
107
+ ],
108
+ },
109
+ transport: "rest",
110
+ transportUnavailable: data.transportUnavailable,
111
+ };
112
+ }
@@ -0,0 +1,14 @@
1
+ import type { BatchPrData } from "../types.mts";
2
+ import { type RestPull } from "./rest-pr-core.mts";
3
+ /**
4
+ * A merged pull is immutable, so its first read is final. A closed pull is not (it can be
5
+ * reopened during the snapshot), so it keeps the full snapshot and its closing re-read.
6
+ */
7
+ export declare function isRestPullMerged(pull: RestPull): boolean;
8
+ /**
9
+ * Batch data for a merged PR, built from the first pull read alone. A terminal tick reports
10
+ * only identity and merge state (`buildTerminalReport`), so the feedback, checks, rules, stack
11
+ * and repository reads of a full snapshot would be discarded unread. The unread resources are
12
+ * listed as unavailable, not presented as empty, so no merge requirement is derived from them.
13
+ */
14
+ export declare function restMergedBatchData(pull: RestPull): BatchPrData;
@@ -0,0 +1,45 @@
1
+ import { restPullRefs } from "./rest-pr-core.mjs";
2
+ import { REST_BATCH_UNAVAILABLE } from "./rest-batch-unavailable.mjs";
3
+ /**
4
+ * A merged pull is immutable, so its first read is final. A closed pull is not (it can be
5
+ * reopened during the snapshot), so it keeps the full snapshot and its closing re-read.
6
+ */
7
+ export function isRestPullMerged(pull) {
8
+ return Boolean(pull.merged_at);
9
+ }
10
+ const NOT_READ = "not read for a merged pull request";
11
+ /**
12
+ * Batch data for a merged PR, built from the first pull read alone. A terminal tick reports
13
+ * only identity and merge state (`buildTerminalReport`), so the feedback, checks, rules, stack
14
+ * and repository reads of a full snapshot would be discarded unread. The unread resources are
15
+ * listed as unavailable, not presented as empty, so no merge requirement is derived from them.
16
+ */
17
+ export function restMergedBatchData(pull) {
18
+ const refs = restPullRefs(pull);
19
+ return {
20
+ nodeId: pull.node_id,
21
+ ...refs,
22
+ state: "MERGED",
23
+ isDraft: pull.draft,
24
+ mergeable: pull.mergeable === true ? "MERGEABLE" : pull.mergeable === false ? "CONFLICTING" : "UNKNOWN",
25
+ mergeStateStatus: pull.mergeable_state.toUpperCase(),
26
+ reviewDecision: null,
27
+ headRepoWithOwner: pull.head.repo?.full_name ?? null,
28
+ reviewRequests: [],
29
+ latestReviews: [],
30
+ reviewThreads: [],
31
+ comments: [],
32
+ changesRequestedReviews: [],
33
+ reviewSummaries: [],
34
+ approvedReviews: [],
35
+ checks: [],
36
+ branchProtection: null,
37
+ stack: null,
38
+ transport: "rest",
39
+ transportUnavailable: [
40
+ ...REST_BATCH_UNAVAILABLE,
41
+ { field: "branchProtection", reason: NOT_READ },
42
+ { field: "mergeRequirements", reason: NOT_READ },
43
+ ],
44
+ };
45
+ }
@@ -1,6 +1,7 @@
1
1
  import { appendEntry, nextEntry } from "../log/log-file.mjs";
2
2
  import { formatRequestEntry, formatResponseEntry } from "../log/session.mjs";
3
3
  import { GitHubRequestError } from "./errors.mjs";
4
+ import { githubFetch } from "./github-fetch.mjs";
4
5
  import { makeAuthHeaders } from "./http-auth.mjs";
5
6
  import { requestWithTokenRetry } from "./http-request.mjs";
6
7
  import { parseRateLimit, parseRetryAfter, redactUrl, sanitizeBody, } from "./http-utils.mjs";
@@ -13,10 +14,12 @@ export async function restText(path, onRateLimit) {
13
14
  appendEntry(formatRequestEntry({ n, kind: "restText", method: "GET", url }));
14
15
  const t0 = performance.now();
15
16
  let authSource = "unknown";
17
+ let credentialFingerprint;
16
18
  const { res, attempt, retryT0 } = await requestWithTokenRetry(async () => {
17
19
  const auth = await makeAuthHeaders();
18
20
  authSource = auth.source;
19
- return fetch(url, { method: "GET", headers: auth.headers, redirect: "manual" });
21
+ credentialFingerprint = auth.fingerprint;
22
+ return githubFetch(url, { method: "GET", headers: auth.headers, redirect: "manual" });
20
23
  }, t0, (response, durationMs) => recordIntermediateResponse({
21
24
  n,
22
25
  kind: "restText",
@@ -25,12 +28,13 @@ export async function restText(path, onRateLimit) {
25
28
  response,
26
29
  durationMs,
27
30
  authSource,
31
+ credentialFingerprint,
28
32
  }));
29
33
  const durationMs = Math.round(performance.now() - retryT0);
30
34
  const rateLimit = parseRateLimit(res.headers) ?? undefined;
31
35
  onRateLimit?.(rateLimit);
32
36
  const retryAfterSeconds = parseRetryAfter(res.headers);
33
- recordApiTelemetry({ kind: "REST", method: "GET", authSource, rateLimit });
37
+ recordApiTelemetry({ kind: "REST", method: "GET", authSource, credentialFingerprint, rateLimit });
34
38
  if ([301, 302, 307, 308].includes(res.status)) {
35
39
  const redirected = await followRestTextRedirect(res, {
36
40
  n,
@@ -101,7 +105,7 @@ async function followRestTextRedirect(res, entry) {
101
105
  const logUrl = redactUrl(location);
102
106
  appendEntry(formatRequestEntry({ n: n2, kind: "restText", method: "GET", url: logUrl }));
103
107
  const t1 = performance.now();
104
- const redirectRes = await fetch(location);
108
+ const redirectRes = await githubFetch(location);
105
109
  appendEntry(formatResponseEntry({
106
110
  n: n2,
107
111
  kind: "restText",
@@ -0,0 +1,4 @@
1
+ import type { RepoInfo } from "./client.mts";
2
+ import type { RawThread } from "./batch-raw-types.mts";
3
+ /** Complete REST reply chain, keeping the caller's opaque thread ID. */
4
+ export declare function readRestRawThread(id: string, repo?: RepoInfo, pr?: number): Promise<RawThread>;
@@ -0,0 +1,35 @@
1
+ import { readRestFeedback } from "./rest-feedback-read.mjs";
2
+ import { resolveRestIdentity, resolveRestThreadRoot, restThreadId } from "./rest-identities.mjs";
3
+ /** Complete REST reply chain, keeping the caller's opaque thread ID. */
4
+ export async function readRestRawThread(id, repo, pr) {
5
+ const identity = repo && pr ? { repo, pr } : await resolveRestIdentity(id, "thread");
6
+ const root = await resolveRestThreadRoot(identity.repo, identity.pr, id);
7
+ const feedback = await readRestFeedback(identity.pr, identity.repo);
8
+ const thread = feedback.threads.find((thread) => thread.id === restThreadId(root));
9
+ if (!thread)
10
+ throw new Error(`Review thread ${id} is absent from the REST snapshot`);
11
+ const comments = (thread.comments ?? []).map((comment) => ({
12
+ id: comment.id,
13
+ body: comment.body,
14
+ url: comment.url,
15
+ author: { login: comment.author, __typename: comment.authorType },
16
+ ...(comment.viewerDidAuthor === true && { viewerDidAuthor: true }),
17
+ ...(comment.authorAssociation && { authorAssociation: comment.authorAssociation }),
18
+ ...(comment.reviewId && { pullRequestReview: { id: comment.reviewId } }),
19
+ path: thread.path,
20
+ line: thread.line,
21
+ startLine: thread.startLine,
22
+ ...(comment.createdAtUnix && {
23
+ createdAt: new Date(comment.createdAtUnix * 1000).toISOString(),
24
+ }),
25
+ }));
26
+ return {
27
+ id,
28
+ ...(thread.isResolved !== undefined && { isResolved: thread.isResolved }),
29
+ ...(thread.isOutdated !== undefined && { isOutdated: thread.isOutdated }),
30
+ path: thread.path,
31
+ line: thread.line,
32
+ startLine: thread.startLine,
33
+ comments: { pageInfo: { hasNextPage: false, endCursor: null }, nodes: comments },
34
+ };
35
+ }
@@ -0,0 +1,2 @@
1
+ /** Installation tokens may read PRs without supporting authenticated-user identity. */
2
+ export declare function readRestViewerLogin(): Promise<string | null>;
@@ -0,0 +1,41 @@
1
+ import { readRest } from "./rest-reader-core.mjs";
2
+ import { GitHubRequestError } from "./errors.mjs";
3
+ import { rateLimitKind } from "./rate-limit-kind.mjs";
4
+ import { isRestSessionRefusal } from "./rest-session-refusal.mjs";
5
+ import { currentRestConditionalKey } from "./rest-conditional-scope.mjs";
6
+ import { makeAuthHeaders } from "./http-auth.mjs";
7
+ import { loadDerived, storeDerived } from "../state/rest-cache.mjs";
8
+ /**
9
+ * GitHub never answers an error status with 304, so a token that cannot read `/user` would be
10
+ * charged for the same denial on every poll tick. The denial is remembered per credential for
11
+ * an hour; a token change, or the hour passing, asks GitHub again.
12
+ */
13
+ const UNAVAILABLE_TTL_MS = 60 * 60 * 1000;
14
+ /** Installation tokens may read PRs without supporting authenticated-user identity. */
15
+ export async function readRestViewerLogin() {
16
+ const key = currentRestConditionalKey();
17
+ const name = key && `viewer-unavailable:${(await makeAuthHeaders()).fingerprint}`;
18
+ if (key && name) {
19
+ const denied = await loadDerived(key, name);
20
+ if (denied && Date.now() - denied.storedAt < UNAVAILABLE_TTL_MS)
21
+ return null;
22
+ }
23
+ try {
24
+ const viewer = await readRest("GET", "/user");
25
+ if (!viewer || typeof viewer !== "object" || Array.isArray(viewer))
26
+ return null;
27
+ const login = viewer.login;
28
+ return typeof login === "string" && login.length > 0 ? login : null;
29
+ }
30
+ catch (error) {
31
+ if (error instanceof GitHubRequestError &&
32
+ [401, 403, 404].includes(error.status) &&
33
+ rateLimitKind(error) === null &&
34
+ !isRestSessionRefusal(error)) {
35
+ if (key && name)
36
+ await storeDerived(key, name, true);
37
+ return null;
38
+ }
39
+ throw error;
40
+ }
41
+ }
@@ -0,0 +1,3 @@
1
+ import type { StackMemberRefs } from "./stack-read.mts";
2
+ /** The first open member can replace merged lower layers only after a fully merged prefix. */
3
+ export declare function verifiedBottomOpenLayer<Pr extends StackMemberRefs>(ordered: readonly Pr[], anchor: number): Pr;
@@ -0,0 +1,14 @@
1
+ import { EXIT, ShepherdError } from "../exit-codes.mjs";
2
+ /** The first open member can replace merged lower layers only after a fully merged prefix. */
3
+ export function verifiedBottomOpenLayer(ordered, anchor) {
4
+ const index = ordered.findIndex((member) => member.state === "OPEN");
5
+ const bottom = ordered[index];
6
+ if (!bottom) {
7
+ throw new ShepherdError(`Native stack for PR #${anchor} has no open layer`, EXIT.TEMPFAIL);
8
+ }
9
+ const predecessor = ordered.slice(0, index).find((member) => member.state !== "MERGED");
10
+ if (predecessor) {
11
+ throw new ShepherdError(`Native stack for PR #${anchor} has PR #${predecessor.number} in state ${predecessor.state} before open PR #${bottom.number}; cannot verify the bottom open layer`, EXIT.TEMPFAIL);
12
+ }
13
+ return bottom;
14
+ }
@@ -0,0 +1,25 @@
1
+ interface RepositoryHandoffFields {
2
+ viewerPermission?: string | null;
3
+ mergeCommitAllowed?: boolean;
4
+ squashMergeAllowed?: boolean;
5
+ rebaseMergeAllowed?: boolean;
6
+ }
7
+ /** What a routed-layer handoff needs from a stack read besides the layers themselves. */
8
+ export interface StackHandoffContext {
9
+ /** Stack identity and each ordered layer's entry position. */
10
+ stack?: {
11
+ id: string;
12
+ positions: number[];
13
+ };
14
+ viewerPermission?: string | null;
15
+ mergeSettings?: Omit<RepositoryHandoffFields, "viewerPermission">;
16
+ }
17
+ export declare function stackHandoffContext(repository: RepositoryHandoffFields, id: string, entries: Array<{
18
+ position: number;
19
+ pullRequest: {
20
+ number: number;
21
+ };
22
+ }>, ordered: Array<{
23
+ number: number;
24
+ }>): StackHandoffContext;
25
+ export {};
@@ -0,0 +1,12 @@
1
+ import { readAllowedMergeMethods } from "../config/merge-method.mjs";
2
+ export function stackHandoffContext(repository, id, entries, ordered) {
3
+ const position = new Map(entries.map((entry) => [entry.pullRequest.number, entry.position]));
4
+ const { viewerPermission, mergeCommitAllowed, squashMergeAllowed, rebaseMergeAllowed } = repository;
5
+ return {
6
+ stack: { id, positions: ordered.map((pr) => position.get(pr.number)) },
7
+ ...(viewerPermission !== undefined && { viewerPermission }),
8
+ ...(readAllowedMergeMethods(repository) && {
9
+ mergeSettings: { mergeCommitAllowed, squashMergeAllowed, rebaseMergeAllowed },
10
+ }),
11
+ };
12
+ }
@@ -0,0 +1,17 @@
1
+ import type { RawBatchResponse, RawContextNode } from "./batch-raw-types.mts";
2
+ import type { RawSummaryPr } from "./poll-summary-raw.mts";
3
+ import type { StackRead } from "./stack-read.mts";
4
+ /** The routing tick's summary read: every layer as read, before projection. */
5
+ export interface StackHandoffSource {
6
+ read: Omit<StackRead<RawSummaryPr>, "ordered">;
7
+ layers: RawSummaryPr[];
8
+ readAt: number;
9
+ }
10
+ export type CheckRunDetail = Pick<Extract<RawContextNode, {
11
+ __typename: "CheckRun";
12
+ }>, "title" | "summary" | "annotations">;
13
+ export declare function checkRunIds(layer: RawSummaryPr): string[];
14
+ /** True when every window `BatchPr`'s first page reads is complete in this summary. */
15
+ export declare function summaryComplete(layer: RawSummaryPr, source: StackHandoffSource): boolean;
16
+ /** The `BatchPr` first page this layer's summary answers, field by field; null if incomplete. */
17
+ export declare function batchResponseFromSummary(layer: RawSummaryPr, source: StackHandoffSource, runs: ReadonlyMap<string, CheckRunDetail>): RawBatchResponse | null;