pr-shepherd 0.56.5 → 0.57.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +40 -19
- 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.d.mts +6 -5
- package/bin/commands/iterate/native-stack-rebase.mjs +24 -7
- package/bin/commands/iterate/render.d.mts +8 -2
- package/bin/commands/iterate/render.mjs +28 -42
- package/bin/commands/iterate/stack-trunk-conflict.d.mts +4 -2
- package/bin/commands/iterate/stack-trunk-conflict.mjs +44 -19
- 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/gql/upper-layer-conflict-target.gql +0 -15
- 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 +16 -3
- package/bin/github/merge-target-rules.mjs +79 -44
- 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 +6 -3
- package/bin/github/poll-summary-unreported.mjs +15 -7
- package/bin/github/poll-summary.d.mts +4 -1
- package/bin/github/poll-summary.mjs +48 -34
- package/bin/github/queries.d.mts +9 -5
- package/bin/github/queries.mjs +10 -6
- 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 -3
- package/bin/github/stack-read.mjs +22 -11
- 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
|
@@ -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 [];
|
|
@@ -22,10 +22,11 @@ export declare function buildNativeStackRebaseInstruction(repo: string, stackNum
|
|
|
22
22
|
/**
|
|
23
23
|
* The stack-aware branch update for a native stack layer (a conflict, or a behind branch whose
|
|
24
24
|
* workflow keeps failing); undefined outside a stack.
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
* upper layer already contains its parent, so the rebase starts
|
|
25
|
+
* The first open layer in validated stack order is the bottom open layer, even when GitHub
|
|
26
|
+
* retains its merged parent's branch as its PR base. Without that topology, a PR base matching
|
|
27
|
+
* the stack trunk also identifies a bottom layer. Other layers rebase from their PR base.
|
|
28
|
+
* `trunkConflict` means an upper layer already contains its parent, so the rebase starts
|
|
29
|
+
* at the bottom open layer.
|
|
29
30
|
*/
|
|
30
31
|
export declare function buildNativeStackLayerRebase(repo: string, pr: {
|
|
31
32
|
number: number;
|
|
@@ -33,7 +34,7 @@ export declare function buildNativeStackLayerRebase(repo: string, pr: {
|
|
|
33
34
|
}, stack: StackStatus | undefined, trunkConflict?: {
|
|
34
35
|
trunk: string;
|
|
35
36
|
bottomPr?: number;
|
|
36
|
-
}): string | undefined;
|
|
37
|
+
}, stackBottomPr?: number): string | undefined;
|
|
37
38
|
/** Point at the conflicts, and at the stack rebase when the PR is a native stack layer. */
|
|
38
39
|
export declare function buildConflictInstruction(stackRebase: string | undefined): string;
|
|
39
40
|
/**
|
|
@@ -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}\``,
|
|
@@ -15,26 +24,32 @@ export function buildNativeStackRebaseInstruction(repo, stackNumber, start) {
|
|
|
15
24
|
]
|
|
16
25
|
: "bottomPr" in start
|
|
17
26
|
? [`check out the head branch of PR #${start.bottomPr}`, "gh stack rebase"]
|
|
18
|
-
: [
|
|
27
|
+
: [
|
|
28
|
+
`check out the bottom open layer of the stack to rebase onto \`${start.trunk}\``,
|
|
29
|
+
"gh stack rebase",
|
|
30
|
+
];
|
|
19
31
|
const prepare = `if \`gh stack\` does not track stack #${stackNumber} locally, import it with \`gh stack checkout ${stackNumber}\``;
|
|
20
32
|
return `From a clean checkout of \`${repo}\`, ${prepare}. Then ${checkout} and run \`${command}\`. ${playbookPointer("Branch update")}`;
|
|
21
33
|
}
|
|
22
34
|
/**
|
|
23
35
|
* The stack-aware branch update for a native stack layer (a conflict, or a behind branch whose
|
|
24
36
|
* workflow keeps failing); undefined outside a stack.
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
* upper layer already contains its parent, so the rebase starts
|
|
37
|
+
* The first open layer in validated stack order is the bottom open layer, even when GitHub
|
|
38
|
+
* retains its merged parent's branch as its PR base. Without that topology, a PR base matching
|
|
39
|
+
* the stack trunk also identifies a bottom layer. Other layers rebase from their PR base.
|
|
40
|
+
* `trunkConflict` means an upper layer already contains its parent, so the rebase starts
|
|
41
|
+
* at the bottom open layer.
|
|
29
42
|
*/
|
|
30
|
-
export function buildNativeStackLayerRebase(repo, pr, stack, trunkConflict) {
|
|
43
|
+
export function buildNativeStackLayerRebase(repo, pr, stack, trunkConflict, stackBottomPr) {
|
|
31
44
|
if (!stack)
|
|
32
45
|
return undefined;
|
|
33
46
|
const start = trunkConflict
|
|
34
47
|
? trunkConflict.bottomPr !== undefined
|
|
35
48
|
? { bottomPr: trunkConflict.bottomPr }
|
|
36
49
|
: { trunk: trunkConflict.trunk }
|
|
37
|
-
:
|
|
50
|
+
: (stackBottomPr !== undefined
|
|
51
|
+
? pr.number === stackBottomPr
|
|
52
|
+
: pr.baseBranch === stack.baseRefName)
|
|
38
53
|
? { bottomPr: pr.number }
|
|
39
54
|
: { parentBranch: pr.baseBranch };
|
|
40
55
|
return buildNativeStackRebaseInstruction(repo, stack.number, start);
|
|
@@ -49,6 +64,8 @@ export function buildConflictInstruction(stackRebase) {
|
|
|
49
64
|
* After a merge-queue ejection update, push only when the update or a fix changed the head.
|
|
50
65
|
*/
|
|
51
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.`;
|
|
52
69
|
if (ejectionUpdate) {
|
|
53
70
|
const push = stackRebase
|
|
54
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
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/** A bottom open layer, or an upper layer that already contains its parent, updates from trunk. */
|
|
2
2
|
export interface UpperLayerTrunkConflict {
|
|
3
3
|
trunk: string;
|
|
4
|
-
/**
|
|
4
|
+
/** First open layer after a verified merged prefix. Omitted when topology is unavailable. */
|
|
5
5
|
bottomPr?: number;
|
|
6
6
|
}
|
|
7
7
|
export declare function lookupUpperLayerTrunkConflict(input: {
|
|
@@ -10,4 +10,6 @@ export declare function lookupUpperLayerTrunkConflict(input: {
|
|
|
10
10
|
pr: number;
|
|
11
11
|
headRef: string;
|
|
12
12
|
trunk: string;
|
|
13
|
+
/** Reuse the bottom layer already resolved for the report, avoiding a topology fetch. */
|
|
14
|
+
bottomPr?: number;
|
|
13
15
|
}): Promise<UpperLayerTrunkConflict | undefined>;
|
|
@@ -1,25 +1,57 @@
|
|
|
1
1
|
import { graphql } from "../../github/client.mjs";
|
|
2
|
+
import { readStackTopology, verifiedBottomOpenLayer } from "../../github/stack-read.mjs";
|
|
2
3
|
import { UPPER_LAYER_CONFLICT_TARGET_QUERY } from "../../github/queries.mjs";
|
|
3
4
|
import { pollRateLimitRetryAfterMs } from "../poll-quota.mjs";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const pull = node?.pullRequest;
|
|
8
|
-
if (!node || !pull || pull.state !== "OPEN" || pull.baseRefName !== trunk)
|
|
9
|
-
return [];
|
|
10
|
-
return [{ position: node.position, number: pull.number }];
|
|
11
|
-
});
|
|
12
|
-
onTrunk.sort((a, b) => a.position - b.position);
|
|
13
|
-
return onTrunk[0]?.number;
|
|
14
|
-
}
|
|
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";
|
|
15
8
|
export async function lookupUpperLayerTrunkConflict(input) {
|
|
9
|
+
let bottomPr = input.bottomPr;
|
|
10
|
+
if (bottomPr === undefined) {
|
|
11
|
+
let topology;
|
|
12
|
+
try {
|
|
13
|
+
topology = await readStackTopology(input.pr, { owner: input.owner, name: input.name });
|
|
14
|
+
}
|
|
15
|
+
catch (err) {
|
|
16
|
+
if (pollRateLimitRetryAfterMs(err) !== null)
|
|
17
|
+
throw err;
|
|
18
|
+
ignore(input.pr, err instanceof Error ? err.message : String(err));
|
|
19
|
+
}
|
|
20
|
+
if (topology) {
|
|
21
|
+
try {
|
|
22
|
+
bottomPr = verifiedBottomOpenLayer(topology.ordered, input.pr).number;
|
|
23
|
+
}
|
|
24
|
+
catch (err) {
|
|
25
|
+
ignore(input.pr, err instanceof Error ? err.message : String(err));
|
|
26
|
+
// A base comparison cannot prove that a closed or unverified predecessor merged.
|
|
27
|
+
return undefined;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
// Merged lower layers need not cause GitHub to retarget this PR to trunk. Even when its
|
|
32
|
+
// head is behind that old parent branch, the first open layer rebases the stack onto trunk.
|
|
33
|
+
if (bottomPr === input.pr)
|
|
34
|
+
return { trunk: input.trunk, bottomPr };
|
|
16
35
|
let data;
|
|
17
36
|
try {
|
|
18
|
-
({ data } = await graphql(UPPER_LAYER_CONFLICT_TARGET_QUERY, {
|
|
37
|
+
({ data } = await githubOperation("UpperLayerConflictTarget", () => graphql(UPPER_LAYER_CONFLICT_TARGET_QUERY, {
|
|
19
38
|
owner: input.owner,
|
|
20
39
|
name: input.name,
|
|
21
40
|
number: input.pr,
|
|
22
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
|
+
};
|
|
23
55
|
}));
|
|
24
56
|
}
|
|
25
57
|
catch (err) {
|
|
@@ -37,13 +69,6 @@ export async function lookupUpperLayerTrunkConflict(input) {
|
|
|
37
69
|
// behindBy > 0: the layer is still behind its parent. Keep the parent rebase.
|
|
38
70
|
if (behindBy !== 0)
|
|
39
71
|
return undefined;
|
|
40
|
-
const entries = pull.stack?.entries;
|
|
41
|
-
const bottomPr = entries ? selectBottomOpenLayer(entries.nodes, input.trunk) : undefined;
|
|
42
|
-
if (bottomPr === undefined) {
|
|
43
|
-
ignore(input.pr, entries?.pageInfo.hasNextPage
|
|
44
|
-
? "stack entry page truncated before the trunk layer"
|
|
45
|
-
: "bottom open layer not found");
|
|
46
|
-
}
|
|
47
72
|
return { trunk: input.trunk, ...(bottomPr !== undefined && { bottomPr }) };
|
|
48
73
|
}
|
|
49
74
|
function ignore(pr, message) {
|
|
@@ -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
|
}
|