pr-shepherd 0.56.6 → 0.57.1
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 +150 -280
- 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/codex-notices.d.mts +8 -0
- package/bin/classify/standard/codex-notices.mjs +34 -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 +7 -0
- package/bin/classify/standard/index.mjs +21 -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 +57 -16
- 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/captured-proxy-agent.d.mts +3 -0
- package/bin/github/captured-proxy-agent.mjs +8 -0
- 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 +32 -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/legacy-dispatcher.d.mts +6 -0
- package/bin/github/legacy-dispatcher.mjs +44 -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.d.mts +6 -1
- package/bin/github/poll-summary-readiness.mjs +13 -4
- 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 +35 -20
- 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 +4 -3
- 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 +3 -1
- 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
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type MergeMethod } from "../../config/merge-method.mts";
|
|
2
|
+
import type { MergeCommandPlan } from "../../types.mts";
|
|
3
|
+
import type { RestMergeStackGuard } from "../../github/rest-merge.mts";
|
|
4
|
+
export interface MergePlanInput {
|
|
5
|
+
transport?: "rest";
|
|
6
|
+
pr: number;
|
|
7
|
+
repo: string;
|
|
8
|
+
nodeId: string;
|
|
9
|
+
headSha: string;
|
|
10
|
+
queue: boolean;
|
|
11
|
+
queueKnown?: boolean;
|
|
12
|
+
/** Omitted when the batch did not select repository merge settings. */
|
|
13
|
+
allowedMergeMethods?: readonly MergeMethod[];
|
|
14
|
+
expectedStack?: RestMergeStackGuard;
|
|
15
|
+
}
|
|
16
|
+
export interface MergeMethodUnavailable {
|
|
17
|
+
unavailable: string;
|
|
18
|
+
}
|
|
19
|
+
export declare function buildMergeCommandPlan(input: MergePlanInput): MergeCommandPlan | MergeMethodUnavailable;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { loadConfig } from "../../config/load.mjs";
|
|
2
|
+
import { findMergeStrategies } from "../../config/merge-command-args.mjs";
|
|
3
|
+
import { chooseMergeMethod, configuredMergeMethod, } from "../../config/merge-method.mjs";
|
|
4
|
+
import { formatPrUrl } from "../../pr-reference.mjs";
|
|
5
|
+
import { buildPrShepherdCommand } from "../../cli/runner.mjs";
|
|
6
|
+
import { getGithubTransport } from "../../github/transport.mjs";
|
|
7
|
+
const ENQUEUE_MUTATION = "mutation EnqueuePullRequest($pullRequestId: ID!, $expectedHeadOid: GitObjectID!) { enqueuePullRequest(input: { pullRequestId: $pullRequestId, expectedHeadOid: $expectedHeadOid }) { mergeQueueEntry { id } } }";
|
|
8
|
+
export function buildMergeCommandPlan(input) {
|
|
9
|
+
if (input.transport === "rest" || getGithubTransport() === "rest") {
|
|
10
|
+
const configured = configuredMergeMethod(loadConfig().merge ?? {});
|
|
11
|
+
if (!input.queue && input.queueKnown !== true && configured)
|
|
12
|
+
return {
|
|
13
|
+
unavailable: "REST cannot verify merge-queue policy and cannot apply a configured direct merge method to an automatic merge request. Refresh branch policy before merging.",
|
|
14
|
+
};
|
|
15
|
+
let method;
|
|
16
|
+
if (!input.queue && input.queueKnown === true) {
|
|
17
|
+
const decision = chooseMergeMethod({
|
|
18
|
+
allowed: input.allowedMergeMethods,
|
|
19
|
+
configured,
|
|
20
|
+
fallback: "merge",
|
|
21
|
+
});
|
|
22
|
+
if ("unavailable" in decision)
|
|
23
|
+
return decision;
|
|
24
|
+
method = decision.method;
|
|
25
|
+
}
|
|
26
|
+
return {
|
|
27
|
+
mode: "rest",
|
|
28
|
+
command: buildPrShepherdCommand([
|
|
29
|
+
"apply",
|
|
30
|
+
"merge",
|
|
31
|
+
formatPrUrl(input.repo, input.pr),
|
|
32
|
+
"--require-sha",
|
|
33
|
+
input.headSha,
|
|
34
|
+
"--merge-action",
|
|
35
|
+
input.queue ? "merge_queue" : input.queueKnown ? "direct_merge" : "default",
|
|
36
|
+
...(method ? ["--method", method] : []),
|
|
37
|
+
...(input.expectedStack ? ["--expected-stack", JSON.stringify(input.expectedStack)] : []),
|
|
38
|
+
"--transport",
|
|
39
|
+
"rest",
|
|
40
|
+
]),
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
const base = [
|
|
44
|
+
"gh",
|
|
45
|
+
"pr",
|
|
46
|
+
"merge",
|
|
47
|
+
String(input.pr),
|
|
48
|
+
"--repo",
|
|
49
|
+
input.repo,
|
|
50
|
+
"--match-head-commit",
|
|
51
|
+
input.headSha,
|
|
52
|
+
];
|
|
53
|
+
if (input.queue) {
|
|
54
|
+
return {
|
|
55
|
+
mode: "queue",
|
|
56
|
+
command: { argv: base },
|
|
57
|
+
queueApiFallbackCommand: {
|
|
58
|
+
argv: [
|
|
59
|
+
"gh",
|
|
60
|
+
"api",
|
|
61
|
+
"graphql",
|
|
62
|
+
"-f",
|
|
63
|
+
`query=${ENQUEUE_MUTATION}`,
|
|
64
|
+
"-f",
|
|
65
|
+
`pullRequestId=${input.nodeId}`,
|
|
66
|
+
"-f",
|
|
67
|
+
`expectedHeadOid=${input.headSha}`,
|
|
68
|
+
],
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
const mergeConfig = loadConfig().merge;
|
|
73
|
+
const configuredArgs = mergeConfig?.commandArgs ?? [];
|
|
74
|
+
const decision = chooseMergeMethod({
|
|
75
|
+
allowed: input.allowedMergeMethods,
|
|
76
|
+
configured: configuredMergeMethod(mergeConfig ?? {}),
|
|
77
|
+
fallback: "merge",
|
|
78
|
+
});
|
|
79
|
+
if ("unavailable" in decision)
|
|
80
|
+
return decision;
|
|
81
|
+
const hasStrategy = findMergeStrategies(configuredArgs).length > 0;
|
|
82
|
+
const commandArgs = hasStrategy ? configuredArgs : [...configuredArgs, `--${decision.method}`];
|
|
83
|
+
return {
|
|
84
|
+
mode: "auto",
|
|
85
|
+
command: { argv: [...base, "--auto", ...commandArgs] },
|
|
86
|
+
fallbackCommand: { argv: [...base, ...commandArgs] },
|
|
87
|
+
};
|
|
88
|
+
}
|
|
@@ -51,10 +51,13 @@ export function buildReadyMergeOutcome(enabled, readyElapsed, base, report) {
|
|
|
51
51
|
report.mergeStatus.mergeRequirements?.mergeQueue?.enabled);
|
|
52
52
|
const plan = buildMergeCommandPlan({
|
|
53
53
|
pr: report.pr,
|
|
54
|
+
...(report.transport && { transport: report.transport }),
|
|
54
55
|
repo: report.repo,
|
|
55
56
|
nodeId: report.nodeId,
|
|
56
57
|
headSha: report.headSha ?? "unknown",
|
|
57
58
|
queue,
|
|
59
|
+
queueKnown: (report.transport !== "rest" || report.branchProtection === null) &&
|
|
60
|
+
!(report.transportUnavailable ?? []).some(({ field }) => ["branchProtection", "branchRules"].includes(field)),
|
|
58
61
|
...(report.allowedMergeMethods && { allowedMergeMethods: report.allowedMergeMethods }),
|
|
59
62
|
});
|
|
60
63
|
if ("unavailable" in plan)
|
|
@@ -1,29 +1,18 @@
|
|
|
1
|
-
|
|
1
|
+
export { buildMergeCommandPlan } from "./merge-plan.mts";
|
|
2
2
|
import type { AgentCheck, IterateResult, IterateResultBase, MergeCommandPlan, ShepherdReport } from "../../types.mts";
|
|
3
|
-
interface
|
|
4
|
-
pr: number;
|
|
5
|
-
repo: string;
|
|
6
|
-
nodeId: string;
|
|
7
|
-
headSha: string;
|
|
8
|
-
queue: boolean;
|
|
9
|
-
/** Omitted when the batch did not select repository merge settings. */
|
|
10
|
-
allowedMergeMethods?: readonly MergeMethod[];
|
|
11
|
-
}
|
|
12
|
-
export interface MergeMethodUnavailable {
|
|
3
|
+
interface QueueRecoveryUnavailable {
|
|
13
4
|
unavailable: string;
|
|
14
5
|
}
|
|
15
|
-
export declare function buildMergeCommandPlan(input: MergePlanInput): MergeCommandPlan | MergeMethodUnavailable;
|
|
16
6
|
export declare function renderMergeCommand(command: {
|
|
17
7
|
argv: string[];
|
|
18
8
|
}): string;
|
|
19
9
|
/** Offer a guarded queue command; the caller decides whether the failure warrants a PR fix. */
|
|
20
|
-
export declare function buildRemovedQueueRecovery(report: ShepherdReport, checks: AgentCheck[], merge: boolean | undefined): MergeCommandPlan | undefined;
|
|
10
|
+
export declare function buildRemovedQueueRecovery(report: ShepherdReport, checks: AgentCheck[], merge: boolean | undefined): MergeCommandPlan | QueueRecoveryUnavailable | undefined;
|
|
21
11
|
/** Bind a caller's disposition to one removed stack queue commit, without submitting a merge. */
|
|
22
12
|
export declare function buildStackQueueRemovalAcknowledgment(report: ShepherdReport, checks: AgentCheck[]): {
|
|
23
13
|
argv: string[];
|
|
24
|
-
} | undefined;
|
|
14
|
+
} | QueueRecoveryUnavailable | undefined;
|
|
25
15
|
export declare function unavailableMergeResult(base: IterateResultBase, report: {
|
|
26
16
|
pr: number;
|
|
27
17
|
repo: string;
|
|
28
18
|
}, unavailable: string): IterateResult;
|
|
29
|
-
export {};
|
|
@@ -1,59 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
import { chooseMergeMethod, configuredMergeMethod, } from "../../config/merge-method.mjs";
|
|
1
|
+
import { buildMergeCommandPlan } from "./merge-plan.mjs";
|
|
2
|
+
export { buildMergeCommandPlan } from "./merge-plan.mjs";
|
|
4
3
|
import { formatPrUrl } from "../../pr-reference.mjs";
|
|
5
4
|
import { renderShellCommand, buildPrShepherdCommand } from "../../cli/runner.mjs";
|
|
6
5
|
import { hasQueueRecoveryEvidence } from "./check-evidence.mjs";
|
|
7
6
|
import { isCiQueueRemovalReason } from "../../state/queue-removal-ack.mjs";
|
|
8
7
|
import { buildEscalateHumanMessage } from "./escalate.mjs";
|
|
9
|
-
|
|
10
|
-
export function buildMergeCommandPlan(input) {
|
|
11
|
-
const base = [
|
|
12
|
-
"gh",
|
|
13
|
-
"pr",
|
|
14
|
-
"merge",
|
|
15
|
-
String(input.pr),
|
|
16
|
-
"--repo",
|
|
17
|
-
input.repo,
|
|
18
|
-
"--match-head-commit",
|
|
19
|
-
input.headSha,
|
|
20
|
-
];
|
|
21
|
-
if (input.queue) {
|
|
22
|
-
return {
|
|
23
|
-
mode: "queue",
|
|
24
|
-
command: { argv: base },
|
|
25
|
-
queueApiFallbackCommand: {
|
|
26
|
-
argv: [
|
|
27
|
-
"gh",
|
|
28
|
-
"api",
|
|
29
|
-
"graphql",
|
|
30
|
-
"-f",
|
|
31
|
-
`query=${ENQUEUE_MUTATION}`,
|
|
32
|
-
"-f",
|
|
33
|
-
`pullRequestId=${input.nodeId}`,
|
|
34
|
-
"-f",
|
|
35
|
-
`expectedHeadOid=${input.headSha}`,
|
|
36
|
-
],
|
|
37
|
-
},
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
const mergeConfig = loadConfig().merge;
|
|
41
|
-
const configuredArgs = mergeConfig?.commandArgs ?? [];
|
|
42
|
-
const decision = chooseMergeMethod({
|
|
43
|
-
allowed: input.allowedMergeMethods,
|
|
44
|
-
configured: configuredMergeMethod(mergeConfig ?? {}),
|
|
45
|
-
fallback: "merge",
|
|
46
|
-
});
|
|
47
|
-
if ("unavailable" in decision)
|
|
48
|
-
return decision;
|
|
49
|
-
const hasStrategy = findMergeStrategies(configuredArgs).length > 0;
|
|
50
|
-
const commandArgs = hasStrategy ? configuredArgs : [...configuredArgs, `--${decision.method}`];
|
|
51
|
-
return {
|
|
52
|
-
mode: "auto",
|
|
53
|
-
command: { argv: [...base, "--auto", ...commandArgs] },
|
|
54
|
-
fallbackCommand: { argv: [...base, ...commandArgs] },
|
|
55
|
-
};
|
|
56
|
-
}
|
|
8
|
+
import { getGithubTransport } from "../../github/transport.mjs";
|
|
57
9
|
export function renderMergeCommand(command) {
|
|
58
10
|
return renderShellCommand(command.argv);
|
|
59
11
|
}
|
|
@@ -63,6 +15,11 @@ export function buildRemovedQueueRecovery(report, checks, merge) {
|
|
|
63
15
|
return undefined;
|
|
64
16
|
if (!removedQueueRecoveryAvailable(report, checks, merge))
|
|
65
17
|
return undefined;
|
|
18
|
+
// REST cannot prove that a recorded enqueue was removed or that no later enqueue exists.
|
|
19
|
+
// Never offer a resume command as if it could authorize a fresh same-head submission.
|
|
20
|
+
const unsupported = unsupportedRestQueueRecovery(report);
|
|
21
|
+
if (unsupported)
|
|
22
|
+
return unsupported;
|
|
66
23
|
const plan = buildMergeCommandPlan({
|
|
67
24
|
pr: report.pr,
|
|
68
25
|
repo: report.repo,
|
|
@@ -79,6 +36,9 @@ export function buildStackQueueRemovalAcknowledgment(report, checks) {
|
|
|
79
36
|
// This records a local disposition, without enqueueing; aggregate child sessions omit --merge.
|
|
80
37
|
if (!removedQueueRecoveryAvailable(report, checks, true))
|
|
81
38
|
return undefined;
|
|
39
|
+
const unsupported = unsupportedRestQueueRecovery(report);
|
|
40
|
+
if (unsupported)
|
|
41
|
+
return unsupported;
|
|
82
42
|
const removal = report.mergeQueue.latestRemoval;
|
|
83
43
|
return buildPrShepherdCommand([
|
|
84
44
|
"apply",
|
|
@@ -92,6 +52,13 @@ export function buildStackQueueRemovalAcknowledgment(report, checks) {
|
|
|
92
52
|
String(removal.createdAtUnix),
|
|
93
53
|
]);
|
|
94
54
|
}
|
|
55
|
+
function unsupportedRestQueueRecovery(report) {
|
|
56
|
+
if (report.transport !== "rest" && getGithubTransport() !== "rest")
|
|
57
|
+
return undefined;
|
|
58
|
+
return {
|
|
59
|
+
unavailable: "Queue recovery is transport-unsupported: REST cannot verify current merge-queue removal evidence. Continue the printed fix steps; requeue and removal acknowledgment require verified current removal evidence.",
|
|
60
|
+
};
|
|
61
|
+
}
|
|
95
62
|
function removedQueueRecoveryAvailable(report, checks, merge) {
|
|
96
63
|
const queue = report.mergeQueue;
|
|
97
64
|
const removedCommit = queue?.latestRemoval?.beforeCommitOid;
|
|
@@ -1,8 +1,4 @@
|
|
|
1
1
|
import type { MergedBasePullRequest } from "../../types.mts";
|
|
2
|
+
import { type MergedBaseLookupInput } from "../../github/rest-merged-base-read.mts";
|
|
2
3
|
/** A bounded, best-effort lookup; matching OIDs and repository prevent branch-name reuse false positives. */
|
|
3
|
-
export declare function lookupMergedBasePullRequests(input:
|
|
4
|
-
owner: string;
|
|
5
|
-
repo: string;
|
|
6
|
-
baseRefName: string;
|
|
7
|
-
baseRefOid: string;
|
|
8
|
-
}): Promise<MergedBasePullRequest[]>;
|
|
4
|
+
export declare function lookupMergedBasePullRequests(input: MergedBaseLookupInput): Promise<MergedBasePullRequest[]>;
|
|
@@ -1,22 +1,26 @@
|
|
|
1
1
|
import { graphql } from "../../github/client.mjs";
|
|
2
2
|
import { MERGED_BASE_PULL_REQUESTS_QUERY } from "../../github/queries.mjs";
|
|
3
3
|
import { pollRateLimitRetryAfterMs } from "../poll-quota.mjs";
|
|
4
|
+
import { githubOperation, isGithubReadFallbackError } from "../../github/transport.mjs";
|
|
5
|
+
import { readRestMergedBasePullRequests, } from "../../github/rest-merged-base-read.mjs";
|
|
4
6
|
/** A bounded, best-effort lookup; matching OIDs and repository prevent branch-name reuse false positives. */
|
|
5
7
|
export async function lookupMergedBasePullRequests(input) {
|
|
6
8
|
try {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
9
|
+
return await githubOperation("MergedBasePullRequests", async () => {
|
|
10
|
+
const { data } = await graphql(MERGED_BASE_PULL_REQUESTS_QUERY, {
|
|
11
|
+
owner: input.owner,
|
|
12
|
+
repo: input.repo,
|
|
13
|
+
branch: input.baseRefName,
|
|
14
|
+
});
|
|
15
|
+
return (data.repository?.pullRequests.nodes ?? []).filter((candidate) => candidate !== null &&
|
|
16
|
+
candidate.state === "MERGED" &&
|
|
17
|
+
candidate.headRefName === input.baseRefName &&
|
|
18
|
+
candidate.headRefOid === input.baseRefOid &&
|
|
19
|
+
candidate.headRepository?.nameWithOwner === `${input.owner}/${input.repo}`);
|
|
20
|
+
}, () => readRestMergedBasePullRequests(input));
|
|
17
21
|
}
|
|
18
22
|
catch (error) {
|
|
19
|
-
if (pollRateLimitRetryAfterMs(error) !== null)
|
|
23
|
+
if (pollRateLimitRetryAfterMs(error) !== null || isGithubReadFallbackError(error))
|
|
20
24
|
throw error;
|
|
21
25
|
process.stderr.write(`pr-shepherd: merged-base PR lookup unavailable (ignored): ${error instanceof Error ? error.message : String(error)}\n`);
|
|
22
26
|
return [];
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { playbookPointer } from "../playbook-pointer.mjs";
|
|
2
|
+
import { getGithubTransport } from "../../github/transport.mjs";
|
|
2
3
|
/**
|
|
3
4
|
* One gh-stack rebase step. A native stack layer must not be rebased or merged from its base
|
|
4
5
|
* branch alone: that rewrites one branch and strands every layer above it.
|
|
@@ -8,6 +9,14 @@ import { playbookPointer } from "../playbook-pointer.mjs";
|
|
|
8
9
|
* stack number before a PR number) and checks each local layer against its PR head.
|
|
9
10
|
*/
|
|
10
11
|
export function buildNativeStackRebaseInstruction(repo, stackNumber, start) {
|
|
12
|
+
if (getGithubTransport() === "rest") {
|
|
13
|
+
const boundary = "parentBranch" in start
|
|
14
|
+
? `parent branch \`${start.parentBranch}\``
|
|
15
|
+
: "trunk" in start
|
|
16
|
+
? `trunk \`${start.trunk}\``
|
|
17
|
+
: `bottom open layer PR #${start.bottomPr}`;
|
|
18
|
+
return `Use the repository's stack-update procedure for native stack #${stackNumber} in \`${repo}\`, starting at ${boundary} and preserving the ordered parent boundaries of every affected upper layer. Read membership with REST-backed Shepherd \`--stack\` output and update and push affected branches using the caller's git workflow. ${playbookPointer("Branch update")}`;
|
|
19
|
+
}
|
|
11
20
|
const [checkout, command] = "parentBranch" in start
|
|
12
21
|
? [
|
|
13
22
|
`check out the parent stack branch \`${start.parentBranch}\``,
|
|
@@ -55,6 +64,8 @@ export function buildConflictInstruction(stackRebase) {
|
|
|
55
64
|
* After a merge-queue ejection update, push only when the update or a fix changed the head.
|
|
56
65
|
*/
|
|
57
66
|
export function buildBranchPushInstruction(stackRebase, hasConflicts, mutationSuffix, ejectionUpdate = false) {
|
|
67
|
+
if (stackRebase && getGithubTransport() === "rest")
|
|
68
|
+
return `If the base update or a fix changed any heads, commit the remaining changes and push every affected stack branch using the repository's stack-update procedure${mutationSuffix}. If no heads changed, do not push.`;
|
|
58
69
|
if (ejectionUpdate) {
|
|
59
70
|
const push = stackRebase
|
|
60
71
|
? "commit any remaining changes on the PR head branch and push the rewritten stack with `gh stack push`"
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import type { AgentThread, AgentComment, AgentCheck, Review, ResolveCommand, FirstLookThread, FirstLookComment, ReviewThread } from "../../types.mts";
|
|
2
2
|
import { type QueueEjectionRecovery } from "./queue-recovery-instructions.mts";
|
|
3
|
-
|
|
3
|
+
import type { InstructionStyle } from "../../config/load.mts";
|
|
4
|
+
/**
|
|
5
|
+
* Render a resolve command as a shell snippet. Appends `--require-sha HEAD` when set: run after
|
|
6
|
+
* the push step, the local HEAD is the pushed PR head, and `apply review` rejects the mutations
|
|
7
|
+
* if it is not. `apply review` reads that HEAD itself with a read-only `git rev-parse HEAD`.
|
|
8
|
+
*/
|
|
4
9
|
export declare function renderResolveCommand(rc: ResolveCommand): string;
|
|
5
10
|
export declare function buildFixInstructions(threads: AgentThread[], actionableComments: AgentComment[], checks: AgentCheck[], changesRequestedReviews: Review[], baseBranch: string, resolveCommand: ResolveCommand, hasConflicts: boolean, prReference: string | number, _cancelledCount: number, firstLookThreads?: FirstLookThread[], firstLookComments?: FirstLookComment[], firstLookSummaries?: Review[], editedSummaries?: Review[], _inProgressRunIds?: string[], resolutionOnlyThreads?: ReviewThread[], resolveOnlyCommand?: ResolveCommand, behindBaseHint?: string, // iterate.behindBaseHint — see buildBehindBaseHintInstruction
|
|
6
11
|
isBehind?: boolean, viewerCanUpdate?: boolean, hasExhaustedWorkflowRerun?: boolean, stackRebase?: string, // native stack layers rebase with gh-stack, not branch by branch
|
|
7
|
-
queueEjection?: QueueEjectionRecovery
|
|
12
|
+
queueEjection?: QueueEjectionRecovery, // current merge-queue removal with failing queue checks
|
|
13
|
+
instructionStyle?: InstructionStyle): string[];
|
|
@@ -1,23 +1,28 @@
|
|
|
1
1
|
import { renderShellCommand } from "../../cli/runner.mjs";
|
|
2
2
|
import { buildFailingCheckInstructions, buildCrStaleClause, buildBehindBaseHintInstruction, buildRepeatedWorkflowBranchRecoveryInstructions, buildResolveCommandInstruction, buildFixCompletionInstruction, } from "./check-instructions.mjs";
|
|
3
|
-
import { SHEPHERD_JOURNAL_FIRST_LOOK_GUIDANCE
|
|
3
|
+
import { SHEPHERD_JOURNAL_FIRST_LOOK_GUIDANCE } from "../shepherd-journal.mjs";
|
|
4
4
|
import { isFailingAgentCheck } from "../../checks/conclusions.mjs";
|
|
5
5
|
import { buildCommitSuggestionInstruction } from "../commit-suggestion-instruction.mjs";
|
|
6
|
-
import { partitionFixThreads
|
|
6
|
+
import { partitionFixThreads } from "./fix-instruction-threads.mjs";
|
|
7
7
|
import { buildBranchPushInstruction, buildConflictInstruction } from "./native-stack-rebase.mjs";
|
|
8
8
|
import { queueEjectionSteps } from "./queue-recovery-instructions.mjs";
|
|
9
|
-
|
|
9
|
+
import { buildPushJournalSteps } from "./fix-loop-instruction.mjs";
|
|
10
|
+
/**
|
|
11
|
+
* Render a resolve command as a shell snippet. Appends `--require-sha HEAD` when set: run after
|
|
12
|
+
* the push step, the local HEAD is the pushed PR head, and `apply review` rejects the mutations
|
|
13
|
+
* if it is not. `apply review` reads that HEAD itself with a read-only `git rev-parse HEAD`.
|
|
14
|
+
*/
|
|
10
15
|
export function renderResolveCommand(rc) {
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
parts.push("--require-sha", "$HEAD_SHA");
|
|
14
|
-
return renderShellCommand(parts);
|
|
16
|
+
const command = renderShellCommand(rc.argv);
|
|
17
|
+
return rc.requiresHeadSha ? `${command} ${REQUIRE_HEAD_SHA}` : command;
|
|
15
18
|
}
|
|
19
|
+
const REQUIRE_HEAD_SHA = "--require-sha HEAD";
|
|
16
20
|
export function buildFixInstructions(threads, actionableComments, checks, changesRequestedReviews, baseBranch, resolveCommand, hasConflicts, prReference, _cancelledCount, firstLookThreads = [], firstLookComments = [], firstLookSummaries = [], editedSummaries = [], _inProgressRunIds = [], resolutionOnlyThreads = [], resolveOnlyCommand, behindBaseHint = "", // iterate.behindBaseHint — see buildBehindBaseHintInstruction
|
|
17
21
|
isBehind = false, viewerCanUpdate = false, hasExhaustedWorkflowRerun = false, stackRebase, // native stack layers rebase with gh-stack, not branch by branch
|
|
18
|
-
queueEjection
|
|
22
|
+
queueEjection, // current merge-queue removal with failing queue checks
|
|
23
|
+
instructionStyle = "inline") {
|
|
19
24
|
const instructions = [];
|
|
20
|
-
const { locatedThreads,
|
|
25
|
+
const { locatedThreads, unlocatedThreads } = partitionFixThreads(threads, resolveCommand, resolveOnlyCommand);
|
|
21
26
|
const failingChecks = checks.filter((c) => isFailingAgentCheck(c));
|
|
22
27
|
const repeatedWorkflowBranchRecoveryInstructions = buildRepeatedWorkflowBranchRecoveryInstructions(baseBranch, hasExhaustedWorkflowRerun, { isBehind, hasConflicts }, stackRebase);
|
|
23
28
|
const hasRepeatedWorkflowBranchRecovery = repeatedWorkflowBranchRecoveryInstructions.length > 0;
|
|
@@ -28,18 +33,8 @@ queueEjection) {
|
|
|
28
33
|
changesRequestedReviews.length > 0 ||
|
|
29
34
|
actionableComments.length > 0;
|
|
30
35
|
// Start with interpretation. The agent decides what raw feedback warrants a code change.
|
|
31
|
-
if (hasNonConflictHints)
|
|
32
|
-
|
|
33
|
-
hasReviewThreads: locatedThreads.length > 0 || unlocatedMutatedThreads.length > 0,
|
|
34
|
-
hasUnlocatedSkipThreads: unlocatedThreads.length > 0,
|
|
35
|
-
hasActionableComments: actionableComments.length > 0,
|
|
36
|
-
hasFailingChecks: failingChecks.length > 0,
|
|
37
|
-
hasAnnotations,
|
|
38
|
-
hasChangesRequested: changesRequestedReviews.length > 0,
|
|
39
|
-
});
|
|
40
|
-
const sectionRef = actionableSections.length > 0 ? `under ${actionableSections.join(", ")}` : "above";
|
|
41
|
-
instructions.push(`Review each item ${sectionRef} and decide whether it needs a code change.`);
|
|
42
|
-
}
|
|
36
|
+
if (hasNonConflictHints)
|
|
37
|
+
instructions.push("Fix each warranted item.");
|
|
43
38
|
// A conflicting native stack layer follows the printed gh-stack route, so it omits the hint.
|
|
44
39
|
const branchUpdateHint = buildBehindBaseHintInstruction(baseBranch, behindBaseHint, {
|
|
45
40
|
isBehind,
|
|
@@ -66,41 +61,32 @@ queueEjection) {
|
|
|
66
61
|
const hasSuggestions = locatedThreads.some((t) => t.suggestion);
|
|
67
62
|
if (hasSuggestions)
|
|
68
63
|
instructions.push(buildCommitSuggestionInstruction(prReference, "## Review threads"));
|
|
69
|
-
if (locatedThreads.length > 0 || actionableComments.length > 0) {
|
|
70
|
-
// Actionable comments carry no file/line location (unlike threads), so "referenced above"
|
|
71
|
-
// is only accurate when threads are present.
|
|
72
|
-
const filesRef = locatedThreads.length > 0 ? "each file referenced above" : "the relevant files";
|
|
73
|
-
instructions.push(`Apply every warranted review fix in ${filesRef}.`);
|
|
74
|
-
}
|
|
75
64
|
if (resolutionOnlyThreads.length > 0)
|
|
76
65
|
instructions.push("Review the threads under `## Review threads to resolve` before running the generated mutations.");
|
|
77
66
|
instructions.push(...buildFailingCheckInstructions(failingChecks), ...repeatedWorkflowBranchRecoveryInstructions, ...queueEjectionSteps(queueEjection, stackRebase, branchRecovery));
|
|
78
67
|
if (hasAnnotations)
|
|
79
68
|
instructions.push("Inspect every referenced range under `## Check annotations` and apply any warranted change.");
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
69
|
+
// The first step already covers applying changes-requested bodies; only stale CRs add a step.
|
|
70
|
+
const staleClause = buildCrStaleClause(changesRequestedReviews);
|
|
71
|
+
if (staleClause)
|
|
72
|
+
instructions.push(staleClause);
|
|
84
73
|
if (!hintWithConflictStep)
|
|
85
74
|
instructions.push(...branchUpdateHint);
|
|
86
75
|
const hasReviewMutations = resolveCommand.hasMutations || resolveOnlyCommand?.hasMutations === true;
|
|
87
76
|
const mutationSuffix = hasReviewMutations ? " before review mutations" : "";
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
}
|
|
91
|
-
else if (hasNonConflictHints) {
|
|
92
|
-
instructions.push("If you changed code, commit any remaining changes and push to the PR head branch. If you did not, do not commit.");
|
|
93
|
-
}
|
|
94
|
-
if (viewerCanUpdate &&
|
|
77
|
+
const genericPush = !(branchRecovery || queueEjection) && hasNonConflictHints;
|
|
78
|
+
const wantsJournal = viewerCanUpdate &&
|
|
95
79
|
(hasReviewMutations ||
|
|
96
80
|
hasNonConflictHints ||
|
|
97
81
|
firstLookTotal > 0 ||
|
|
98
82
|
firstLookSummaries.length > 0 ||
|
|
99
|
-
editedTotal > 0)
|
|
100
|
-
|
|
83
|
+
editedTotal > 0);
|
|
84
|
+
if (branchRecovery || queueEjection) {
|
|
85
|
+
instructions.push(buildBranchPushInstruction(stackRebase, hasConflicts, mutationSuffix, !branchRecovery));
|
|
101
86
|
}
|
|
87
|
+
instructions.push(...buildPushJournalSteps(instructionStyle, prReference, genericPush, wantsJournal));
|
|
102
88
|
if (resolveOnlyCommand?.hasMutations)
|
|
103
|
-
instructions.push(
|
|
104
|
-
instructions.push(...buildResolveCommandInstruction(resolveCommand), buildFixCompletionInstruction());
|
|
89
|
+
instructions.push(`Run: \`${renderResolveCommand(resolveOnlyCommand)}\``);
|
|
90
|
+
instructions.push(...buildResolveCommandInstruction(resolveCommand, renderResolveCommand(resolveCommand)), buildFixCompletionInstruction());
|
|
105
91
|
return instructions;
|
|
106
92
|
}
|
|
@@ -2,6 +2,9 @@ import { graphql } from "../../github/client.mjs";
|
|
|
2
2
|
import { readStackTopology, verifiedBottomOpenLayer } from "../../github/stack-read.mjs";
|
|
3
3
|
import { UPPER_LAYER_CONFLICT_TARGET_QUERY } from "../../github/queries.mjs";
|
|
4
4
|
import { pollRateLimitRetryAfterMs } from "../poll-quota.mjs";
|
|
5
|
+
import { githubOperation } from "../../github/transport.mjs";
|
|
6
|
+
import { readRestPull } from "../../github/rest-pr-core.mjs";
|
|
7
|
+
import { readRestBehind } from "../../github/rest-check-read.mjs";
|
|
5
8
|
export async function lookupUpperLayerTrunkConflict(input) {
|
|
6
9
|
let bottomPr = input.bottomPr;
|
|
7
10
|
if (bottomPr === undefined) {
|
|
@@ -31,11 +34,24 @@ export async function lookupUpperLayerTrunkConflict(input) {
|
|
|
31
34
|
return { trunk: input.trunk, bottomPr };
|
|
32
35
|
let data;
|
|
33
36
|
try {
|
|
34
|
-
({ data } = await graphql(UPPER_LAYER_CONFLICT_TARGET_QUERY, {
|
|
37
|
+
({ data } = await githubOperation("UpperLayerConflictTarget", () => graphql(UPPER_LAYER_CONFLICT_TARGET_QUERY, {
|
|
35
38
|
owner: input.owner,
|
|
36
39
|
name: input.name,
|
|
37
40
|
number: input.pr,
|
|
38
41
|
headRef: input.headRef,
|
|
42
|
+
}), async () => {
|
|
43
|
+
const repo = { owner: input.owner, name: input.name };
|
|
44
|
+
const pull = await readRestPull(input.pr, repo);
|
|
45
|
+
const behindBy = await readRestBehind(repo, pull.base.ref, input.headRef);
|
|
46
|
+
return {
|
|
47
|
+
data: {
|
|
48
|
+
repository: {
|
|
49
|
+
pullRequest: {
|
|
50
|
+
baseRef: { compare: { behindBy } },
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
};
|
|
39
55
|
}));
|
|
40
56
|
}
|
|
41
57
|
catch (err) {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { readStackTopology, stackAncestryGaps } from "../../github/stack-read.mjs";
|
|
2
2
|
import { buildNativeStackRebaseInstruction } from "./native-stack-rebase.mjs";
|
|
3
|
+
import { getGithubTransport } from "../../github/transport.mjs";
|
|
3
4
|
/**
|
|
4
5
|
* Find a stale immediate parent boundary for one PR.
|
|
5
6
|
*
|
|
@@ -36,6 +37,8 @@ function buildStaleNativeStackAncestryInstructions(repo, stackNumber, ancestry)
|
|
|
36
37
|
buildNativeStackRebaseInstruction(`${repo.owner}/${repo.name}`, stackNumber, {
|
|
37
38
|
parentBranch: ancestry.parentHeadRefName,
|
|
38
39
|
}),
|
|
39
|
-
|
|
40
|
+
getGithubTransport() === "rest"
|
|
41
|
+
? "Push every affected stack branch using the repository's stack-update procedure."
|
|
42
|
+
: "Push the rewritten stack with `gh stack push`.",
|
|
40
43
|
];
|
|
41
44
|
}
|
|
@@ -3,4 +3,8 @@ export declare function applyStallGuard(stallKey: {
|
|
|
3
3
|
owner: string;
|
|
4
4
|
repo: string;
|
|
5
5
|
pr: number;
|
|
6
|
-
}, stallTimeoutSeconds: number, headSha: string, base: IterateResultBase, prNumber: number, prospectiveResult: IterateResult, report: ShepherdReport, reviewSummaryIds: string[]): Promise<IterateResult>;
|
|
6
|
+
}, stallTimeoutSeconds: number, headSha: string, base: IterateResultBase, prNumber: number, prospectiveResult: IterateResult, report: ShepherdReport, reviewSummaryIds: string[], stallDeadlineSink?: StallDeadlineSink): Promise<IterateResult>;
|
|
7
|
+
/** Internal out-parameter: when the earliest unstarted check would trip the CI-start stall. */
|
|
8
|
+
export interface StallDeadlineSink {
|
|
9
|
+
ciStartDeadlineSeconds?: number;
|
|
10
|
+
}
|
|
@@ -62,13 +62,14 @@ function computeStallFingerprint(action, headSha, base, report, reviewSummaryIds
|
|
|
62
62
|
annotations,
|
|
63
63
|
});
|
|
64
64
|
}
|
|
65
|
-
export async function applyStallGuard(stallKey, stallTimeoutSeconds, headSha, base, prNumber, prospectiveResult, report, reviewSummaryIds) {
|
|
65
|
+
export async function applyStallGuard(stallKey, stallTimeoutSeconds, headSha, base, prNumber, prospectiveResult, report, reviewSummaryIds, stallDeadlineSink) {
|
|
66
66
|
const prReference = formatPrUrl(report.repo, prNumber);
|
|
67
67
|
const nowSeconds = Math.floor(Date.now() / 1000);
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
68
|
+
const ciStartOpts = { stallTimeoutSeconds, action: prospectiveResult.action };
|
|
69
|
+
const stalledChecks = findCiStartStalledChecks(report.checks.inProgress, nowSeconds, ciStartOpts);
|
|
70
|
+
if (stallDeadlineSink) {
|
|
71
|
+
stallDeadlineSink.ciStartDeadlineSeconds = ciStartStallDeadline(report.checks.inProgress, nowSeconds, ciStartOpts);
|
|
72
|
+
}
|
|
72
73
|
if (stalledChecks.length > 0) {
|
|
73
74
|
const pending = pendingReviewCommandsFromResult(prospectiveResult);
|
|
74
75
|
const stalledDuration = formatDurationApprox(Math.max(...stalledChecks.map((c) => c.ageSeconds)));
|
|
@@ -168,13 +169,24 @@ function stallStateUnavailable(base, prReference, prospectiveResult, reason) {
|
|
|
168
169
|
},
|
|
169
170
|
};
|
|
170
171
|
}
|
|
171
|
-
function
|
|
172
|
+
function unstartedStallCandidates(checks, nowSeconds, opts) {
|
|
172
173
|
if (opts.stallTimeoutSeconds <= 0 || opts.action !== "wait")
|
|
173
174
|
return [];
|
|
174
175
|
return checks
|
|
175
176
|
.filter((c) => isUnstartedCheck(c))
|
|
176
177
|
.map((c) => toAgentStalledCheck(c, nowSeconds))
|
|
177
|
-
.filter((c) => c.createdAtUnix !== undefined
|
|
178
|
+
.filter((c) => c.createdAtUnix !== undefined);
|
|
179
|
+
}
|
|
180
|
+
function findCiStartStalledChecks(checks, nowSeconds, opts) {
|
|
181
|
+
return unstartedStallCandidates(checks, nowSeconds, opts).filter((c) => c.ageSeconds >= opts.stallTimeoutSeconds);
|
|
182
|
+
}
|
|
183
|
+
/** Unix seconds at which the oldest unstarted check reaches the stall timeout, if any. */
|
|
184
|
+
function ciStartStallDeadline(checks, nowSeconds, opts) {
|
|
185
|
+
const candidates = unstartedStallCandidates(checks, nowSeconds, opts);
|
|
186
|
+
if (candidates.length === 0)
|
|
187
|
+
return undefined;
|
|
188
|
+
const maxAge = Math.max(...candidates.map((c) => c.ageSeconds));
|
|
189
|
+
return nowSeconds - maxAge + opts.stallTimeoutSeconds;
|
|
178
190
|
}
|
|
179
191
|
function isUnstartedCheck(check) {
|
|
180
192
|
if (check.source === "status_context")
|
|
@@ -10,6 +10,7 @@ export interface ThreadMutationRouting {
|
|
|
10
10
|
}
|
|
11
11
|
export declare function threadHasAuthorizedMutation(thread: {
|
|
12
12
|
id: string;
|
|
13
|
+
isResolved?: boolean;
|
|
13
14
|
viewerCanReply?: boolean;
|
|
14
15
|
viewerCanResolve?: boolean;
|
|
15
16
|
}, replyThreadIds: ReadonlySet<string>, resolveThreadIds: ReadonlySet<string>): boolean;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { isConfiguredBotAuthor, isHumanAuthor, isViewerAuthoredHuman, } from "../../comments/authors.mjs";
|
|
2
2
|
import { threadEndedByShepherd } from "../../comments/marker.mjs";
|
|
3
3
|
import { shouldResolveOtherHumanThread } from "../../comments/thread-resolve-policy.mjs";
|
|
4
|
+
import { canGenerateGithubMutation } from "../../github/mutation-policy.mjs";
|
|
4
5
|
function dedupeIds(ids) {
|
|
5
6
|
return [...new Set(ids)];
|
|
6
7
|
}
|
|
@@ -19,9 +20,10 @@ export function threadHasAuthorizedMutation(thread, replyThreadIds, resolveThrea
|
|
|
19
20
|
const inResolve = resolveThreadIds.has(thread.id);
|
|
20
21
|
if (!inReply && !inResolve)
|
|
21
22
|
return false;
|
|
22
|
-
if (inReply && thread.viewerCanReply
|
|
23
|
+
if (inReply && !canGenerateGithubMutation(thread.viewerCanReply, "reply"))
|
|
23
24
|
return false;
|
|
24
|
-
if (inResolve &&
|
|
25
|
+
if (inResolve &&
|
|
26
|
+
(thread.isResolved !== false || !canGenerateGithubMutation(thread.viewerCanResolve, "resolve")))
|
|
25
27
|
return false;
|
|
26
28
|
return true;
|
|
27
29
|
}
|
|
@@ -4,6 +4,7 @@ import { readCiRetrigger, sameCiRetrigger, writeCiRetrigger } from "../../state/
|
|
|
4
4
|
import { buildFixCompletionInstruction } from "./check-instructions.mjs";
|
|
5
5
|
import { buildEscalateHumanMessage, buildEscalateSuggestion } from "./escalate.mjs";
|
|
6
6
|
import { buildNativeStackRebaseInstruction } from "./native-stack-rebase.mjs";
|
|
7
|
+
import { getGithubTransport } from "../../github/transport.mjs";
|
|
7
8
|
/** Rebase when the trunk or the PR base is behind; otherwise close and reopen once. */
|
|
8
9
|
function decideUnreportedRequired(input) {
|
|
9
10
|
if (input.behind)
|
|
@@ -29,12 +30,14 @@ function buildUnreportedRequiredInstructions(input) {
|
|
|
29
30
|
if (!input.behind) {
|
|
30
31
|
return [
|
|
31
32
|
facts,
|
|
32
|
-
|
|
33
|
+
getGithubTransport() === "rest"
|
|
34
|
+
? `Retrigger workflows once for this head: run \`gh api --method PATCH repos/${input.repo}/pulls/${input.pr} -f state=closed\`, then run \`gh api --method PATCH repos/${input.repo}/pulls/${input.pr} -f state=open\`.`
|
|
35
|
+
: `Retrigger workflows once for this head with \`gh pr close ${input.pr} -R ${input.repo}\` then \`gh pr reopen ${input.pr} -R ${input.repo}\`.`,
|
|
33
36
|
"If those checks are still missing on the next poll, investigate why the workflows did not start. Do not close the PR again. Shepherd escalates with `required-checks-unreported` when this remains the only blocker.",
|
|
34
37
|
];
|
|
35
38
|
}
|
|
36
39
|
const rebase = input.stackRebase
|
|
37
|
-
? `${input.stackRebase} Then push the rewritten stack with
|
|
40
|
+
? `${input.stackRebase} Then push the rewritten stack${getGithubTransport() === "rest" ? " using the repository's stack-update procedure" : " with `gh stack push`"}.`
|
|
38
41
|
: `Rebase onto \`${input.baseBranch}\` and push.`;
|
|
39
42
|
return [
|
|
40
43
|
facts,
|