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.
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +44 -27
- package/bin/api.d.mts +25 -3
- package/bin/api.mjs +51 -13
- package/bin/checks/classify.d.mts +1 -0
- package/bin/checks/classify.mjs +1 -1
- package/bin/checks/conclusions.d.mts +5 -1
- package/bin/checks/conclusions.mjs +8 -2
- package/bin/checks/superseded.d.mts +8 -2
- package/bin/checks/superseded.mjs +24 -7
- package/bin/classify/loader.d.mts +2 -0
- package/bin/classify/loader.mjs +15 -0
- package/bin/classify/standard/author.d.mts +3 -0
- package/bin/classify/standard/author.mjs +10 -0
- package/bin/classify/standard/codecov-report.d.mts +4 -0
- package/bin/classify/standard/codecov-report.mjs +10 -0
- package/bin/classify/standard/coderabbit-notices.d.mts +8 -0
- package/bin/classify/standard/coderabbit-notices.mjs +38 -0
- package/bin/classify/standard/coderabbit-review-summary.d.mts +8 -0
- package/bin/classify/standard/coderabbit-review-summary.mjs +37 -0
- package/bin/classify/standard/codex-notices.d.mts +7 -0
- package/bin/classify/standard/codex-notices.mjs +36 -0
- package/bin/classify/standard/codex-review-summary.d.mts +7 -0
- package/bin/classify/standard/codex-review-summary.mjs +20 -0
- package/bin/classify/standard/dependabot-notices.d.mts +4 -0
- package/bin/classify/standard/dependabot-notices.mjs +15 -0
- package/bin/classify/standard/gemini-notices.d.mts +4 -0
- package/bin/classify/standard/gemini-notices.mjs +13 -0
- package/bin/classify/standard/index.d.mts +4 -0
- package/bin/classify/standard/index.mjs +22 -0
- package/bin/classify/standard/kilo-no-issues.d.mts +4 -0
- package/bin/classify/standard/kilo-no-issues.mjs +17 -0
- package/bin/classify/standard/sourcery-notices.d.mts +8 -0
- package/bin/classify/standard/sourcery-notices.mjs +20 -0
- package/bin/cli/api-usage-formatter.mjs +6 -1
- package/bin/cli/apply-merge-handler.d.mts +3 -0
- package/bin/cli/apply-merge-handler.mjs +73 -0
- package/bin/cli/arg-flags.d.mts +2 -0
- package/bin/cli/arg-flags.mjs +47 -0
- package/bin/cli/args.mjs +10 -41
- package/bin/cli/clean-handler.d.mts +1 -0
- package/bin/cli/clean-handler.mjs +71 -0
- package/bin/cli/default-poll.mjs +3 -0
- package/bin/cli/event-state-scope.d.mts +19 -0
- package/bin/cli/event-state-scope.mjs +60 -0
- package/bin/cli/fix-formatter.mjs +5 -11
- package/bin/cli/handlers.d.mts +0 -1
- package/bin/cli/handlers.mjs +8 -64
- package/bin/cli/help-command-pages.d.mts +62 -18
- package/bin/cli/help-command-pages.mjs +59 -15
- package/bin/cli/help-iterate-poll-pages.d.mts +2 -2
- package/bin/cli/help-iterate-poll-pages.mjs +6 -0
- package/bin/cli/help-log-file-page.d.mts +1 -1
- package/bin/cli/help-log-file-page.mjs +4 -1
- package/bin/cli/help-top-page.d.mts +1 -1
- package/bin/cli/help-top-page.mjs +5 -0
- package/bin/cli/help.d.mts +63 -19
- package/bin/cli/help.mjs +2 -0
- package/bin/cli/iterate-branch-segment.d.mts +2 -0
- package/bin/cli/iterate-branch-segment.mjs +12 -7
- package/bin/cli/iterate-flags.d.mts +7 -1
- package/bin/cli/iterate-flags.mjs +38 -0
- package/bin/cli/iterate-formatter.d.mts +6 -6
- package/bin/cli/iterate-formatter.mjs +56 -22
- package/bin/cli/iterate-instructions.mjs +45 -15
- package/bin/cli/iterate-lean.mjs +39 -14
- package/bin/cli/iterate-merge-formatter.d.mts +6 -0
- package/bin/cli/iterate-merge-formatter.mjs +24 -14
- package/bin/cli/iterate-verbose.mjs +3 -6
- package/bin/cli/list-formatters.mjs +3 -1
- package/bin/cli/mutate-formatter.mjs +10 -5
- package/bin/cli/next-check-format.d.mts +7 -0
- package/bin/cli/next-check-format.mjs +10 -0
- package/bin/cli/playbook-handler.d.mts +5 -0
- package/bin/cli/playbook-handler.mjs +40 -0
- package/bin/cli/poll-handler.mjs +7 -6
- package/bin/cli/poll-summary-formatter.mjs +11 -2
- package/bin/cli/poll-targets.mjs +2 -0
- package/bin/cli/resolve-validators.mjs +2 -2
- package/bin/cli/runner.mjs +6 -1
- package/bin/cli/stack-layer-view.d.mts +33 -0
- package/bin/cli/stack-layer-view.mjs +1 -0
- package/bin/cli/stack-overview.d.mts +10 -28
- package/bin/cli/stack-overview.mjs +39 -14
- package/bin/cli/transport-args.d.mts +5 -0
- package/bin/cli/transport-args.mjs +23 -0
- package/bin/cli/transport-formatter.d.mts +9 -0
- package/bin/cli/transport-formatter.mjs +13 -0
- package/bin/cli-parser.mjs +62 -7
- package/bin/commands/apply-merge-options.d.mts +4 -0
- package/bin/commands/apply-merge-options.mjs +34 -0
- package/bin/commands/apply-merge-output.d.mts +7 -0
- package/bin/commands/apply-merge-output.mjs +20 -0
- package/bin/commands/apply-merge-pull.d.mts +20 -0
- package/bin/commands/apply-merge-pull.mjs +15 -0
- package/bin/commands/apply-merge.d.mts +18 -0
- package/bin/commands/apply-merge.mjs +126 -0
- package/bin/commands/apply-queue-removal.mjs +7 -0
- package/bin/commands/check-annotations.mjs +28 -18
- package/bin/commands/check-execution-context.d.mts +5 -0
- package/bin/commands/check-execution-context.mjs +16 -1
- package/bin/commands/check-fingerprint.d.mts +26 -2
- package/bin/commands/check-fingerprint.mjs +64 -28
- package/bin/commands/check-terminal-report.mjs +11 -1
- package/bin/commands/check-unreported.d.mts +6 -2
- package/bin/commands/check-unreported.mjs +32 -12
- package/bin/commands/check-wait-detectors.d.mts +35 -0
- package/bin/commands/check-wait-detectors.mjs +107 -0
- package/bin/commands/check.d.mts +4 -2
- package/bin/commands/check.mjs +130 -40
- package/bin/commands/event-instructions.d.mts +11 -0
- package/bin/commands/event-instructions.mjs +27 -0
- package/bin/commands/event-mode.d.mts +14 -0
- package/bin/commands/event-mode.mjs +138 -0
- package/bin/commands/iterate/api-usage.mjs +4 -2
- package/bin/commands/iterate/base.mjs +4 -0
- package/bin/commands/iterate/check-blocker-gate.mjs +14 -2
- package/bin/commands/iterate/check-instructions.d.mts +9 -10
- package/bin/commands/iterate/check-instructions.mjs +23 -22
- package/bin/commands/iterate/classify.mjs +19 -5
- package/bin/commands/iterate/escalate.mjs +13 -3
- package/bin/commands/iterate/fix-code.mjs +26 -9
- package/bin/commands/iterate/fix-instruction-threads.d.mts +0 -8
- package/bin/commands/iterate/fix-instruction-threads.mjs +0 -16
- package/bin/commands/iterate/fix-loop-instruction.d.mts +9 -0
- package/bin/commands/iterate/fix-loop-instruction.mjs +35 -0
- package/bin/commands/iterate/helpers.mjs +15 -2
- package/bin/commands/iterate/index.mjs +26 -4
- package/bin/commands/iterate/mark-ready.mjs +50 -10
- package/bin/commands/iterate/merge-plan.d.mts +19 -0
- package/bin/commands/iterate/merge-plan.mjs +88 -0
- package/bin/commands/iterate/merge-state.mjs +3 -0
- package/bin/commands/iterate/merge.d.mts +4 -15
- package/bin/commands/iterate/merge.mjs +18 -51
- package/bin/commands/iterate/merged-base-pull-requests.d.mts +2 -6
- package/bin/commands/iterate/merged-base-pull-requests.mjs +15 -11
- package/bin/commands/iterate/native-stack-rebase.mjs +11 -0
- package/bin/commands/iterate/render.d.mts +8 -2
- package/bin/commands/iterate/render.mjs +28 -42
- package/bin/commands/iterate/stack-trunk-conflict.mjs +17 -1
- package/bin/commands/iterate/stale-ancestry.mjs +4 -1
- package/bin/commands/iterate/stall.d.mts +5 -1
- package/bin/commands/iterate/stall.mjs +19 -7
- package/bin/commands/iterate/thread-mutation-routing.d.mts +1 -0
- package/bin/commands/iterate/thread-mutation-routing.mjs +4 -2
- package/bin/commands/iterate/unreported-required.mjs +5 -2
- package/bin/commands/mark-files-as-viewed.mjs +7 -0
- package/bin/commands/next-check.d.mts +31 -0
- package/bin/commands/next-check.mjs +46 -0
- package/bin/commands/playbook.d.mts +13 -0
- package/bin/commands/playbook.mjs +48 -0
- package/bin/commands/poll-mode.d.mts +8 -0
- package/bin/commands/poll-mode.mjs +14 -0
- package/bin/commands/poll-progress.d.mts +1 -0
- package/bin/commands/poll-progress.mjs +6 -3
- package/bin/commands/poll-quota.d.mts +3 -2
- package/bin/commands/poll-quota.mjs +7 -3
- package/bin/commands/poll-summary-explicit-instructions.d.mts +2 -0
- package/bin/commands/poll-summary-explicit-instructions.mjs +10 -1
- package/bin/commands/poll-summary-instructions.mjs +16 -17
- package/bin/commands/poll-summary.mjs +42 -17
- package/bin/commands/poll.d.mts +0 -1
- package/bin/commands/poll.mjs +11 -19
- package/bin/commands/quota-selection.d.mts +2 -1
- package/bin/commands/quota-selection.mjs +12 -7
- package/bin/commands/resolve-mutate.mjs +33 -5
- package/bin/commands/rest-stack-merge-readiness.d.mts +4 -0
- package/bin/commands/rest-stack-merge-readiness.mjs +74 -0
- package/bin/commands/rule-auto-resolve.mjs +9 -3
- package/bin/commands/shepherd-journal.d.mts +5 -4
- package/bin/commands/shepherd-journal.mjs +9 -8
- package/bin/commands/stack-drain.d.mts +1 -9
- package/bin/commands/stack-drain.mjs +50 -37
- package/bin/commands/stack-handoffs.d.mts +10 -0
- package/bin/commands/stack-handoffs.mjs +25 -0
- package/bin/commands/stack-stall.d.mts +5 -0
- package/bin/commands/stack-stall.mjs +11 -0
- package/bin/commands/stack-work.d.mts +5 -0
- package/bin/commands/stack-work.mjs +32 -0
- package/bin/comments/existing-reply-scan.d.mts +17 -0
- package/bin/comments/existing-reply-scan.mjs +41 -0
- package/bin/comments/rate-limit.mjs +2 -2
- package/bin/comments/resolve.d.mts +7 -1
- package/bin/comments/resolve.mjs +108 -18
- package/bin/comments/rest-reply.d.mts +9 -0
- package/bin/comments/rest-reply.mjs +95 -0
- package/bin/comments/rest-review-mutations.d.mts +22 -0
- package/bin/comments/rest-review-mutations.mjs +125 -0
- package/bin/comments/review-visibility.d.mts +1 -1
- package/bin/comments/review-visibility.mjs +3 -2
- package/bin/comments/sha-poll.mjs +7 -3
- package/bin/comments/thread-visibility.mjs +10 -5
- package/bin/comments/uncertain-replies.d.mts +11 -0
- package/bin/comments/uncertain-replies.mjs +121 -0
- package/bin/comments/uncertain-reply-guards.d.mts +10 -0
- package/bin/comments/uncertain-reply-guards.mjs +94 -0
- package/bin/comments/visible-comments.d.mts +1 -1
- package/bin/comments/visible-comments.mjs +4 -2
- package/bin/config/load.d.mts +37 -1
- package/bin/config/load.mjs +73 -1
- package/bin/config.json +6 -2
- package/bin/exit-codes.d.mts +3 -0
- package/bin/exit-codes.mjs +8 -0
- package/bin/github/api-telemetry-aggregate.d.mts +15 -4
- package/bin/github/api-telemetry-aggregate.mjs +57 -18
- package/bin/github/api-telemetry.d.mts +4 -0
- package/bin/github/api-telemetry.mjs +22 -8
- package/bin/github/apply-review-preflight.d.mts +20 -0
- package/bin/github/apply-review-preflight.mjs +61 -0
- package/bin/github/base-behind-cache.d.mts +15 -0
- package/bin/github/base-behind-cache.mjs +18 -0
- package/bin/github/batch-parse-suites.d.mts +4 -2
- package/bin/github/batch-parse-suites.mjs +6 -1
- package/bin/github/batch-parser-helpers.mjs +40 -2
- package/bin/github/batch-parsers.mjs +1 -0
- package/bin/github/batch-raw-rules.d.mts +26 -0
- package/bin/github/batch-raw-types.d.mts +8 -6
- package/bin/github/batch-stack-evidence.d.mts +28 -0
- package/bin/github/batch-stack-evidence.mjs +62 -0
- package/bin/github/batch.d.mts +15 -2
- package/bin/github/batch.mjs +34 -17
- package/bin/github/check-annotations-batch.d.mts +0 -5
- package/bin/github/check-annotations-batch.mjs +25 -4
- package/bin/github/check-annotations.mjs +3 -1
- package/bin/github/client.d.mts +8 -19
- package/bin/github/client.mjs +45 -13
- package/bin/github/fingerprint-fields.d.mts +8 -0
- package/bin/github/fingerprint-fields.mjs +6 -1
- package/bin/github/fingerprint.d.mts +4 -2
- package/bin/github/fingerprint.mjs +6 -38
- package/bin/github/github-fetch.d.mts +2 -0
- package/bin/github/github-fetch.mjs +19 -0
- package/bin/github/gql/base-behind.gql +3 -0
- package/bin/github/gql/batch-pr-page.gql +16 -0
- package/bin/github/gql/batch-pr.gql +57 -0
- package/bin/github/gql/commit-check-contexts.gql +17 -0
- package/bin/github/gql/get-pr-body.gql +1 -0
- package/bin/github/gql/poll-stack-summary.gql +1 -0
- package/bin/github/gql/poll-summary-check-contexts.gql +5 -0
- package/bin/github/gql/poll-summary-fragment.gql +65 -15
- package/bin/github/gql/stack-handoff-check-runs.gql +42 -0
- package/bin/github/graphql-http.mjs +9 -4
- package/bin/github/graphql-internal-retry.d.mts +2 -0
- package/bin/github/graphql-internal-retry.mjs +1 -1
- package/bin/github/graphql-quota-probe.d.mts +6 -0
- package/bin/github/graphql-quota-probe.mjs +56 -0
- package/bin/github/graphql-session-refusal.d.mts +8 -0
- package/bin/github/graphql-session-refusal.mjs +14 -0
- package/bin/github/http-request.d.mts +1 -1
- package/bin/github/http-request.mjs +22 -6
- package/bin/github/http-utils.mjs +6 -0
- package/bin/github/merge-target-rules.d.mts +12 -3
- package/bin/github/merge-target-rules.mjs +71 -34
- package/bin/github/mutation-policy.d.mts +6 -0
- package/bin/github/mutation-policy.mjs +21 -0
- package/bin/github/poll-summary-annotation-probe.mjs +17 -10
- package/bin/github/poll-summary-check-blockers.d.mts +1 -1
- package/bin/github/poll-summary-check-blockers.mjs +2 -2
- package/bin/github/poll-summary-check-hydration.mjs +25 -10
- package/bin/github/poll-summary-checks.d.mts +2 -2
- package/bin/github/poll-summary-checks.mjs +9 -6
- package/bin/github/poll-summary-command.d.mts +2 -0
- package/bin/github/poll-summary-command.mjs +24 -0
- package/bin/github/poll-summary-fingerprint.d.mts +1 -1
- package/bin/github/poll-summary-fingerprint.mjs +4 -2
- package/bin/github/poll-summary-handoff-fields.d.mts +3 -0
- package/bin/github/poll-summary-handoff-fields.mjs +73 -0
- package/bin/github/poll-summary-projector.d.mts +1 -1
- package/bin/github/poll-summary-projector.mjs +17 -24
- package/bin/github/poll-summary-raw.d.mts +70 -10
- package/bin/github/poll-summary-readiness.mjs +4 -1
- package/bin/github/poll-summary-rest-queue.d.mts +3 -0
- package/bin/github/poll-summary-rest-queue.mjs +12 -0
- package/bin/github/poll-summary-review.d.mts +1 -1
- package/bin/github/poll-summary-review.mjs +23 -11
- package/bin/github/poll-summary-route.mjs +19 -3
- package/bin/github/poll-summary-stack-page.d.mts +11 -0
- package/bin/github/poll-summary-stack-page.mjs +27 -0
- package/bin/github/poll-summary-unreported.d.mts +3 -1
- package/bin/github/poll-summary-unreported.mjs +6 -3
- package/bin/github/poll-summary.d.mts +4 -1
- package/bin/github/poll-summary.mjs +47 -33
- package/bin/github/queries.d.mts +7 -3
- package/bin/github/queries.mjs +8 -4
- package/bin/github/rate-limit-sample.d.mts +7 -0
- package/bin/github/rate-limit-sample.mjs +12 -0
- package/bin/github/reply-recovery-read.d.mts +50 -0
- package/bin/github/reply-recovery-read.mjs +118 -0
- package/bin/github/reply-thread-transcripts.d.mts +0 -1
- package/bin/github/reply-thread-transcripts.mjs +24 -1
- package/bin/github/rest-annotation-read.d.mts +5 -0
- package/bin/github/rest-annotation-read.mjs +44 -0
- package/bin/github/rest-batch-read.d.mts +12 -0
- package/bin/github/rest-batch-read.mjs +57 -0
- package/bin/github/rest-batch-snapshot.d.mts +30 -0
- package/bin/github/rest-batch-snapshot.mjs +115 -0
- package/bin/github/rest-batch-unavailable.d.mts +5 -0
- package/bin/github/rest-batch-unavailable.mjs +16 -0
- package/bin/github/rest-check-read.d.mts +34 -0
- package/bin/github/rest-check-read.mjs +124 -0
- package/bin/github/rest-comment-authorship.d.mts +7 -0
- package/bin/github/rest-comment-authorship.mjs +11 -0
- package/bin/github/rest-conditional-scope.d.mts +20 -0
- package/bin/github/rest-conditional-scope.mjs +44 -0
- package/bin/github/rest-explicit-summary-read.d.mts +3 -0
- package/bin/github/rest-explicit-summary-read.mjs +8 -0
- package/bin/github/rest-feedback-read.d.mts +36 -0
- package/bin/github/rest-feedback-read.mjs +147 -0
- package/bin/github/rest-feedback-validation.d.mts +5 -0
- package/bin/github/rest-feedback-validation.mjs +28 -0
- package/bin/github/rest-http.d.mts +12 -0
- package/bin/github/rest-http.mjs +108 -23
- package/bin/github/rest-identities.d.mts +22 -0
- package/bin/github/rest-identities.mjs +134 -0
- package/bin/github/rest-merge-stack-guard.d.mts +14 -0
- package/bin/github/rest-merge-stack-guard.mjs +41 -0
- package/bin/github/rest-merge.d.mts +29 -0
- package/bin/github/rest-merge.mjs +56 -0
- package/bin/github/rest-merged-base-read.d.mts +9 -0
- package/bin/github/rest-merged-base-read.mjs +48 -0
- package/bin/github/rest-pr-core.d.mts +52 -0
- package/bin/github/rest-pr-core.mjs +60 -0
- package/bin/github/rest-reader-core.d.mts +16 -0
- package/bin/github/rest-reader-core.mjs +154 -0
- package/bin/github/rest-review-read.d.mts +11 -0
- package/bin/github/rest-review-read.mjs +47 -0
- package/bin/github/rest-rules-read.d.mts +9 -0
- package/bin/github/rest-rules-read.mjs +154 -0
- package/bin/github/rest-session-refusal.d.mts +5 -0
- package/bin/github/rest-session-refusal.mjs +21 -0
- package/bin/github/rest-snapshot-context.d.mts +10 -0
- package/bin/github/rest-snapshot-context.mjs +1 -0
- package/bin/github/rest-stack-read.d.mts +21 -0
- package/bin/github/rest-stack-read.mjs +47 -0
- package/bin/github/rest-stack-summary.d.mts +8 -0
- package/bin/github/rest-stack-summary.mjs +62 -0
- package/bin/github/rest-summary-read.d.mts +7 -0
- package/bin/github/rest-summary-read.mjs +112 -0
- package/bin/github/rest-terminal-batch.d.mts +14 -0
- package/bin/github/rest-terminal-batch.mjs +45 -0
- package/bin/github/rest-text.mjs +7 -3
- package/bin/github/rest-thread-read.d.mts +4 -0
- package/bin/github/rest-thread-read.mjs +35 -0
- package/bin/github/rest-viewer-read.d.mts +2 -0
- package/bin/github/rest-viewer-read.mjs +41 -0
- package/bin/github/stack-bottom.d.mts +3 -0
- package/bin/github/stack-bottom.mjs +14 -0
- package/bin/github/stack-handoff-context.d.mts +25 -0
- package/bin/github/stack-handoff-context.mjs +12 -0
- package/bin/github/stack-handoff-page.d.mts +17 -0
- package/bin/github/stack-handoff-page.mjs +306 -0
- package/bin/github/stack-handoff.d.mts +16 -0
- package/bin/github/stack-handoff.mjs +115 -0
- package/bin/github/stack-order.d.mts +6 -0
- package/bin/github/stack-order.mjs +13 -0
- package/bin/github/stack-read.d.mts +7 -5
- package/bin/github/stack-read.mjs +22 -24
- package/bin/github/stack-size-hint.d.mts +3 -0
- package/bin/github/stack-size-hint.mjs +14 -0
- package/bin/github/suggestion-thread.mjs +27 -1
- package/bin/github/thread-comments.mjs +9 -1
- package/bin/github/transport-evidence.d.mts +20 -0
- package/bin/github/transport-evidence.mjs +26 -0
- package/bin/github/transport-mode.d.mts +2 -0
- package/bin/github/transport-mode.mjs +5 -0
- package/bin/github/transport.d.mts +19 -0
- package/bin/github/transport.mjs +126 -0
- package/bin/github/unsupported-rest.d.mts +4 -0
- package/bin/github/unsupported-rest.mjs +7 -0
- package/bin/mcp/server.mjs +52 -3
- package/bin/merge-status/derive.d.mts +2 -0
- package/bin/merge-status/derive.mjs +17 -13
- package/bin/merge-status/required-check-requirements.d.mts +7 -0
- package/bin/merge-status/required-check-requirements.mjs +15 -0
- package/bin/merge-status/requirements-format.d.mts +5 -0
- package/bin/merge-status/requirements-format.mjs +41 -12
- package/bin/merge-status/requirements.mjs +18 -7
- package/bin/state/base.mjs +41 -0
- package/bin/state/durable-state.d.mts +6 -0
- package/bin/state/durable-state.mjs +41 -0
- package/bin/state/graphql-quota-policy.mjs +23 -16
- package/bin/state/merge-request.d.mts +25 -0
- package/bin/state/merge-request.mjs +145 -0
- package/bin/state/pr-fingerprint.d.mts +15 -0
- package/bin/state/pr-fingerprint.mjs +22 -7
- package/bin/state/rest-cache.d.mts +3 -0
- package/bin/state/rest-cache.mjs +1 -0
- package/bin/state/rest-snapshot-report.d.mts +21 -0
- package/bin/state/rest-snapshot-report.mjs +52 -0
- package/bin/state/seen-comments.d.mts +3 -0
- package/bin/state/seen-comments.mjs +18 -0
- package/bin/types/api-usage.d.mts +9 -1
- package/bin/types/escalate.d.mts +1 -1
- package/bin/types/github.d.mts +23 -9
- package/bin/types/iterate.d.mts +24 -2
- package/bin/types/merge-action.d.mts +1 -1
- package/bin/types/merge-requirements.d.mts +7 -7
- package/bin/types/next-check.d.mts +12 -0
- package/bin/types/next-check.mjs +1 -0
- package/bin/types/poll-summary.d.mts +21 -0
- package/bin/types/report.d.mts +13 -1
- package/bin/types/review-thread.d.mts +1 -1
- package/bin/types.d.mts +1 -0
- package/bin/types.mjs +1 -0
- package/package.json +3 -2
- package/plugins/pr-shepherd/.codex-plugin/plugin.json +1 -1
- package/plugins/pr-shepherd/.codex.mcp.json +1 -1
- package/plugins/pr-shepherd/.mcp.json +1 -1
- package/plugins/pr-shepherd/skills/mark-files-as-viewed/SKILL.md +1 -1
- package/plugins/pr-shepherd/skills/pr-shepherd/SKILL.md +14 -51
- package/plugins/pr-shepherd/skills/pr-shepherd/references/ci-failure-triage.md +12 -16
- package/plugins/pr-shepherd/skills/pr-shepherd/references/cloud-event-loop.md +14 -0
- package/plugins/pr-shepherd/skills/pr-shepherd/references/create-pr.md +10 -0
- package/plugins/pr-shepherd/skills/pr-shepherd/references/fix-code-loop.md +10 -0
- package/plugins/pr-shepherd/skills/pr-shepherd/references/mcp-fallback.md +9 -0
- package/plugins/pr-shepherd/skills/reduce-pr-noise/references/classifiers.md +2 -0
- package/bin/github/gql/pr-fingerprint.gql +0 -75
- package/plugins/pr-shepherd/skills/pr-shepherd/references/journal.md +0 -7
- package/plugins/pr-shepherd/skills/pr-shepherd/references/review-mutations.md +0 -9
- package/plugins/pr-shepherd/skills/pr-shepherd/references/stack-merge.md +0 -7
package/bin/github/batch.mjs
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { recordThreadIdentity } from "./rest-identities.mjs";
|
|
2
|
+
import { githubOperation, runWithGithubTransport } from "./transport.mjs";
|
|
3
|
+
import { fetchRestPrBatch } from "./rest-batch-read.mjs";
|
|
1
4
|
import { graphqlWithRateLimit } from "./client.mjs";
|
|
2
5
|
import { hydrateThreadCommentPages } from "./thread-comments.mjs";
|
|
3
6
|
import { BATCH_PR_QUERY, BATCH_PR_RECEIPT_QUERY } from "./queries.mjs";
|
|
@@ -5,30 +8,24 @@ import { prepareBatchReceiptEvidence } from "./batch-receipt-evidence.mjs";
|
|
|
5
8
|
import { GitHubRequestError, isRetryableGraphQlResourceLimit, } from "./errors.mjs";
|
|
6
9
|
import { rateLimitKind } from "./rate-limit-kind.mjs";
|
|
7
10
|
import { parseRawPr } from "./batch-parsers.mjs";
|
|
8
|
-
import { parseCheckSuitesComplete, parseHeadCheckSuitesEmpty,
|
|
11
|
+
import { parseCheckSuitesComplete, parseHeadCheckSuitesEmpty, workflowSuites, parseSuiteStartupFailures, } from "./batch-parse-suites.mjs";
|
|
9
12
|
import { mergeStartupFailureChecks } from "../checks/startup-failures.mjs";
|
|
10
13
|
import { paginateBatchConnections } from "./batch-page.mjs";
|
|
11
14
|
import { requireRawPr } from "./batch-response.mjs";
|
|
12
15
|
import { hydrateMergeQueueChecks } from "./merge-queue-checks.mjs";
|
|
13
16
|
import { fingerprintFromRaw } from "./fingerprint.mjs";
|
|
17
|
+
import { stackEvidenceFromRaw } from "./batch-stack-evidence.mjs";
|
|
18
|
+
import { takeStackHandoff } from "./stack-handoff.mjs";
|
|
14
19
|
function onlyReceiptSummaryErrors(errors) {
|
|
15
20
|
return (!!errors?.length &&
|
|
16
21
|
errors.every((error) => Array.isArray(error.path) &&
|
|
17
22
|
error.path[0] === "repository" &&
|
|
18
23
|
error.path[1] === "receiptSummary"));
|
|
19
24
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
*/
|
|
23
|
-
export async function fetchPrBatch(pr, repo, opts = {}) {
|
|
24
|
-
const variables = {
|
|
25
|
-
owner: repo.owner,
|
|
26
|
-
repo: repo.name,
|
|
27
|
-
pr,
|
|
28
|
-
};
|
|
29
|
-
let result;
|
|
25
|
+
async function readBatchFirstPage(pr, repo, opts) {
|
|
26
|
+
const variables = { owner: repo.owner, repo: repo.name, pr };
|
|
30
27
|
try {
|
|
31
|
-
|
|
28
|
+
return await graphqlWithRateLimit(opts.includeReceiptSummary ? BATCH_PR_RECEIPT_QUERY : BATCH_PR_QUERY, variables);
|
|
32
29
|
}
|
|
33
30
|
catch (error) {
|
|
34
31
|
if (!opts.includeReceiptSummary ||
|
|
@@ -39,9 +36,23 @@ export async function fetchPrBatch(pr, repo, opts = {}) {
|
|
|
39
36
|
throw error;
|
|
40
37
|
// Receipt evidence is optional; a resource-limited combined query or an
|
|
41
38
|
// error confined to its sibling must not prevent the ordinary snapshot.
|
|
42
|
-
|
|
39
|
+
return graphqlWithRateLimit(BATCH_PR_QUERY, variables);
|
|
43
40
|
}
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Fetch all PR data needed for a `shepherd check` in one (or a few, if paginating) GraphQL requests.
|
|
44
|
+
*/
|
|
45
|
+
async function fetchGraphqlPrBatch(pr, repo, opts = {}, reuse) {
|
|
46
|
+
const handoff = await takeStackHandoff(repo, pr); // a routed stack layer's first read
|
|
47
|
+
const result = handoff ? { data: handoff } : await readBatchFirstPage(pr, repo, opts);
|
|
44
48
|
const raw = requireRawPr(result.data, pr, repo);
|
|
49
|
+
const fingerprint = fingerprintFromRaw(raw, result.data.repository?.viewerPermission ?? null, result.data.viewer?.login ?? null);
|
|
50
|
+
// Decide reuse from the first page alone, before any supplement is paid for.
|
|
51
|
+
const reused = reuse && (await reuse(fingerprint));
|
|
52
|
+
const baseTipOid = raw.baseRef?.target?.oid;
|
|
53
|
+
const stackEvidence = stackEvidenceFromRaw(raw, result.data);
|
|
54
|
+
if (reused)
|
|
55
|
+
return { reused, ...(baseTipOid && { baseTipOid }), ...(stackEvidence && { stackEvidence }) };
|
|
45
56
|
const queueRateLimit = await hydrateMergeQueueChecks(raw, repo, result.rateLimit);
|
|
46
57
|
const paged = await paginateBatchConnections(pr, repo, raw, opts, queueRateLimit);
|
|
47
58
|
const threadPages = await hydrateThreadCommentPages(paged.threads, paged.rateLimit);
|
|
@@ -54,6 +65,12 @@ export async function fetchPrBatch(pr, repo, opts = {}) {
|
|
|
54
65
|
// Malformed supplemental evidence must not discard a complete BatchPr.
|
|
55
66
|
}
|
|
56
67
|
}
|
|
68
|
+
for (const thread of threadPages.threads) {
|
|
69
|
+
const root = thread.comments.nodes[0];
|
|
70
|
+
const numericId = root?.url?.match(/discussion_r([0-9]+)/)?.[1];
|
|
71
|
+
if (numericId)
|
|
72
|
+
await recordThreadIdentity(repo, pr, thread.id, numericId);
|
|
73
|
+
}
|
|
57
74
|
const data = parseRawPr(raw, threadPages.threads, paged.comments, paged.changesRequested, paged.reviewSummaries, paged.approvedReviews, paged.checks, result.data.repository);
|
|
58
75
|
const viewerLogin = result.data.viewer?.login;
|
|
59
76
|
if (viewerLogin)
|
|
@@ -61,15 +78,15 @@ export async function fetchPrBatch(pr, repo, opts = {}) {
|
|
|
61
78
|
data.checks = mergeStartupFailureChecks(data.checks, parseSuiteStartupFailures(raw));
|
|
62
79
|
return {
|
|
63
80
|
data,
|
|
64
|
-
fingerprint
|
|
81
|
+
fingerprint,
|
|
65
82
|
rateLimit: threadPages.rateLimit ?? paged.rateLimit ?? result.rateLimit,
|
|
66
83
|
...(parseCheckSuitesComplete(raw) && { checkSuitesComplete: true }),
|
|
67
84
|
...(parseHeadCheckSuitesEmpty(raw) && { headCheckSuitesEmpty: true }),
|
|
68
85
|
...workflowSuites(raw),
|
|
69
86
|
...(receiptSummary && { receiptSummary }),
|
|
87
|
+
...(stackEvidence && { stackEvidence }),
|
|
70
88
|
};
|
|
71
89
|
}
|
|
72
|
-
function
|
|
73
|
-
|
|
74
|
-
return suites.length > 0 ? { headWorkflowSuites: suites } : {};
|
|
90
|
+
export function fetchPrBatch(pr, repo, opts = {}, reuse) {
|
|
91
|
+
return githubOperation("BatchPr", () => runWithGithubTransport("graphql", () => fetchGraphqlPrBatch(pr, repo, opts, reuse)), () => fetchRestPrBatch(pr, repo, opts));
|
|
75
92
|
}
|
|
@@ -8,10 +8,5 @@ interface CheckAnnotationBatchResult {
|
|
|
8
8
|
annotations: Map<string, CheckAnnotation[]>;
|
|
9
9
|
failures: AnnotationBatchFailure[];
|
|
10
10
|
}
|
|
11
|
-
/**
|
|
12
|
-
* First annotation page for every uncached id, in chunks of 20. Further pages
|
|
13
|
-
* use the single-node query and only run when that first page has `hasNextPage`.
|
|
14
|
-
* A retryable rate limit aborts the remaining chunks and pages.
|
|
15
|
-
*/
|
|
16
11
|
export declare function fetchCheckRunAnnotationsBatch(checkRunIds: string[], cacheOpts?: AnnotationCacheOptions): Promise<CheckAnnotationBatchResult>;
|
|
17
12
|
export {};
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { githubOperation, runWithGithubTransport, isGithubReadFallbackError, } from "./transport.mjs";
|
|
2
|
+
import { mapPool } from "../util/pool.mjs";
|
|
3
|
+
import { ensureRestCheckIdentities } from "./rest-annotation-read.mjs";
|
|
1
4
|
import { pollRateLimitRetryAfterMs } from "../commands/poll-quota.mjs";
|
|
2
5
|
import { readFreshCheckAnnotations, } from "./check-annotation-cache.mjs";
|
|
3
6
|
import {} from "./check-annotation-shape.mjs";
|
|
@@ -24,7 +27,7 @@ function retryableRateLimit(err) {
|
|
|
24
27
|
* use the single-node query and only run when that first page has `hasNextPage`.
|
|
25
28
|
* A retryable rate limit aborts the remaining chunks and pages.
|
|
26
29
|
*/
|
|
27
|
-
|
|
30
|
+
async function fetchGraphqlCheckRunAnnotationsBatch(checkRunIds, cacheOpts) {
|
|
28
31
|
const annotations = new Map();
|
|
29
32
|
const failures = [];
|
|
30
33
|
const cached = await Promise.all(checkRunIds.map((id) => readFreshCheckAnnotations(id, cacheOpts)));
|
|
@@ -48,7 +51,7 @@ async function fetchChunk(chunk, annotations, failures, cacheOpts) {
|
|
|
48
51
|
await applyBatchNodes(chunk, nodes, annotations, failures, cacheOpts);
|
|
49
52
|
}
|
|
50
53
|
catch (err) {
|
|
51
|
-
if (retryableRateLimit(err))
|
|
54
|
+
if (retryableRateLimit(err) || isGithubReadFallbackError(err))
|
|
52
55
|
throw err;
|
|
53
56
|
// A non-rate-limit batch failure (one NOT_FOUND or FORBIDDEN node rejects
|
|
54
57
|
// the whole `nodes(ids:)` request) must not drop the other ids.
|
|
@@ -67,7 +70,7 @@ async function applyBatchNodes(chunk, nodes, annotations, failures, cacheOpts) {
|
|
|
67
70
|
annotations.set(id, await fetchCheckRunAnnotations(id, cacheOpts, node.annotations));
|
|
68
71
|
}
|
|
69
72
|
catch (err) {
|
|
70
|
-
if (retryableRateLimit(err))
|
|
73
|
+
if (retryableRateLimit(err) || isGithubReadFallbackError(err))
|
|
71
74
|
throw err;
|
|
72
75
|
failures.push({ checkRunId: id, error: err });
|
|
73
76
|
}
|
|
@@ -80,7 +83,7 @@ async function fetchChunkOneByOne(chunk, annotations, failures, cacheOpts) {
|
|
|
80
83
|
annotations.set(id, await fetchCheckRunAnnotations(id, cacheOpts));
|
|
81
84
|
}
|
|
82
85
|
catch (err) {
|
|
83
|
-
if (retryableRateLimit(err))
|
|
86
|
+
if (retryableRateLimit(err) || isGithubReadFallbackError(err))
|
|
84
87
|
throw err;
|
|
85
88
|
failures.push({ checkRunId: id, error: err });
|
|
86
89
|
}
|
|
@@ -90,3 +93,21 @@ async function requestFirstPages(ids) {
|
|
|
90
93
|
const res = await graphql(CHECK_RUN_ANNOTATIONS_BATCH_QUERY, { ids }, { allowPartialData: true });
|
|
91
94
|
return res.data.nodes ?? [];
|
|
92
95
|
}
|
|
96
|
+
export function fetchCheckRunAnnotationsBatch(checkRunIds, cacheOpts) {
|
|
97
|
+
return githubOperation("CheckRunAnnotationsBatch", () => runWithGithubTransport("graphql", () => fetchGraphqlCheckRunAnnotationsBatch(checkRunIds, cacheOpts)), async () => {
|
|
98
|
+
const annotations = new Map();
|
|
99
|
+
const failures = [];
|
|
100
|
+
await ensureRestCheckIdentities(checkRunIds, cacheOpts);
|
|
101
|
+
await mapPool([...new Set(checkRunIds)], 4, async (id) => {
|
|
102
|
+
try {
|
|
103
|
+
annotations.set(id, await fetchCheckRunAnnotations(id, cacheOpts));
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
if (retryableRateLimit(error))
|
|
107
|
+
throw error;
|
|
108
|
+
failures.push({ checkRunId: id, error });
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
return { annotations, failures };
|
|
112
|
+
});
|
|
113
|
+
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { githubOperation } from "./transport.mjs";
|
|
2
|
+
import { readRestCheckAnnotations } from "./rest-annotation-read.mjs";
|
|
1
3
|
import { readFreshCheckAnnotations, storeCheckAnnotations, } from "./check-annotation-cache.mjs";
|
|
2
4
|
import { collectAnnotations } from "./check-annotation-pages.mjs";
|
|
3
5
|
/**
|
|
@@ -14,7 +16,7 @@ export async function fetchCheckRunAnnotations(checkRunId, cacheOpts, initialPag
|
|
|
14
16
|
if (cached)
|
|
15
17
|
return cached;
|
|
16
18
|
}
|
|
17
|
-
const annotations = await collectAnnotations(checkRunId, initialPage);
|
|
19
|
+
const annotations = await githubOperation("CheckRunAnnotations", () => collectAnnotations(checkRunId, initialPage), () => readRestCheckAnnotations(checkRunId, cacheOpts));
|
|
18
20
|
await storeCheckAnnotations(checkRunId, annotations, cacheOpts);
|
|
19
21
|
return annotations;
|
|
20
22
|
}
|
package/bin/github/client.d.mts
CHANGED
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* High-level GitHub client — wraps http.mts for application-level concerns.
|
|
3
|
-
*
|
|
4
|
-
* All GitHub I/O goes through native fetch (via http.mts); the `gh` CLI is no
|
|
5
|
-
* longer used for GitHub API calls, but may be invoked as an auth-token
|
|
6
|
-
* fallback via `gh auth token` when neither GH_TOKEN nor GITHUB_TOKEN is set.
|
|
7
|
-
*/
|
|
8
1
|
import type { MergeableState, MergeStateStatus } from "../types.mts";
|
|
9
2
|
export type { RateLimitInfo } from "./http.mts";
|
|
10
3
|
export { graphql, graphqlWithRateLimit } from "./http.mts";
|
|
@@ -22,22 +15,11 @@ export declare function getRepoInfo(): Promise<RepoInfo>;
|
|
|
22
15
|
* Returns null if no open PR is found.
|
|
23
16
|
*/
|
|
24
17
|
export declare function getCurrentPrNumber(): Promise<number | null>;
|
|
25
|
-
/** Returns the PR number for a given branch, or null if no open PR is found. */
|
|
26
|
-
export declare function getPrNumberForBranch(branch: string, owner: string, repo: string): Promise<number | null>;
|
|
27
|
-
/** Returns the `headRefOid` (commit SHA) of the given PR as reported by GitHub. */
|
|
28
|
-
export declare function getPrHeadSha(pr: number, owner: string, name: string): Promise<string>;
|
|
29
|
-
/** Fetches the node ID and body text for a PR. GitHub returns null body for empty bodies — coerced to "". */
|
|
30
|
-
export declare function getPullRequestBody(pr: number, owner: string, name: string): Promise<{
|
|
31
|
-
nodeId: string;
|
|
32
|
-
body: string;
|
|
33
|
-
}>;
|
|
34
|
-
/** Overwrites the PR body. */
|
|
35
|
-
export declare function updatePullRequestBody(pullRequestId: string, body: string): Promise<void>;
|
|
36
18
|
/**
|
|
37
19
|
* Fetches PR state, `mergeable`, and `mergeStateStatus` via the REST API.
|
|
38
20
|
*
|
|
39
21
|
* Used when the GraphQL API returns `UNKNOWN` for mergeability or before a
|
|
40
|
-
* READY state. The same response carries state so a concurrent merge or
|
|
22
|
+
* READY state. The read is conditional inside a PR's REST conditional scope. The same response carries state so a concurrent merge or
|
|
41
23
|
* close can supersede the earlier GraphQL snapshot without another request.
|
|
42
24
|
*/
|
|
43
25
|
export declare function getMergeableState(pr: number, owner: string, repo: string): Promise<{
|
|
@@ -46,3 +28,10 @@ export declare function getMergeableState(pr: number, owner: string, repo: strin
|
|
|
46
28
|
state?: "OPEN" | "CLOSED" | "MERGED";
|
|
47
29
|
}>;
|
|
48
30
|
export declare function getCurrentBranch(): Promise<string>;
|
|
31
|
+
export declare function getPrNumberForBranch(branch: string, owner: string, name: string): Promise<number | null>;
|
|
32
|
+
export declare function getPrHeadSha(pr: number, owner: string, name: string): Promise<string>;
|
|
33
|
+
export declare function getPullRequestBody(pr: number, owner: string, name: string): Promise<{
|
|
34
|
+
nodeId: string;
|
|
35
|
+
body: string;
|
|
36
|
+
}>;
|
|
37
|
+
export declare function updatePullRequestBody(pullRequestId: string, body: string): Promise<void>;
|
package/bin/github/client.mjs
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import { githubOperation } from "./transport.mjs";
|
|
2
|
+
import { readRestPull } from "./rest-pr-core.mjs";
|
|
3
|
+
import { readRest, readRestPages, restRepoPath, restObject, restNumber, restString, } from "./rest-reader-core.mjs";
|
|
4
|
+
import { recordRestIdentity, resolveRestIdentity } from "./rest-identities.mjs";
|
|
1
5
|
/* eslint-disable max-lines */
|
|
2
6
|
/**
|
|
3
7
|
* High-level GitHub client — wraps http.mts for application-level concerns.
|
|
@@ -44,17 +48,12 @@ export async function getCurrentPrNumber() {
|
|
|
44
48
|
}
|
|
45
49
|
}
|
|
46
50
|
/** Returns the PR number for a given branch, or null if no open PR is found. */
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
return result.data.repository?.pullRequests.nodes[0]?.number ?? null;
|
|
51
|
-
}
|
|
52
|
-
catch {
|
|
53
|
-
return null;
|
|
54
|
-
}
|
|
51
|
+
async function getGraphqlPrNumberForBranch(branch, owner, repo) {
|
|
52
|
+
const result = await httpGraphql(PR_NUMBER_BY_BRANCH_QUERY, { owner, repo, branch });
|
|
53
|
+
return result.data.repository?.pullRequests.nodes[0]?.number ?? null;
|
|
55
54
|
}
|
|
56
55
|
/** Returns the `headRefOid` (commit SHA) of the given PR as reported by GitHub. */
|
|
57
|
-
|
|
56
|
+
async function getGraphqlPrHeadSha(pr, owner, name) {
|
|
58
57
|
const result = await httpGraphql(GET_PR_HEAD_SHA_QUERY, { owner, repo: name, pr });
|
|
59
58
|
const sha = result.data.repository?.pullRequest?.headRefOid;
|
|
60
59
|
if (!sha) {
|
|
@@ -68,7 +67,7 @@ export async function getPrHeadSha(pr, owner, name) {
|
|
|
68
67
|
return sha;
|
|
69
68
|
}
|
|
70
69
|
/** Fetches the node ID and body text for a PR. GitHub returns null body for empty bodies — coerced to "". */
|
|
71
|
-
|
|
70
|
+
async function getGraphqlPullRequestBody(pr, owner, name) {
|
|
72
71
|
const result = await httpGraphql(GET_PR_BODY_QUERY, { owner, repo: name, pr });
|
|
73
72
|
const pullRequest = result.data.repository?.pullRequest;
|
|
74
73
|
if (!pullRequest) {
|
|
@@ -77,24 +76,31 @@ export async function getPullRequestBody(pr, owner, name) {
|
|
|
77
76
|
: "PR not found or access denied";
|
|
78
77
|
throw new Error(`Could not fetch body for ${owner}/${name} PR #${pr}: ${detail}`);
|
|
79
78
|
}
|
|
79
|
+
if (pullRequest.fullDatabaseId != null) {
|
|
80
|
+
if (typeof pullRequest.fullDatabaseId !== "string")
|
|
81
|
+
restNumber(pullRequest.fullDatabaseId, "pull request fullDatabaseId");
|
|
82
|
+
await recordRestIdentity({ owner, name }, pr, pullRequest.id, pullRequest.fullDatabaseId, "pull");
|
|
83
|
+
}
|
|
80
84
|
return {
|
|
81
85
|
nodeId: pullRequest.id,
|
|
82
86
|
body: pullRequest.body ?? "",
|
|
83
87
|
};
|
|
84
88
|
}
|
|
85
89
|
/** Overwrites the PR body. */
|
|
86
|
-
|
|
90
|
+
async function updateGraphqlPullRequestBody(pullRequestId, body) {
|
|
87
91
|
await httpGraphql(UPDATE_PR_BODY_MUTATION, { pullRequestId, body });
|
|
88
92
|
}
|
|
89
93
|
/**
|
|
90
94
|
* Fetches PR state, `mergeable`, and `mergeStateStatus` via the REST API.
|
|
91
95
|
*
|
|
92
96
|
* Used when the GraphQL API returns `UNKNOWN` for mergeability or before a
|
|
93
|
-
* READY state. The same response carries state so a concurrent merge or
|
|
97
|
+
* READY state. The read is conditional inside a PR's REST conditional scope. The same response carries state so a concurrent merge or
|
|
94
98
|
* close can supersede the earlier GraphQL snapshot without another request.
|
|
95
99
|
*/
|
|
96
100
|
export async function getMergeableState(pr, owner, repo) {
|
|
97
|
-
|
|
101
|
+
// Inside a PR's conditional scope this shares the pull's ETag with the snapshot and wait
|
|
102
|
+
// detectors: a 304 proves GitHub's current mergeability equals the stored settled body.
|
|
103
|
+
const data = await readRest("GET", `${restRepoPath({ owner, name: repo })}/pulls/${pr}`);
|
|
98
104
|
const mergeable = data.mergeable === true ? "MERGEABLE" : data.mergeable === false ? "CONFLICTING" : "UNKNOWN";
|
|
99
105
|
const mergeStateStatus = data.mergeable_state.toUpperCase();
|
|
100
106
|
const rawState = data.state?.toUpperCase();
|
|
@@ -137,3 +143,29 @@ function parseRemoteUrl(url) {
|
|
|
137
143
|
}
|
|
138
144
|
throw new Error(`Cannot parse GitHub remote URL: ${url}`);
|
|
139
145
|
}
|
|
146
|
+
export function getPrNumberForBranch(branch, owner, name) {
|
|
147
|
+
return githubOperation("PrNumberByBranch", () => getGraphqlPrNumberForBranch(branch, owner, name), async () => {
|
|
148
|
+
const listed = await readRestPages(`${restRepoPath({ owner, name })}/pulls?state=open`);
|
|
149
|
+
// REST's head filter requires an owner, but GraphQL's headRefName also matches fork heads.
|
|
150
|
+
const pull = listed.nodes.find((value) => {
|
|
151
|
+
const head = restObject(restObject(value, "pull request").head, "pull request head");
|
|
152
|
+
return restString(head.ref, "pull request head ref") === branch;
|
|
153
|
+
});
|
|
154
|
+
return pull ? restNumber(pull.number, "pull number") : null;
|
|
155
|
+
}).catch(() => null);
|
|
156
|
+
}
|
|
157
|
+
export function getPrHeadSha(pr, owner, name) {
|
|
158
|
+
return githubOperation("GetPrHeadSha", () => getGraphqlPrHeadSha(pr, owner, name), async () => (await readRestPull(pr, { owner, name })).head.sha);
|
|
159
|
+
}
|
|
160
|
+
export function getPullRequestBody(pr, owner, name) {
|
|
161
|
+
return githubOperation("GetPrBody", () => getGraphqlPullRequestBody(pr, owner, name), async () => {
|
|
162
|
+
const pull = await readRestPull(pr, { owner, name });
|
|
163
|
+
return { nodeId: pull.node_id, body: pull.body ?? "" };
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
export function updatePullRequestBody(pullRequestId, body) {
|
|
167
|
+
return githubOperation("UpdatePrBody", () => updateGraphqlPullRequestBody(pullRequestId, body), async () => {
|
|
168
|
+
const identity = await resolveRestIdentity(pullRequestId, "pull");
|
|
169
|
+
await rest("PATCH", `${restRepoPath(identity.repo)}/pulls/${identity.pr}`, { body });
|
|
170
|
+
}, { mutation: true });
|
|
171
|
+
}
|
|
@@ -35,9 +35,17 @@ export declare function threadCommentRevisions(nodes: Array<{
|
|
|
35
35
|
}>;
|
|
36
36
|
};
|
|
37
37
|
}>): string;
|
|
38
|
+
/**
|
|
39
|
+
* A thread whose earlier comments the fingerprint cannot see. BatchPr's `comments(first: 100)`
|
|
40
|
+
* carries the nodes and `hasNextPage`; a stored `totalCount` is honored when present.
|
|
41
|
+
*/
|
|
38
42
|
export declare function hasMultiCommentThreads(nodes: Array<{
|
|
39
43
|
comments?: {
|
|
40
44
|
totalCount?: number;
|
|
45
|
+
nodes?: unknown[];
|
|
46
|
+
pageInfo?: {
|
|
47
|
+
hasNextPage?: boolean;
|
|
48
|
+
};
|
|
41
49
|
};
|
|
42
50
|
}>): boolean;
|
|
43
51
|
export declare function rulesComplete(baseRef?: {
|
|
@@ -26,8 +26,13 @@ export function threadCommentRevisions(nodes) {
|
|
|
26
26
|
})
|
|
27
27
|
.join(",");
|
|
28
28
|
}
|
|
29
|
+
/**
|
|
30
|
+
* A thread whose earlier comments the fingerprint cannot see. BatchPr's `comments(first: 100)`
|
|
31
|
+
* carries the nodes and `hasNextPage`; a stored `totalCount` is honored when present.
|
|
32
|
+
*/
|
|
29
33
|
export function hasMultiCommentThreads(nodes) {
|
|
30
|
-
return nodes.some((
|
|
34
|
+
return nodes.some(({ comments }) => (comments?.totalCount ?? comments?.nodes?.length ?? 0) > 1 ||
|
|
35
|
+
comments?.pageInfo?.hasNextPage === true);
|
|
31
36
|
}
|
|
32
37
|
export function rulesComplete(baseRef) {
|
|
33
38
|
return baseRef?.rules?.pageInfo?.hasNextPage !== true;
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
import type { RepoInfo } from "./client.mts";
|
|
2
1
|
import type { RawPr } from "./batch-raw-types.mts";
|
|
2
|
+
/**
|
|
3
|
+
* Summary of BatchPr's first page. Two equal fingerprints mean the first page is unchanged, as
|
|
4
|
+
* long as every window it summarizes is complete (see `fingerprintReuser`).
|
|
5
|
+
*/
|
|
3
6
|
export interface PrFingerprint {
|
|
4
7
|
headRefOid: string;
|
|
5
8
|
updatedAt: string;
|
|
@@ -32,4 +35,3 @@ export interface PrFingerprint {
|
|
|
32
35
|
}
|
|
33
36
|
export declare function fingerprintFromRaw(raw: RawPr, viewerPermission?: string | null, viewerLogin?: string | null): PrFingerprint;
|
|
34
37
|
export declare function fingerprintsEqual(left: PrFingerprint, right: PrFingerprint): boolean;
|
|
35
|
-
export declare function fetchPrFingerprint(pr: number, repo: RepoInfo): Promise<PrFingerprint>;
|
|
@@ -1,9 +1,5 @@
|
|
|
1
|
-
import { graphqlWithRateLimit } from "./client.mjs";
|
|
2
|
-
import { PR_FINGERPRINT_QUERY } from "./queries.mjs";
|
|
3
|
-
import { GitHubRequestError } from "./errors.mjs";
|
|
4
|
-
import { EXIT, ShepherdError } from "../exit-codes.mjs";
|
|
5
1
|
import { commentRevisions, mergePolicyFingerprint, rulesComplete, stackKey, suiteFingerprint, hasMultiCommentThreads, threadCommentRevisions, } from "./fingerprint-fields.mjs";
|
|
6
|
-
function
|
|
2
|
+
export function fingerprintFromRaw(raw, viewerPermission = null, viewerLogin = null) {
|
|
7
3
|
return {
|
|
8
4
|
headRefOid: raw.headRefOid,
|
|
9
5
|
updatedAt: raw.updatedAt ?? "",
|
|
@@ -18,50 +14,22 @@ function coreFingerprint(raw, counts, viewer) {
|
|
|
18
14
|
commentCount: raw.comments.totalCount ?? raw.comments.nodes.length,
|
|
19
15
|
commentRevisions: commentRevisions(raw.comments.nodes),
|
|
20
16
|
threadCount: raw.reviewThreads.totalCount ?? raw.reviewThreads.nodes.length,
|
|
21
|
-
reviewCount:
|
|
22
|
-
reviewRevisions:
|
|
17
|
+
reviewCount: raw.allReviews?.totalCount ?? 0,
|
|
18
|
+
reviewRevisions: commentRevisions(raw.allReviews?.nodes ?? []),
|
|
23
19
|
latestCommentId: raw.comments.nodes.at(-1)?.id ?? null,
|
|
24
20
|
latestThreadId: raw.reviewThreads.nodes.at(-1)?.id ?? null,
|
|
25
|
-
latestReviewId:
|
|
21
|
+
latestReviewId: raw.allReviews?.nodes?.at(-1)?.id ?? null,
|
|
26
22
|
checkRollupState: raw.commits.nodes[0]?.commit.statusCheckRollup?.state ?? null,
|
|
27
23
|
...suiteFingerprint(raw.commits.nodes[0]?.commit.checkSuites),
|
|
28
24
|
viewerCanUpdate: raw.viewerCanUpdate === true,
|
|
29
|
-
viewerPermission
|
|
30
|
-
viewerLogin
|
|
25
|
+
viewerPermission,
|
|
26
|
+
viewerLogin,
|
|
31
27
|
stackKey: stackKey(raw),
|
|
32
28
|
threadCommentRevisions: threadCommentRevisions(raw.reviewThreads.nodes),
|
|
33
29
|
rulesComplete: rulesComplete(raw.baseRef),
|
|
34
30
|
hasMultiCommentThreads: hasMultiCommentThreads(raw.reviewThreads.nodes),
|
|
35
31
|
};
|
|
36
32
|
}
|
|
37
|
-
export function fingerprintFromRaw(raw, viewerPermission = null, viewerLogin = null) {
|
|
38
|
-
return coreFingerprint(raw, {
|
|
39
|
-
reviewCount: raw.allReviews?.totalCount ?? 0,
|
|
40
|
-
latestReviewId: raw.allReviews?.nodes?.at(-1)?.id ?? null,
|
|
41
|
-
reviewRevisions: commentRevisions(raw.allReviews?.nodes ?? []),
|
|
42
|
-
}, { permission: viewerPermission, login: viewerLogin });
|
|
43
|
-
}
|
|
44
33
|
export function fingerprintsEqual(left, right) {
|
|
45
34
|
return JSON.stringify(left) === JSON.stringify(right);
|
|
46
35
|
}
|
|
47
|
-
export async function fetchPrFingerprint(pr, repo) {
|
|
48
|
-
const result = await graphqlWithRateLimit(PR_FINGERPRINT_QUERY, {
|
|
49
|
-
owner: repo.owner,
|
|
50
|
-
repo: repo.name,
|
|
51
|
-
pr,
|
|
52
|
-
});
|
|
53
|
-
if (!result.data.repository) {
|
|
54
|
-
throw new GitHubRequestError(`GitHub GraphQL response did not include repository ${repo.owner}/${repo.name} (not found or access denied)`, { status: 200 });
|
|
55
|
-
}
|
|
56
|
-
const raw = result.data.repository.pullRequest;
|
|
57
|
-
if (!raw)
|
|
58
|
-
throw new ShepherdError(`PR #${pr} not found`, EXIT.UNAVAILABLE);
|
|
59
|
-
return coreFingerprint(raw, {
|
|
60
|
-
reviewCount: raw.reviews.totalCount,
|
|
61
|
-
latestReviewId: raw.reviews.nodes.at(-1)?.id ?? null,
|
|
62
|
-
reviewRevisions: commentRevisions(raw.reviews.nodes),
|
|
63
|
-
}, {
|
|
64
|
-
permission: result.data.repository.viewerPermission,
|
|
65
|
-
login: result.data.viewer?.login ?? null,
|
|
66
|
-
});
|
|
67
|
-
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { EnvHttpProxyAgent } from "undici";
|
|
2
|
+
let proxyAgent;
|
|
3
|
+
let proxyConfiguration;
|
|
4
|
+
/** Attach proxy routing to GitHub requests without changing the host's dispatcher. */
|
|
5
|
+
export function githubFetch(input, init) {
|
|
6
|
+
const httpProxy = process.env["http_proxy"] ?? process.env["HTTP_PROXY"] ?? "";
|
|
7
|
+
const httpsProxy = process.env["https_proxy"] ?? process.env["HTTPS_PROXY"] ?? "";
|
|
8
|
+
if (!httpProxy && !httpsProxy)
|
|
9
|
+
return fetch(input, init);
|
|
10
|
+
const configuration = JSON.stringify([httpProxy, httpsProxy]);
|
|
11
|
+
if (!proxyAgent || configuration !== proxyConfiguration) {
|
|
12
|
+
const previous = proxyAgent;
|
|
13
|
+
proxyAgent = new EnvHttpProxyAgent();
|
|
14
|
+
proxyConfiguration = configuration;
|
|
15
|
+
// close waits for in-flight bodies before releasing the previous pool.
|
|
16
|
+
void previous?.close().catch(() => { });
|
|
17
|
+
}
|
|
18
|
+
return fetch(input, { ...init, dispatcher: proxyAgent });
|
|
19
|
+
}
|
|
@@ -176,7 +176,23 @@ query BatchPrPage(
|
|
|
176
176
|
annotations(first: 1) {
|
|
177
177
|
totalCount
|
|
178
178
|
nodes {
|
|
179
|
+
fullDatabaseId
|
|
180
|
+
path
|
|
181
|
+
annotationLevel
|
|
182
|
+
title
|
|
179
183
|
message
|
|
184
|
+
rawDetails
|
|
185
|
+
blobUrl
|
|
186
|
+
location {
|
|
187
|
+
start {
|
|
188
|
+
line
|
|
189
|
+
column
|
|
190
|
+
}
|
|
191
|
+
end {
|
|
192
|
+
line
|
|
193
|
+
column
|
|
194
|
+
}
|
|
195
|
+
}
|
|
180
196
|
}
|
|
181
197
|
}
|
|
182
198
|
checkSuite {
|
|
@@ -39,6 +39,12 @@ query BatchPr($owner: String!, $repo: String!, $pr: Int!) {
|
|
|
39
39
|
}
|
|
40
40
|
baseRefName
|
|
41
41
|
baseRefOid
|
|
42
|
+
# Live base tip (an object, no connection cost): keys the BaseBehind cache.
|
|
43
|
+
baseRef {
|
|
44
|
+
target {
|
|
45
|
+
oid
|
|
46
|
+
}
|
|
47
|
+
}
|
|
42
48
|
isInMergeQueue
|
|
43
49
|
...PrMergePolicy
|
|
44
50
|
autoMergeRequest {
|
|
@@ -102,10 +108,45 @@ query BatchPr($owner: String!, $repo: String!, $pr: Int!) {
|
|
|
102
108
|
}
|
|
103
109
|
}
|
|
104
110
|
}
|
|
111
|
+
# Native-stack topology and trunk rules ride along so a stack layer needs no
|
|
112
|
+
# separate PollStackTopology or RefRules read. Neither nested selection
|
|
113
|
+
# multiplies a connection by 50, so together they add about 3 requests.
|
|
105
114
|
stack {
|
|
115
|
+
id
|
|
106
116
|
number
|
|
107
117
|
size
|
|
108
118
|
baseRefName
|
|
119
|
+
entries(first: 50) {
|
|
120
|
+
pageInfo {
|
|
121
|
+
hasNextPage
|
|
122
|
+
endCursor
|
|
123
|
+
}
|
|
124
|
+
nodes {
|
|
125
|
+
position
|
|
126
|
+
pullRequest {
|
|
127
|
+
number
|
|
128
|
+
state
|
|
129
|
+
headRefName
|
|
130
|
+
headRefOid
|
|
131
|
+
baseRefName
|
|
132
|
+
baseRefOid
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
# The bottom entry's base is the trunk: its rules and live tip.
|
|
137
|
+
trunkEntry: entries(first: 1) {
|
|
138
|
+
nodes {
|
|
139
|
+
pullRequest {
|
|
140
|
+
baseRefName
|
|
141
|
+
baseRef {
|
|
142
|
+
...RefRules
|
|
143
|
+
target {
|
|
144
|
+
oid
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
109
150
|
}
|
|
110
151
|
stackEntry {
|
|
111
152
|
position
|
|
@@ -295,7 +336,23 @@ query BatchPr($owner: String!, $repo: String!, $pr: Int!) {
|
|
|
295
336
|
annotations(first: 1) {
|
|
296
337
|
totalCount
|
|
297
338
|
nodes {
|
|
339
|
+
fullDatabaseId
|
|
340
|
+
path
|
|
341
|
+
annotationLevel
|
|
342
|
+
title
|
|
298
343
|
message
|
|
344
|
+
rawDetails
|
|
345
|
+
blobUrl
|
|
346
|
+
location {
|
|
347
|
+
start {
|
|
348
|
+
line
|
|
349
|
+
column
|
|
350
|
+
}
|
|
351
|
+
end {
|
|
352
|
+
line
|
|
353
|
+
column
|
|
354
|
+
}
|
|
355
|
+
}
|
|
299
356
|
}
|
|
300
357
|
}
|
|
301
358
|
checkSuite {
|
|
@@ -31,8 +31,25 @@ query CommitCheckContexts($owner: String!, $repo: String!, $oid: String!, $curso
|
|
|
31
31
|
title
|
|
32
32
|
summary
|
|
33
33
|
annotations(first: 1) {
|
|
34
|
+
totalCount
|
|
34
35
|
nodes {
|
|
36
|
+
fullDatabaseId
|
|
37
|
+
path
|
|
38
|
+
annotationLevel
|
|
39
|
+
title
|
|
35
40
|
message
|
|
41
|
+
rawDetails
|
|
42
|
+
blobUrl
|
|
43
|
+
location {
|
|
44
|
+
start {
|
|
45
|
+
line
|
|
46
|
+
column
|
|
47
|
+
}
|
|
48
|
+
end {
|
|
49
|
+
line
|
|
50
|
+
column
|
|
51
|
+
}
|
|
52
|
+
}
|
|
36
53
|
}
|
|
37
54
|
}
|
|
38
55
|
checkSuite {
|