pr-shepherd 0.56.6 → 0.57.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +44 -27
- package/bin/api.d.mts +25 -3
- package/bin/api.mjs +51 -13
- package/bin/checks/classify.d.mts +1 -0
- package/bin/checks/classify.mjs +1 -1
- package/bin/checks/conclusions.d.mts +5 -1
- package/bin/checks/conclusions.mjs +8 -2
- package/bin/checks/superseded.d.mts +8 -2
- package/bin/checks/superseded.mjs +24 -7
- package/bin/classify/loader.d.mts +2 -0
- package/bin/classify/loader.mjs +15 -0
- package/bin/classify/standard/author.d.mts +3 -0
- package/bin/classify/standard/author.mjs +10 -0
- package/bin/classify/standard/codecov-report.d.mts +4 -0
- package/bin/classify/standard/codecov-report.mjs +10 -0
- package/bin/classify/standard/coderabbit-notices.d.mts +8 -0
- package/bin/classify/standard/coderabbit-notices.mjs +38 -0
- package/bin/classify/standard/coderabbit-review-summary.d.mts +8 -0
- package/bin/classify/standard/coderabbit-review-summary.mjs +37 -0
- package/bin/classify/standard/codex-notices.d.mts +7 -0
- package/bin/classify/standard/codex-notices.mjs +36 -0
- package/bin/classify/standard/codex-review-summary.d.mts +7 -0
- package/bin/classify/standard/codex-review-summary.mjs +20 -0
- package/bin/classify/standard/dependabot-notices.d.mts +4 -0
- package/bin/classify/standard/dependabot-notices.mjs +15 -0
- package/bin/classify/standard/gemini-notices.d.mts +4 -0
- package/bin/classify/standard/gemini-notices.mjs +13 -0
- package/bin/classify/standard/index.d.mts +4 -0
- package/bin/classify/standard/index.mjs +22 -0
- package/bin/classify/standard/kilo-no-issues.d.mts +4 -0
- package/bin/classify/standard/kilo-no-issues.mjs +17 -0
- package/bin/classify/standard/sourcery-notices.d.mts +8 -0
- package/bin/classify/standard/sourcery-notices.mjs +20 -0
- package/bin/cli/api-usage-formatter.mjs +6 -1
- package/bin/cli/apply-merge-handler.d.mts +3 -0
- package/bin/cli/apply-merge-handler.mjs +73 -0
- package/bin/cli/arg-flags.d.mts +2 -0
- package/bin/cli/arg-flags.mjs +47 -0
- package/bin/cli/args.mjs +10 -41
- package/bin/cli/clean-handler.d.mts +1 -0
- package/bin/cli/clean-handler.mjs +71 -0
- package/bin/cli/default-poll.mjs +3 -0
- package/bin/cli/event-state-scope.d.mts +19 -0
- package/bin/cli/event-state-scope.mjs +60 -0
- package/bin/cli/fix-formatter.mjs +5 -11
- package/bin/cli/handlers.d.mts +0 -1
- package/bin/cli/handlers.mjs +8 -64
- package/bin/cli/help-command-pages.d.mts +62 -18
- package/bin/cli/help-command-pages.mjs +59 -15
- package/bin/cli/help-iterate-poll-pages.d.mts +2 -2
- package/bin/cli/help-iterate-poll-pages.mjs +6 -0
- package/bin/cli/help-log-file-page.d.mts +1 -1
- package/bin/cli/help-log-file-page.mjs +4 -1
- package/bin/cli/help-top-page.d.mts +1 -1
- package/bin/cli/help-top-page.mjs +5 -0
- package/bin/cli/help.d.mts +63 -19
- package/bin/cli/help.mjs +2 -0
- package/bin/cli/iterate-branch-segment.d.mts +2 -0
- package/bin/cli/iterate-branch-segment.mjs +12 -7
- package/bin/cli/iterate-flags.d.mts +7 -1
- package/bin/cli/iterate-flags.mjs +38 -0
- package/bin/cli/iterate-formatter.d.mts +6 -6
- package/bin/cli/iterate-formatter.mjs +56 -22
- package/bin/cli/iterate-instructions.mjs +45 -15
- package/bin/cli/iterate-lean.mjs +39 -14
- package/bin/cli/iterate-merge-formatter.d.mts +6 -0
- package/bin/cli/iterate-merge-formatter.mjs +24 -14
- package/bin/cli/iterate-verbose.mjs +3 -6
- package/bin/cli/list-formatters.mjs +3 -1
- package/bin/cli/mutate-formatter.mjs +10 -5
- package/bin/cli/next-check-format.d.mts +7 -0
- package/bin/cli/next-check-format.mjs +10 -0
- package/bin/cli/playbook-handler.d.mts +5 -0
- package/bin/cli/playbook-handler.mjs +40 -0
- package/bin/cli/poll-handler.mjs +7 -6
- package/bin/cli/poll-summary-formatter.mjs +11 -2
- package/bin/cli/poll-targets.mjs +2 -0
- package/bin/cli/resolve-validators.mjs +2 -2
- package/bin/cli/runner.mjs +6 -1
- package/bin/cli/stack-layer-view.d.mts +33 -0
- package/bin/cli/stack-layer-view.mjs +1 -0
- package/bin/cli/stack-overview.d.mts +10 -28
- package/bin/cli/stack-overview.mjs +39 -14
- package/bin/cli/transport-args.d.mts +5 -0
- package/bin/cli/transport-args.mjs +23 -0
- package/bin/cli/transport-formatter.d.mts +9 -0
- package/bin/cli/transport-formatter.mjs +13 -0
- package/bin/cli-parser.mjs +62 -7
- package/bin/commands/apply-merge-options.d.mts +4 -0
- package/bin/commands/apply-merge-options.mjs +34 -0
- package/bin/commands/apply-merge-output.d.mts +7 -0
- package/bin/commands/apply-merge-output.mjs +20 -0
- package/bin/commands/apply-merge-pull.d.mts +20 -0
- package/bin/commands/apply-merge-pull.mjs +15 -0
- package/bin/commands/apply-merge.d.mts +18 -0
- package/bin/commands/apply-merge.mjs +126 -0
- package/bin/commands/apply-queue-removal.mjs +7 -0
- package/bin/commands/check-annotations.mjs +28 -18
- package/bin/commands/check-execution-context.d.mts +5 -0
- package/bin/commands/check-execution-context.mjs +16 -1
- package/bin/commands/check-fingerprint.d.mts +26 -2
- package/bin/commands/check-fingerprint.mjs +64 -28
- package/bin/commands/check-terminal-report.mjs +11 -1
- package/bin/commands/check-unreported.d.mts +6 -2
- package/bin/commands/check-unreported.mjs +32 -12
- package/bin/commands/check-wait-detectors.d.mts +35 -0
- package/bin/commands/check-wait-detectors.mjs +107 -0
- package/bin/commands/check.d.mts +4 -2
- package/bin/commands/check.mjs +130 -40
- package/bin/commands/event-instructions.d.mts +11 -0
- package/bin/commands/event-instructions.mjs +27 -0
- package/bin/commands/event-mode.d.mts +14 -0
- package/bin/commands/event-mode.mjs +138 -0
- package/bin/commands/iterate/api-usage.mjs +4 -2
- package/bin/commands/iterate/base.mjs +4 -0
- package/bin/commands/iterate/check-blocker-gate.mjs +14 -2
- package/bin/commands/iterate/check-instructions.d.mts +9 -10
- package/bin/commands/iterate/check-instructions.mjs +23 -22
- package/bin/commands/iterate/classify.mjs +19 -5
- package/bin/commands/iterate/escalate.mjs +13 -3
- package/bin/commands/iterate/fix-code.mjs +26 -9
- package/bin/commands/iterate/fix-instruction-threads.d.mts +0 -8
- package/bin/commands/iterate/fix-instruction-threads.mjs +0 -16
- package/bin/commands/iterate/fix-loop-instruction.d.mts +9 -0
- package/bin/commands/iterate/fix-loop-instruction.mjs +35 -0
- package/bin/commands/iterate/helpers.mjs +15 -2
- package/bin/commands/iterate/index.mjs +26 -4
- package/bin/commands/iterate/mark-ready.mjs +50 -10
- package/bin/commands/iterate/merge-plan.d.mts +19 -0
- package/bin/commands/iterate/merge-plan.mjs +88 -0
- package/bin/commands/iterate/merge-state.mjs +3 -0
- package/bin/commands/iterate/merge.d.mts +4 -15
- package/bin/commands/iterate/merge.mjs +18 -51
- package/bin/commands/iterate/merged-base-pull-requests.d.mts +2 -6
- package/bin/commands/iterate/merged-base-pull-requests.mjs +15 -11
- package/bin/commands/iterate/native-stack-rebase.mjs +11 -0
- package/bin/commands/iterate/render.d.mts +8 -2
- package/bin/commands/iterate/render.mjs +28 -42
- package/bin/commands/iterate/stack-trunk-conflict.mjs +17 -1
- package/bin/commands/iterate/stale-ancestry.mjs +4 -1
- package/bin/commands/iterate/stall.d.mts +5 -1
- package/bin/commands/iterate/stall.mjs +19 -7
- package/bin/commands/iterate/thread-mutation-routing.d.mts +1 -0
- package/bin/commands/iterate/thread-mutation-routing.mjs +4 -2
- package/bin/commands/iterate/unreported-required.mjs +5 -2
- package/bin/commands/mark-files-as-viewed.mjs +7 -0
- package/bin/commands/next-check.d.mts +31 -0
- package/bin/commands/next-check.mjs +46 -0
- package/bin/commands/playbook.d.mts +13 -0
- package/bin/commands/playbook.mjs +48 -0
- package/bin/commands/poll-mode.d.mts +8 -0
- package/bin/commands/poll-mode.mjs +14 -0
- package/bin/commands/poll-progress.d.mts +1 -0
- package/bin/commands/poll-progress.mjs +6 -3
- package/bin/commands/poll-quota.d.mts +3 -2
- package/bin/commands/poll-quota.mjs +7 -3
- package/bin/commands/poll-summary-explicit-instructions.d.mts +2 -0
- package/bin/commands/poll-summary-explicit-instructions.mjs +10 -1
- package/bin/commands/poll-summary-instructions.mjs +16 -17
- package/bin/commands/poll-summary.mjs +42 -17
- package/bin/commands/poll.d.mts +0 -1
- package/bin/commands/poll.mjs +11 -19
- package/bin/commands/quota-selection.d.mts +2 -1
- package/bin/commands/quota-selection.mjs +12 -7
- package/bin/commands/resolve-mutate.mjs +33 -5
- package/bin/commands/rest-stack-merge-readiness.d.mts +4 -0
- package/bin/commands/rest-stack-merge-readiness.mjs +74 -0
- package/bin/commands/rule-auto-resolve.mjs +9 -3
- package/bin/commands/shepherd-journal.d.mts +5 -4
- package/bin/commands/shepherd-journal.mjs +9 -8
- package/bin/commands/stack-drain.d.mts +1 -9
- package/bin/commands/stack-drain.mjs +50 -37
- package/bin/commands/stack-handoffs.d.mts +10 -0
- package/bin/commands/stack-handoffs.mjs +25 -0
- package/bin/commands/stack-stall.d.mts +5 -0
- package/bin/commands/stack-stall.mjs +11 -0
- package/bin/commands/stack-work.d.mts +5 -0
- package/bin/commands/stack-work.mjs +32 -0
- package/bin/comments/existing-reply-scan.d.mts +17 -0
- package/bin/comments/existing-reply-scan.mjs +41 -0
- package/bin/comments/rate-limit.mjs +2 -2
- package/bin/comments/resolve.d.mts +7 -1
- package/bin/comments/resolve.mjs +108 -18
- package/bin/comments/rest-reply.d.mts +9 -0
- package/bin/comments/rest-reply.mjs +95 -0
- package/bin/comments/rest-review-mutations.d.mts +22 -0
- package/bin/comments/rest-review-mutations.mjs +125 -0
- package/bin/comments/review-visibility.d.mts +1 -1
- package/bin/comments/review-visibility.mjs +3 -2
- package/bin/comments/sha-poll.mjs +7 -3
- package/bin/comments/thread-visibility.mjs +10 -5
- package/bin/comments/uncertain-replies.d.mts +11 -0
- package/bin/comments/uncertain-replies.mjs +121 -0
- package/bin/comments/uncertain-reply-guards.d.mts +10 -0
- package/bin/comments/uncertain-reply-guards.mjs +94 -0
- package/bin/comments/visible-comments.d.mts +1 -1
- package/bin/comments/visible-comments.mjs +4 -2
- package/bin/config/load.d.mts +37 -1
- package/bin/config/load.mjs +73 -1
- package/bin/config.json +6 -2
- package/bin/exit-codes.d.mts +3 -0
- package/bin/exit-codes.mjs +8 -0
- package/bin/github/api-telemetry-aggregate.d.mts +15 -4
- package/bin/github/api-telemetry-aggregate.mjs +57 -18
- package/bin/github/api-telemetry.d.mts +4 -0
- package/bin/github/api-telemetry.mjs +22 -8
- package/bin/github/apply-review-preflight.d.mts +20 -0
- package/bin/github/apply-review-preflight.mjs +61 -0
- package/bin/github/base-behind-cache.d.mts +15 -0
- package/bin/github/base-behind-cache.mjs +18 -0
- package/bin/github/batch-parse-suites.d.mts +4 -2
- package/bin/github/batch-parse-suites.mjs +6 -1
- package/bin/github/batch-parser-helpers.mjs +40 -2
- package/bin/github/batch-parsers.mjs +1 -0
- package/bin/github/batch-raw-rules.d.mts +26 -0
- package/bin/github/batch-raw-types.d.mts +8 -6
- package/bin/github/batch-stack-evidence.d.mts +28 -0
- package/bin/github/batch-stack-evidence.mjs +62 -0
- package/bin/github/batch.d.mts +15 -2
- package/bin/github/batch.mjs +34 -17
- package/bin/github/check-annotations-batch.d.mts +0 -5
- package/bin/github/check-annotations-batch.mjs +25 -4
- package/bin/github/check-annotations.mjs +3 -1
- package/bin/github/client.d.mts +8 -19
- package/bin/github/client.mjs +45 -13
- package/bin/github/fingerprint-fields.d.mts +8 -0
- package/bin/github/fingerprint-fields.mjs +6 -1
- package/bin/github/fingerprint.d.mts +4 -2
- package/bin/github/fingerprint.mjs +6 -38
- package/bin/github/github-fetch.d.mts +2 -0
- package/bin/github/github-fetch.mjs +19 -0
- package/bin/github/gql/base-behind.gql +3 -0
- package/bin/github/gql/batch-pr-page.gql +16 -0
- package/bin/github/gql/batch-pr.gql +57 -0
- package/bin/github/gql/commit-check-contexts.gql +17 -0
- package/bin/github/gql/get-pr-body.gql +1 -0
- package/bin/github/gql/poll-stack-summary.gql +1 -0
- package/bin/github/gql/poll-summary-check-contexts.gql +5 -0
- package/bin/github/gql/poll-summary-fragment.gql +65 -15
- package/bin/github/gql/stack-handoff-check-runs.gql +42 -0
- package/bin/github/graphql-http.mjs +9 -4
- package/bin/github/graphql-internal-retry.d.mts +2 -0
- package/bin/github/graphql-internal-retry.mjs +1 -1
- package/bin/github/graphql-quota-probe.d.mts +6 -0
- package/bin/github/graphql-quota-probe.mjs +56 -0
- package/bin/github/graphql-session-refusal.d.mts +8 -0
- package/bin/github/graphql-session-refusal.mjs +14 -0
- package/bin/github/http-request.d.mts +1 -1
- package/bin/github/http-request.mjs +22 -6
- package/bin/github/http-utils.mjs +6 -0
- package/bin/github/merge-target-rules.d.mts +12 -3
- package/bin/github/merge-target-rules.mjs +71 -34
- package/bin/github/mutation-policy.d.mts +6 -0
- package/bin/github/mutation-policy.mjs +21 -0
- package/bin/github/poll-summary-annotation-probe.mjs +17 -10
- package/bin/github/poll-summary-check-blockers.d.mts +1 -1
- package/bin/github/poll-summary-check-blockers.mjs +2 -2
- package/bin/github/poll-summary-check-hydration.mjs +25 -10
- package/bin/github/poll-summary-checks.d.mts +2 -2
- package/bin/github/poll-summary-checks.mjs +9 -6
- package/bin/github/poll-summary-command.d.mts +2 -0
- package/bin/github/poll-summary-command.mjs +24 -0
- package/bin/github/poll-summary-fingerprint.d.mts +1 -1
- package/bin/github/poll-summary-fingerprint.mjs +4 -2
- package/bin/github/poll-summary-handoff-fields.d.mts +3 -0
- package/bin/github/poll-summary-handoff-fields.mjs +73 -0
- package/bin/github/poll-summary-projector.d.mts +1 -1
- package/bin/github/poll-summary-projector.mjs +17 -24
- package/bin/github/poll-summary-raw.d.mts +70 -10
- package/bin/github/poll-summary-readiness.mjs +4 -1
- package/bin/github/poll-summary-rest-queue.d.mts +3 -0
- package/bin/github/poll-summary-rest-queue.mjs +12 -0
- package/bin/github/poll-summary-review.d.mts +1 -1
- package/bin/github/poll-summary-review.mjs +23 -11
- package/bin/github/poll-summary-route.mjs +19 -3
- package/bin/github/poll-summary-stack-page.d.mts +11 -0
- package/bin/github/poll-summary-stack-page.mjs +27 -0
- package/bin/github/poll-summary-unreported.d.mts +3 -1
- package/bin/github/poll-summary-unreported.mjs +6 -3
- package/bin/github/poll-summary.d.mts +4 -1
- package/bin/github/poll-summary.mjs +47 -33
- package/bin/github/queries.d.mts +7 -3
- package/bin/github/queries.mjs +8 -4
- package/bin/github/rate-limit-sample.d.mts +7 -0
- package/bin/github/rate-limit-sample.mjs +12 -0
- package/bin/github/reply-recovery-read.d.mts +50 -0
- package/bin/github/reply-recovery-read.mjs +118 -0
- package/bin/github/reply-thread-transcripts.d.mts +0 -1
- package/bin/github/reply-thread-transcripts.mjs +24 -1
- package/bin/github/rest-annotation-read.d.mts +5 -0
- package/bin/github/rest-annotation-read.mjs +44 -0
- package/bin/github/rest-batch-read.d.mts +12 -0
- package/bin/github/rest-batch-read.mjs +57 -0
- package/bin/github/rest-batch-snapshot.d.mts +30 -0
- package/bin/github/rest-batch-snapshot.mjs +115 -0
- package/bin/github/rest-batch-unavailable.d.mts +5 -0
- package/bin/github/rest-batch-unavailable.mjs +16 -0
- package/bin/github/rest-check-read.d.mts +34 -0
- package/bin/github/rest-check-read.mjs +124 -0
- package/bin/github/rest-comment-authorship.d.mts +7 -0
- package/bin/github/rest-comment-authorship.mjs +11 -0
- package/bin/github/rest-conditional-scope.d.mts +20 -0
- package/bin/github/rest-conditional-scope.mjs +44 -0
- package/bin/github/rest-explicit-summary-read.d.mts +3 -0
- package/bin/github/rest-explicit-summary-read.mjs +8 -0
- package/bin/github/rest-feedback-read.d.mts +36 -0
- package/bin/github/rest-feedback-read.mjs +147 -0
- package/bin/github/rest-feedback-validation.d.mts +5 -0
- package/bin/github/rest-feedback-validation.mjs +28 -0
- package/bin/github/rest-http.d.mts +12 -0
- package/bin/github/rest-http.mjs +108 -23
- package/bin/github/rest-identities.d.mts +22 -0
- package/bin/github/rest-identities.mjs +134 -0
- package/bin/github/rest-merge-stack-guard.d.mts +14 -0
- package/bin/github/rest-merge-stack-guard.mjs +41 -0
- package/bin/github/rest-merge.d.mts +29 -0
- package/bin/github/rest-merge.mjs +56 -0
- package/bin/github/rest-merged-base-read.d.mts +9 -0
- package/bin/github/rest-merged-base-read.mjs +48 -0
- package/bin/github/rest-pr-core.d.mts +52 -0
- package/bin/github/rest-pr-core.mjs +60 -0
- package/bin/github/rest-reader-core.d.mts +16 -0
- package/bin/github/rest-reader-core.mjs +154 -0
- package/bin/github/rest-review-read.d.mts +11 -0
- package/bin/github/rest-review-read.mjs +47 -0
- package/bin/github/rest-rules-read.d.mts +9 -0
- package/bin/github/rest-rules-read.mjs +154 -0
- package/bin/github/rest-session-refusal.d.mts +5 -0
- package/bin/github/rest-session-refusal.mjs +21 -0
- package/bin/github/rest-snapshot-context.d.mts +10 -0
- package/bin/github/rest-snapshot-context.mjs +1 -0
- package/bin/github/rest-stack-read.d.mts +21 -0
- package/bin/github/rest-stack-read.mjs +47 -0
- package/bin/github/rest-stack-summary.d.mts +8 -0
- package/bin/github/rest-stack-summary.mjs +62 -0
- package/bin/github/rest-summary-read.d.mts +7 -0
- package/bin/github/rest-summary-read.mjs +112 -0
- package/bin/github/rest-terminal-batch.d.mts +14 -0
- package/bin/github/rest-terminal-batch.mjs +45 -0
- package/bin/github/rest-text.mjs +7 -3
- package/bin/github/rest-thread-read.d.mts +4 -0
- package/bin/github/rest-thread-read.mjs +35 -0
- package/bin/github/rest-viewer-read.d.mts +2 -0
- package/bin/github/rest-viewer-read.mjs +41 -0
- package/bin/github/stack-bottom.d.mts +3 -0
- package/bin/github/stack-bottom.mjs +14 -0
- package/bin/github/stack-handoff-context.d.mts +25 -0
- package/bin/github/stack-handoff-context.mjs +12 -0
- package/bin/github/stack-handoff-page.d.mts +17 -0
- package/bin/github/stack-handoff-page.mjs +306 -0
- package/bin/github/stack-handoff.d.mts +16 -0
- package/bin/github/stack-handoff.mjs +115 -0
- package/bin/github/stack-order.d.mts +6 -0
- package/bin/github/stack-order.mjs +13 -0
- package/bin/github/stack-read.d.mts +7 -5
- package/bin/github/stack-read.mjs +22 -24
- package/bin/github/stack-size-hint.d.mts +3 -0
- package/bin/github/stack-size-hint.mjs +14 -0
- package/bin/github/suggestion-thread.mjs +27 -1
- package/bin/github/thread-comments.mjs +9 -1
- package/bin/github/transport-evidence.d.mts +20 -0
- package/bin/github/transport-evidence.mjs +26 -0
- package/bin/github/transport-mode.d.mts +2 -0
- package/bin/github/transport-mode.mjs +5 -0
- package/bin/github/transport.d.mts +19 -0
- package/bin/github/transport.mjs +126 -0
- package/bin/github/unsupported-rest.d.mts +4 -0
- package/bin/github/unsupported-rest.mjs +7 -0
- package/bin/mcp/server.mjs +52 -3
- package/bin/merge-status/derive.d.mts +2 -0
- package/bin/merge-status/derive.mjs +17 -13
- package/bin/merge-status/required-check-requirements.d.mts +7 -0
- package/bin/merge-status/required-check-requirements.mjs +15 -0
- package/bin/merge-status/requirements-format.d.mts +5 -0
- package/bin/merge-status/requirements-format.mjs +41 -12
- package/bin/merge-status/requirements.mjs +18 -7
- package/bin/state/base.mjs +41 -0
- package/bin/state/durable-state.d.mts +6 -0
- package/bin/state/durable-state.mjs +41 -0
- package/bin/state/graphql-quota-policy.mjs +23 -16
- package/bin/state/merge-request.d.mts +25 -0
- package/bin/state/merge-request.mjs +145 -0
- package/bin/state/pr-fingerprint.d.mts +15 -0
- package/bin/state/pr-fingerprint.mjs +22 -7
- package/bin/state/rest-cache.d.mts +3 -0
- package/bin/state/rest-cache.mjs +1 -0
- package/bin/state/rest-snapshot-report.d.mts +21 -0
- package/bin/state/rest-snapshot-report.mjs +52 -0
- package/bin/state/seen-comments.d.mts +3 -0
- package/bin/state/seen-comments.mjs +18 -0
- package/bin/types/api-usage.d.mts +9 -1
- package/bin/types/escalate.d.mts +1 -1
- package/bin/types/github.d.mts +23 -9
- package/bin/types/iterate.d.mts +24 -2
- package/bin/types/merge-action.d.mts +1 -1
- package/bin/types/merge-requirements.d.mts +7 -7
- package/bin/types/next-check.d.mts +12 -0
- package/bin/types/next-check.mjs +1 -0
- package/bin/types/poll-summary.d.mts +21 -0
- package/bin/types/report.d.mts +13 -1
- package/bin/types/review-thread.d.mts +1 -1
- package/bin/types.d.mts +1 -0
- package/bin/types.mjs +1 -0
- package/package.json +3 -2
- package/plugins/pr-shepherd/.codex-plugin/plugin.json +1 -1
- package/plugins/pr-shepherd/.codex.mcp.json +1 -1
- package/plugins/pr-shepherd/.mcp.json +1 -1
- package/plugins/pr-shepherd/skills/mark-files-as-viewed/SKILL.md +1 -1
- package/plugins/pr-shepherd/skills/pr-shepherd/SKILL.md +14 -51
- package/plugins/pr-shepherd/skills/pr-shepherd/references/ci-failure-triage.md +12 -16
- package/plugins/pr-shepherd/skills/pr-shepherd/references/cloud-event-loop.md +14 -0
- package/plugins/pr-shepherd/skills/pr-shepherd/references/create-pr.md +10 -0
- package/plugins/pr-shepherd/skills/pr-shepherd/references/fix-code-loop.md +10 -0
- package/plugins/pr-shepherd/skills/pr-shepherd/references/mcp-fallback.md +9 -0
- package/plugins/pr-shepherd/skills/reduce-pr-noise/references/classifiers.md +2 -0
- package/bin/github/gql/pr-fingerprint.gql +0 -75
- package/plugins/pr-shepherd/skills/pr-shepherd/references/journal.md +0 -7
- package/plugins/pr-shepherd/skills/pr-shepherd/references/review-mutations.md +0 -9
- package/plugins/pr-shepherd/skills/pr-shepherd/references/stack-merge.md +0 -7
|
@@ -1,12 +1,19 @@
|
|
|
1
|
-
import { renderMergeCommand } from "../commands/iterate/merge.mjs";
|
|
2
1
|
import { inlineCode } from "../util/markdown.mjs";
|
|
3
2
|
import { buildQuotaAwareContinuation } from "../quota-warning.mjs";
|
|
4
3
|
import { formatPrUrl } from "../pr-reference.mjs";
|
|
5
4
|
import { AUTO_MARK_READY_DISABLED_HOLD } from "../commands/stack-work.mjs";
|
|
6
|
-
import { buildPrShepherdCommand } from "./runner.mjs";
|
|
5
|
+
import { buildPrShepherdCommand, renderShellCommand } from "./runner.mjs";
|
|
6
|
+
import { eventWaitSteps } from "../commands/event-instructions.mjs";
|
|
7
|
+
import { playbookPointer } from "../commands/playbook-pointer.mjs";
|
|
7
8
|
export function buildSimpleIterateInstructions(result) {
|
|
8
9
|
switch (result.action) {
|
|
9
10
|
case "ready": {
|
|
11
|
+
if (result.nextCheck) {
|
|
12
|
+
return [
|
|
13
|
+
`PR #${result.pr} is ready. Ready-delay has ${result.remainingSeconds}s left. Do not invent unrelated work.`,
|
|
14
|
+
...eventWaitSteps(result.nextCheck),
|
|
15
|
+
];
|
|
16
|
+
}
|
|
10
17
|
const sentence = `PR #${result.pr} is ready. Ready-delay has ${result.remainingSeconds}s left. Rerun this command when the timer elapses. Do not invent unrelated work.`;
|
|
11
18
|
return [
|
|
12
19
|
result.quotaWarning ? buildQuotaAwareContinuation(result.quotaWarning, sentence) : sentence,
|
|
@@ -14,7 +21,10 @@ export function buildSimpleIterateInstructions(result) {
|
|
|
14
21
|
}
|
|
15
22
|
case "wait":
|
|
16
23
|
if (result.stackDraftHold)
|
|
17
|
-
return
|
|
24
|
+
return buildStackDraftHoldInstructions(result, result.stackDraftHold);
|
|
25
|
+
if (result.nextCheck) {
|
|
26
|
+
return ["Non-terminal — no action needed this tick.", ...eventWaitSteps(result.nextCheck)];
|
|
27
|
+
}
|
|
18
28
|
if (result.quotaWarning) {
|
|
19
29
|
return [
|
|
20
30
|
buildQuotaAwareContinuation(result.quotaWarning, "Non-terminal — no action needed this tick."),
|
|
@@ -24,7 +34,8 @@ export function buildSimpleIterateInstructions(result) {
|
|
|
24
34
|
"Non-terminal — no action needed this tick. Iterate immediately with the same options to continue.",
|
|
25
35
|
];
|
|
26
36
|
case "mark_ready":
|
|
27
|
-
|
|
37
|
+
// Event mode reruns at once too: Shepherd is not polling, so no cadence applies.
|
|
38
|
+
if (result.quotaWarning && result.pollMode !== "event") {
|
|
28
39
|
return [
|
|
29
40
|
buildQuotaAwareContinuation(result.quotaWarning, "The CLI marked the PR ready for review."),
|
|
30
41
|
];
|
|
@@ -33,32 +44,43 @@ export function buildSimpleIterateInstructions(result) {
|
|
|
33
44
|
"The CLI marked the PR ready for review. Iterate immediately with the same options to continue.",
|
|
34
45
|
];
|
|
35
46
|
case "merge": {
|
|
47
|
+
// The commands are inline, so no separate `## Merge command` section repeats them.
|
|
48
|
+
const command = inlineCode(renderShellCommand(result.merge.command.argv));
|
|
49
|
+
if (result.merge.mode === "rest" && result.nextCheck)
|
|
50
|
+
return [
|
|
51
|
+
`Run the REST merge command exactly as printed: ${command}. \`enqueued\` is not merged.`,
|
|
52
|
+
...eventWaitSteps(result.nextCheck),
|
|
53
|
+
];
|
|
54
|
+
if (result.merge.mode === "rest")
|
|
55
|
+
return [
|
|
56
|
+
`Run the REST merge command exactly as printed: ${command}. If its status is \`pending\`, rerun that same command at the configured polling cadence to resume the recorded request; \`enqueued\` is not merged.`,
|
|
57
|
+
"Then iterate with the same options until GitHub confirms the PR merged or needs work.",
|
|
58
|
+
];
|
|
36
59
|
const instructions = [
|
|
37
|
-
`Run the
|
|
60
|
+
`Run the ${result.merge.mode === "queue" ? "merge queue" : "auto-merge"} command exactly as printed: ${command}.`,
|
|
38
61
|
];
|
|
39
62
|
if (result.merge.mode === "queue" && result.merge.queueApiFallbackCommand) {
|
|
40
|
-
instructions.push(`If
|
|
63
|
+
instructions.push(`If gh says auto-merge is disabled instead of adding the PR to the queue, run the queue API fallback: ${inlineCode(renderShellCommand(result.merge.queueApiFallbackCommand.argv))}.`);
|
|
41
64
|
}
|
|
42
65
|
else if (result.merge.fallbackCommand) {
|
|
43
|
-
instructions.push(`Only if GitHub reports that auto-merge is unavailable, run the
|
|
66
|
+
instructions.push(`Only if GitHub reports that auto-merge is unavailable, run the plain merge fallback: ${inlineCode(renderShellCommand(result.merge.fallbackCommand.argv))}.`);
|
|
44
67
|
}
|
|
45
68
|
instructions.push(result.quotaWarning
|
|
46
69
|
? buildQuotaAwareContinuation(result.quotaWarning, "After running the merge command.")
|
|
47
|
-
: "Then iterate immediately with the same options
|
|
70
|
+
: "Then iterate immediately with the same options until the PR merges or needs work.");
|
|
48
71
|
return instructions;
|
|
49
72
|
}
|
|
50
73
|
case "cancel":
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
];
|
|
74
|
+
// `[CANCEL]` needs no steps: stopping, then continuing the original request, is the skill's
|
|
75
|
+
// invariant recurrence rule, and nothing remains to run for this PR.
|
|
76
|
+
return [];
|
|
55
77
|
case "escalate": {
|
|
56
78
|
const pending = result.escalate.pendingReviewCommands;
|
|
57
79
|
if (!pending)
|
|
58
80
|
return ["Stop — human direction is required before automated polling can resume."];
|
|
59
81
|
return [
|
|
60
82
|
"Stop polling. Ask the user whether to run the pending review commands shown above.",
|
|
61
|
-
"If yes,
|
|
83
|
+
"If yes, set any `$DISMISS_MESSAGE` to a one-sentence disposition, run every pending command from the pushed PR head, then rerun Shepherd with the same options.",
|
|
62
84
|
];
|
|
63
85
|
}
|
|
64
86
|
}
|
|
@@ -67,18 +89,26 @@ export function buildSimpleIterateInstructions(result) {
|
|
|
67
89
|
* A held stack draft cannot advance by repeating its one-PR session, so hand control back
|
|
68
90
|
* to the stack selector instead of asking for another immediate iteration.
|
|
69
91
|
*/
|
|
70
|
-
function
|
|
92
|
+
function buildStackDraftHoldInstructions(result, hold) {
|
|
93
|
+
const event = result.pollMode === "event";
|
|
71
94
|
const stackCommand = buildPrShepherdCommand([
|
|
72
95
|
"--stack",
|
|
73
96
|
formatPrUrl(result.repo, result.pr),
|
|
74
97
|
"--until-terminal",
|
|
98
|
+
...(event ? ["--poll-mode", "event"] : []),
|
|
75
99
|
]).text;
|
|
76
100
|
const handoff = `a \`--stack\` selector listed this session, finish that selector's remaining steps and rerun it with its original flags; otherwise run ${inlineCode(stackCommand)}, adding \`--merge\` when merging was requested.`;
|
|
77
101
|
const reason = hold.kind === "auto-mark-ready-disabled" ? AUTO_MARK_READY_DISABLED_HOLD : hold.kind;
|
|
78
102
|
const instruction = `PR #${result.pr} stays in draft because ${reason}, so repeating this one-PR session cannot advance it. If ${handoff}`;
|
|
79
|
-
|
|
103
|
+
const step = result.quotaWarning
|
|
80
104
|
? buildQuotaAwareContinuation(result.quotaWarning, instruction)
|
|
81
105
|
: instruction;
|
|
106
|
+
if (!event)
|
|
107
|
+
return [step];
|
|
108
|
+
return [
|
|
109
|
+
step,
|
|
110
|
+
`Event mode: do not rerun this one-PR session and keep no wake-up for it. After the handoff, follow only the stack selector's output; it ends the turn and schedules the next tick through its own \`nextCheck\`. ${playbookPointer("Cloud event loop")}`,
|
|
111
|
+
];
|
|
82
112
|
}
|
|
83
113
|
export function adaptIterateLog(log) {
|
|
84
114
|
return log.replace(/\s+—\s+\d+s until auto-cancel/g, "");
|
package/bin/cli/iterate-lean.mjs
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { adaptIterateLog, buildSimpleIterateInstructions } from "./iterate-instructions.mjs";
|
|
2
2
|
import { projectRuleAutoResolve } from "../commands/rule-auto-resolve-format.mjs";
|
|
3
|
+
import { projectMergeRequirements } from "../merge-status/requirements-format.mjs";
|
|
4
|
+
import { branchSegmentShowsBase } from "./iterate-branch-segment.mjs";
|
|
5
|
+
import { isRedundantMergeQueue } from "./iterate-merge-formatter.mjs";
|
|
3
6
|
/**
|
|
4
7
|
* Project an IterateResult to a lean JSON shape for the default (non-verbose) output.
|
|
5
8
|
* Omits fields that are the trivial default (false, 0, empty) or state-gated fields
|
|
@@ -17,38 +20,56 @@ export function projectIterateLean(result, opts) {
|
|
|
17
20
|
const hasActivity = activity.commitCount > 0 ||
|
|
18
21
|
activity.reviewRoundCount > 0 ||
|
|
19
22
|
activity.reviewItemsSinceLatestCommit.length > 0;
|
|
23
|
+
if (result.action === "cancel" && (result.reason === "merged" || result.reason === "closed")) {
|
|
24
|
+
// Terminal: the PR's checks, reviews, and merge state no longer drive any action.
|
|
25
|
+
return {
|
|
26
|
+
action: result.action,
|
|
27
|
+
pr: result.pr,
|
|
28
|
+
reason: result.reason,
|
|
29
|
+
...(result.ruleAutoResolve && {
|
|
30
|
+
ruleAutoResolve: projectRuleAutoResolve(result.ruleAutoResolve),
|
|
31
|
+
}),
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
const counts = Object.fromEntries(["passing", "skipped", "filtered", "inProgress", "superseded"]
|
|
35
|
+
.filter((k) => result.summary[k] > 0)
|
|
36
|
+
.map((k) => [k, result.summary[k]]));
|
|
37
|
+
const summary = Object.keys(counts).length > 0 ? counts : null;
|
|
38
|
+
const mergeRequirements = result.mergeRequirements
|
|
39
|
+
? projectMergeRequirements(result.mergeRequirements)
|
|
40
|
+
: null;
|
|
20
41
|
const base = {
|
|
21
42
|
action: result.action,
|
|
22
43
|
pr: result.pr,
|
|
23
44
|
repo: result.repo || undefined,
|
|
45
|
+
...(result.transport && { transport: result.transport }),
|
|
46
|
+
...(result.transportUnavailable?.length && {
|
|
47
|
+
transportUnavailable: result.transportUnavailable,
|
|
48
|
+
}),
|
|
24
49
|
status: result.status,
|
|
25
|
-
|
|
26
|
-
|
|
50
|
+
// OPEN and CLEAN are the trivial defaults; the text header omits them the same way.
|
|
51
|
+
...(result.state !== "OPEN" && { state: result.state }),
|
|
52
|
+
...(result.mergeStateStatus !== "CLEAN" && { mergeStateStatus: result.mergeStateStatus }),
|
|
27
53
|
...(result.mergeStatus !== "CLEAN" && { mergeStatus: result.mergeStatus }), // mergeStateStatus alone can't always reconstruct this
|
|
28
54
|
...(readyDelaySuffix && { readyDelayOverride: readyDelaySuffix }),
|
|
29
55
|
...(result.mergeStatus === "BLOCKED" &&
|
|
30
56
|
result.reviewDecision !== null && { reviewDecision: result.reviewDecision }),
|
|
31
57
|
...(result.blockingBotReviewInProgress && { blockingBotReviewInProgress: true }),
|
|
32
58
|
...(result.isDraft && { isDraft: true }),
|
|
33
|
-
summary
|
|
34
|
-
passing: result.summary.passing,
|
|
35
|
-
...(result.summary.skipped > 0 && { skipped: result.summary.skipped }),
|
|
36
|
-
...(result.summary.filtered > 0 && { filtered: result.summary.filtered }),
|
|
37
|
-
...(result.summary.inProgress > 0 && { inProgress: result.summary.inProgress }),
|
|
38
|
-
...(result.summary.superseded > 0 && { superseded: result.summary.superseded }),
|
|
39
|
-
},
|
|
59
|
+
...(summary && { summary }),
|
|
40
60
|
...(result.status === "READY" &&
|
|
41
61
|
result.remainingSeconds > 0 && {
|
|
42
62
|
remainingSeconds: result.remainingSeconds,
|
|
43
63
|
}),
|
|
44
|
-
|
|
64
|
+
// Lean text shows the base branch only in the behind/conflicts branch segment.
|
|
65
|
+
...(branchSegmentShowsBase(result) && { baseBranch: result.baseBranch }),
|
|
45
66
|
...(result.stackTrunkConflict && { stackTrunkConflict: result.stackTrunkConflict }),
|
|
46
67
|
...((result.mergedBasePullRequests?.length ?? 0) > 0 && {
|
|
47
68
|
mergedBasePullRequests: result.mergedBasePullRequests,
|
|
48
69
|
}),
|
|
49
70
|
...(result.branchProtection !== null && { branchProtection: result.branchProtection }),
|
|
50
|
-
...(
|
|
51
|
-
...(result.mergeQueue && { mergeQueue: result.mergeQueue }),
|
|
71
|
+
...(mergeRequirements && { mergeRequirements }),
|
|
72
|
+
...(result.mergeQueue && !isRedundantMergeQueue(result) && { mergeQueue: result.mergeQueue }),
|
|
52
73
|
...(hasActivity && {
|
|
53
74
|
activity: {
|
|
54
75
|
commitCount: activity.commitCount,
|
|
@@ -78,6 +99,8 @@ export function projectIterateLean(result, opts) {
|
|
|
78
99
|
...(result.baseBehindBy !== undefined &&
|
|
79
100
|
result.baseBehindBy > 0 && { baseBehindBy: result.baseBehindBy }),
|
|
80
101
|
...(result.quotaWarning && { quotaWarning: result.quotaWarning }),
|
|
102
|
+
...(result.pollMode && { pollMode: result.pollMode }),
|
|
103
|
+
...(result.nextCheck && { nextCheck: result.nextCheck }),
|
|
81
104
|
...(result.ruleAutoResolve && {
|
|
82
105
|
ruleAutoResolve: projectRuleAutoResolve(result.ruleAutoResolve),
|
|
83
106
|
}),
|
|
@@ -92,7 +115,10 @@ export function projectIterateLean(result, opts) {
|
|
|
92
115
|
case "wait":
|
|
93
116
|
return {
|
|
94
117
|
...base,
|
|
95
|
-
|
|
118
|
+
// Zero counts are omitted, matching the text `**deferred (in merge queue)**` rollup.
|
|
119
|
+
...(result.deferredWork && {
|
|
120
|
+
deferredWork: Object.fromEntries(Object.entries(result.deferredWork).filter(([, n]) => n > 0)),
|
|
121
|
+
}),
|
|
96
122
|
...(result.stackDraftHold && { stackDraftHold: result.stackDraftHold }),
|
|
97
123
|
log: adaptIterateLog(result.log),
|
|
98
124
|
instructions: simpleInstructions(result),
|
|
@@ -102,7 +128,6 @@ export function projectIterateLean(result, opts) {
|
|
|
102
128
|
...base,
|
|
103
129
|
reason: result.reason,
|
|
104
130
|
log: adaptIterateLog(result.log),
|
|
105
|
-
instructions: simpleInstructions(result),
|
|
106
131
|
};
|
|
107
132
|
case "mark_ready":
|
|
108
133
|
// drop markedReady — always true, redundant with action discriminator
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import type { IterateDeferredWork, IterateResult, IterateResultMerge } from "../types.mts";
|
|
2
2
|
/** One inline rollup line of the non-CI work held back while the PR sits in the merge queue. */
|
|
3
3
|
export declare function formatDeferredWorkLine(dw: IterateDeferredWork): string;
|
|
4
|
+
/**
|
|
5
|
+
* True when `mergeQueue` adds nothing to the `Merge queue:` requirement line: it carries only
|
|
6
|
+
* `enabled`/`inQueue`, the queue is required (so enabled), and membership matches. Text and JSON
|
|
7
|
+
* both omit it then.
|
|
8
|
+
*/
|
|
9
|
+
export declare function isRedundantMergeQueue(result: IterateResult): boolean;
|
|
4
10
|
export declare function appendMergeQueueHeader(lines: string[], result: IterateResult): void;
|
|
5
11
|
export declare function formatMergeAction(header: string, result: IterateResultMerge): string;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { inlineCode, joinSections } from "../util/markdown.mjs";
|
|
1
|
+
import { joinSections } from "../util/markdown.mjs";
|
|
3
2
|
import { buildSimpleIterateInstructions, numberInstructions } from "./iterate-instructions.mjs";
|
|
4
3
|
/** One inline rollup line of the non-CI work held back while the PR sits in the merge queue. */
|
|
5
4
|
export function formatDeferredWorkLine(dw) {
|
|
@@ -16,9 +15,25 @@ export function formatDeferredWorkLine(dw) {
|
|
|
16
15
|
}
|
|
17
16
|
return `**deferred (in merge queue)** ${parts.join(", ")}`;
|
|
18
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* True when `mergeQueue` adds nothing to the `Merge queue:` requirement line: it carries only
|
|
20
|
+
* `enabled`/`inQueue`, the queue is required (so enabled), and membership matches. Text and JSON
|
|
21
|
+
* both omit it then.
|
|
22
|
+
*/
|
|
23
|
+
export function isRedundantMergeQueue(result) {
|
|
24
|
+
const queue = result.mergeQueue;
|
|
25
|
+
const req = result.mergeRequirements?.mergeQueue;
|
|
26
|
+
if (!queue || !req)
|
|
27
|
+
return false;
|
|
28
|
+
return (Object.keys(queue).every((k) => k === "enabled" || k === "inQueue") &&
|
|
29
|
+
queue.enabled &&
|
|
30
|
+
req.required &&
|
|
31
|
+
req.enabled === true &&
|
|
32
|
+
req.inQueue === queue.inQueue);
|
|
33
|
+
}
|
|
19
34
|
export function appendMergeQueueHeader(lines, result) {
|
|
20
35
|
const queue = result.mergeQueue;
|
|
21
|
-
if (!queue)
|
|
36
|
+
if (!queue || isRedundantMergeQueue(result))
|
|
22
37
|
return;
|
|
23
38
|
const parts = [`enabled \`${queue.enabled}\``, `inQueue \`${queue.inQueue}\``];
|
|
24
39
|
if (queue.entry) {
|
|
@@ -46,7 +61,12 @@ export function appendMergeQueueHeader(lines, result) {
|
|
|
46
61
|
parts.push("removal acknowledged");
|
|
47
62
|
lines.push(`**merge queue** ${parts.join(" · ")}`);
|
|
48
63
|
if (queue.autoMergeRequest) {
|
|
49
|
-
|
|
64
|
+
const autoMergeParts = [`method \`${queue.autoMergeRequest.mergeMethod}\``];
|
|
65
|
+
if (queue.autoMergeRequest.enabledAtUnix !== undefined)
|
|
66
|
+
autoMergeParts.push(`enabledAtUnix \`${queue.autoMergeRequest.enabledAtUnix}\``);
|
|
67
|
+
if (queue.autoMergeRequest.enabledBy)
|
|
68
|
+
autoMergeParts.push(`by \`@${queue.autoMergeRequest.enabledBy}\``);
|
|
69
|
+
lines.push(`**auto-merge** ${autoMergeParts.join(" · ")}`);
|
|
50
70
|
}
|
|
51
71
|
if (queue.latestRemoval) {
|
|
52
72
|
const removal = queue.latestRemoval;
|
|
@@ -54,18 +74,8 @@ export function appendMergeQueueHeader(lines, result) {
|
|
|
54
74
|
}
|
|
55
75
|
}
|
|
56
76
|
export function formatMergeAction(header, result) {
|
|
57
|
-
const commandLines = [
|
|
58
|
-
`- ${result.merge.mode === "queue" ? "merge queue" : "auto-merge"}: ${inlineCode(renderMergeCommand(result.merge.command))}`,
|
|
59
|
-
];
|
|
60
|
-
if (result.merge.fallbackCommand) {
|
|
61
|
-
commandLines.push(`- plain merge fallback: ${inlineCode(renderMergeCommand(result.merge.fallbackCommand))}`);
|
|
62
|
-
}
|
|
63
|
-
if (result.merge.queueApiFallbackCommand) {
|
|
64
|
-
commandLines.push(`- queue API fallback: ${inlineCode(renderMergeCommand(result.merge.queueApiFallbackCommand))}`);
|
|
65
|
-
}
|
|
66
77
|
return joinSections([
|
|
67
78
|
header,
|
|
68
|
-
`## Merge command\n\n${commandLines.join("\n")}`,
|
|
69
79
|
`## Instructions\n\n${numberInstructions(buildSimpleIterateInstructions(result))}`,
|
|
70
80
|
]);
|
|
71
81
|
}
|
|
@@ -5,10 +5,7 @@ export function projectIterateVerbose(result, opts) {
|
|
|
5
5
|
if (result.action === "fix_code")
|
|
6
6
|
return { ...result, ...readyDelayOverride };
|
|
7
7
|
const log = "log" in result && typeof result.log === "string" ? { log: adaptIterateLog(result.log) } : {};
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
...readyDelayOverride,
|
|
12
|
-
instructions: buildSimpleIterateInstructions(result),
|
|
13
|
-
};
|
|
8
|
+
// `cancel` has no instructions, so verbose JSON omits the field as verbose Markdown omits the section.
|
|
9
|
+
const instructions = result.action === "cancel" ? {} : { instructions: buildSimpleIterateInstructions(result) };
|
|
10
|
+
return { ...result, ...log, ...readyDelayOverride, ...instructions };
|
|
14
11
|
}
|
|
@@ -3,7 +3,9 @@ import { threadComments } from "../threads/transcript.mjs";
|
|
|
3
3
|
import { truncateBody, BODY_TRUNCATE_MAX_CHARS, NESTED_BODY_TRUNCATE_MAX_CHARS, } from "./body-truncate.mjs";
|
|
4
4
|
const BODY_PREVIEW_MAX = 100;
|
|
5
5
|
export function renderAuthor(author, authorType, authorAssociation, viewerDidAuthor) {
|
|
6
|
-
|
|
6
|
+
// `User` is the default author type; only `Bot` and `Unknown` are worth a label.
|
|
7
|
+
const type = authorType === "User" ? null : authorType;
|
|
8
|
+
return [`@${author}`, type, authorAssociation, viewerDidAuthor ? "viewer-authored" : null]
|
|
7
9
|
.filter(Boolean)
|
|
8
10
|
.join(" · ");
|
|
9
11
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
function pushIds(lines, label, ids) {
|
|
2
2
|
if (ids?.length)
|
|
3
|
-
lines.push(`${label}
|
|
3
|
+
lines.push(`${label}: ${ids.join(", ")}`);
|
|
4
4
|
}
|
|
5
5
|
function formatRateLimit(result) {
|
|
6
6
|
const rateLimit = result.rateLimit;
|
|
@@ -27,6 +27,8 @@ function formatRateLimit(result) {
|
|
|
27
27
|
}
|
|
28
28
|
export function formatMutateResult(result) {
|
|
29
29
|
const lines = [];
|
|
30
|
+
if (result.sessionRefusal)
|
|
31
|
+
lines.push(`Stopped: GitHub session access refused — ${result.sessionRefusal}`);
|
|
30
32
|
pushIds(lines, "Replied to threads", result.repliedThreads);
|
|
31
33
|
pushIds(lines, "Resolved threads", result.resolvedThreads);
|
|
32
34
|
pushIds(lines, "Minimized comments", result.minimizedComments);
|
|
@@ -43,14 +45,17 @@ export function formatMutateResult(result) {
|
|
|
43
45
|
const rateLimit = formatRateLimit(result);
|
|
44
46
|
if (rateLimit)
|
|
45
47
|
lines.push(rateLimit);
|
|
46
|
-
|
|
47
|
-
pushIds(lines,
|
|
48
|
-
pushIds(lines,
|
|
49
|
-
pushIds(lines,
|
|
48
|
+
const pendingReason = result.sessionRefusal ? "session access" : "rate limit";
|
|
49
|
+
pushIds(lines, `Not replied due to ${pendingReason}`, result.unrepliedThreads);
|
|
50
|
+
pushIds(lines, `Not resolved due to ${pendingReason}`, result.unresolvedThreads);
|
|
51
|
+
pushIds(lines, `Not minimized due to ${pendingReason}`, result.unminimizedComments);
|
|
52
|
+
pushIds(lines, `Not dismissed due to ${pendingReason}`, result.undismissedReviews);
|
|
50
53
|
const errors = result.rateLimit
|
|
51
54
|
? result.errors.filter((e) => !e.startsWith("rate limit:"))
|
|
52
55
|
: result.errors;
|
|
53
56
|
if (errors.length)
|
|
54
57
|
lines.push(`Errors:\n ${errors.join("\n ")}`);
|
|
58
|
+
if (result.instructions?.length)
|
|
59
|
+
lines.push(`## Instructions\n\n${result.instructions.map((instruction, index) => `${index + 1}. ${instruction}`).join("\n")}`);
|
|
55
60
|
return lines.join("\n");
|
|
56
61
|
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { NextCheck } from "../types/next-check.mts";
|
|
2
|
+
/** ` · **pollMode** \`event\``, or nothing in poll mode. */
|
|
3
|
+
export declare function formatPollModeSegment(result: {
|
|
4
|
+
pollMode?: "event";
|
|
5
|
+
}): string;
|
|
6
|
+
/** The header line naming the next wake-up, or nothing when none applies. */
|
|
7
|
+
export declare function formatNextCheckLines(next: NextCheck | undefined): string[];
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** ` · **pollMode** \`event\``, or nothing in poll mode. */
|
|
2
|
+
export function formatPollModeSegment(result) {
|
|
3
|
+
return result.pollMode ? ` · **pollMode** \`${result.pollMode}\`` : "";
|
|
4
|
+
}
|
|
5
|
+
/** The header line naming the next wake-up, or nothing when none applies. */
|
|
6
|
+
export function formatNextCheckLines(next) {
|
|
7
|
+
if (!next)
|
|
8
|
+
return [];
|
|
9
|
+
return [`**nextCheck** \`${next.at}\` · in ${next.inSeconds}s · reason \`${next.reason}\``];
|
|
10
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { EXIT, ShepherdError } from "../exit-codes.mjs";
|
|
2
|
+
import { formatPlaybookResult, runPlaybook } from "../commands/playbook.mjs";
|
|
3
|
+
import { maybePrintHelp } from "./help.mjs";
|
|
4
|
+
/**
|
|
5
|
+
* Print a playbook shipped in the package, or list the names. Local read only: no GitHub,
|
|
6
|
+
* git, or log I/O, so playbook pointers resolve without the skill installed.
|
|
7
|
+
*/
|
|
8
|
+
export function handlePlaybook(args) {
|
|
9
|
+
if (maybePrintHelp(args, "playbook"))
|
|
10
|
+
return;
|
|
11
|
+
let format = "text";
|
|
12
|
+
const words = [];
|
|
13
|
+
for (let index = 0; index < args.length; index++) {
|
|
14
|
+
const arg = args[index];
|
|
15
|
+
if (arg === "--format" || arg.startsWith("--format=")) {
|
|
16
|
+
const value = arg === "--format" ? args[++index] : arg.slice("--format=".length);
|
|
17
|
+
if (value !== "text" && value !== "json")
|
|
18
|
+
return usageError(`invalid --format ${value}`);
|
|
19
|
+
format = value;
|
|
20
|
+
}
|
|
21
|
+
else if (arg.startsWith("-")) {
|
|
22
|
+
return usageError(`unknown flag ${arg}`);
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
words.push(arg);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
try {
|
|
29
|
+
const result = runPlaybook(words.join(" "));
|
|
30
|
+
process.stdout.write(format === "json" ? `${JSON.stringify(result)}\n` : `${formatPlaybookResult(result)}\n`);
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
process.stderr.write(`pr-shepherd: playbook: ${String(error)}\n`);
|
|
34
|
+
process.exitCode = error instanceof ShepherdError ? error.exitCode : EXIT.USAGE;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function usageError(message) {
|
|
38
|
+
process.stderr.write(`pr-shepherd: playbook: ${message}\n`);
|
|
39
|
+
process.exitCode = EXIT.USAGE;
|
|
40
|
+
}
|
package/bin/cli/poll-handler.mjs
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { runAggregatePollForMode, runPollForMode } from "../commands/event-mode.mjs";
|
|
2
2
|
import { loadConfig } from "../config/load.mjs";
|
|
3
3
|
import { parseCommonArgs, getFlag, hasFlag } from "./args.mjs";
|
|
4
4
|
import { parseDurationToSeconds } from "./duration.mjs";
|
|
5
5
|
import { validateSecondsDurationFlag } from "./duration-flag.mjs";
|
|
6
|
-
import { parseIterateFlags } from "./iterate-flags.mjs";
|
|
6
|
+
import { hasInvalidIterateFlags, parseIterateFlags } from "./iterate-flags.mjs";
|
|
7
7
|
import { emitIterateResult } from "./iterate-emitter.mjs";
|
|
8
8
|
import { EXIT } from "../exit-codes.mjs";
|
|
9
|
-
import { runAggregatePoll } from "../commands/poll-summary.mjs";
|
|
10
9
|
import { emitPollSummaryResult } from "./poll-summary-emitter.mjs";
|
|
11
10
|
import { parsePollTargets, resolvePollTargets } from "./poll-targets.mjs";
|
|
12
11
|
export async function handlePoll(args) {
|
|
@@ -23,7 +22,7 @@ export async function handlePoll(args) {
|
|
|
23
22
|
const extra = isAggregate ? parsedTargets.extra : commonExtra;
|
|
24
23
|
const cfg = loadConfig();
|
|
25
24
|
const flags = parseIterateFlags(extra, cfg);
|
|
26
|
-
if (flags
|
|
25
|
+
if (hasInvalidIterateFlags(flags))
|
|
27
26
|
return;
|
|
28
27
|
const intervalStr = getFlag(extra, "--interval");
|
|
29
28
|
const intervalSuffix = validateSecondsDurationFlag("pr-shepherd", "--interval", intervalStr, hasFlag(extra, "--interval"));
|
|
@@ -61,6 +60,8 @@ export async function handlePoll(args) {
|
|
|
61
60
|
noAutoMarkReady: flags.noAutoMarkReady,
|
|
62
61
|
noAutoCancelActionable: flags.noAutoCancelActionable,
|
|
63
62
|
merge: flags.merge,
|
|
63
|
+
instructions: flags.instructions ?? undefined,
|
|
64
|
+
pollMode: flags.pollMode ?? undefined,
|
|
64
65
|
intervalSeconds,
|
|
65
66
|
timeoutSeconds,
|
|
66
67
|
debounceSeconds,
|
|
@@ -68,14 +69,14 @@ export async function handlePoll(args) {
|
|
|
68
69
|
untilTerminal: hasFlag(extra, "--until-terminal"),
|
|
69
70
|
};
|
|
70
71
|
if (isAggregate) {
|
|
71
|
-
const result = await
|
|
72
|
+
const result = await runAggregatePollForMode({
|
|
72
73
|
...shared,
|
|
73
74
|
...resolvedTargets,
|
|
74
75
|
});
|
|
75
76
|
emitPollSummaryResult(result, { format: globalOpts.format });
|
|
76
77
|
return;
|
|
77
78
|
}
|
|
78
|
-
const result = await
|
|
79
|
+
const result = await runPollForMode({ ...shared, prNumber });
|
|
79
80
|
emitIterateResult(result, {
|
|
80
81
|
format: globalOpts.format,
|
|
81
82
|
verbose: globalOpts.verbose ?? false,
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { formatApiUsage, formatQuotaWarning } from "./api-usage-formatter.mjs";
|
|
2
2
|
import { withPollSummaryInstructions } from "../commands/poll-summary-instructions.mjs";
|
|
3
3
|
import { formatStackOverview, projectStackOverview } from "./stack-overview.mjs";
|
|
4
|
+
import { formatTransportEvidence } from "./transport-formatter.mjs";
|
|
5
|
+
import { formatNextCheckLines, formatPollModeSegment } from "./next-check-format.mjs";
|
|
4
6
|
export function formatPollSummaryResult(result) {
|
|
5
7
|
if (result.selection.kind === "stack")
|
|
6
8
|
return formatStackOverview(projectStackOverview(result));
|
|
@@ -8,11 +10,13 @@ export function formatPollSummaryResult(result) {
|
|
|
8
10
|
const lines = [
|
|
9
11
|
`# Poll summary [${result.reason.toUpperCase()}]`,
|
|
10
12
|
"",
|
|
11
|
-
`**repo** \`${result.repo}\` · **selection** ${selection} · **mode** \`${result.mode}\`${result.stackMergeable !== undefined ? ` · **stack mergeable** \`${result.stackMergeable}\`` : ""}${result.nextAction ? ` · **next action** \`${result.nextAction}\`` : ""}`,
|
|
13
|
+
`**repo** \`${result.repo}\` · **selection** ${selection} · **mode** \`${result.mode}\`${formatPollModeSegment(result)}${result.stackMergeable !== undefined ? ` · **stack mergeable** \`${result.stackMergeable}\`` : ""}${result.nextAction ? ` · **next action** \`${result.nextAction}\`` : ""}`,
|
|
14
|
+
...formatNextCheckLines(result.nextCheck),
|
|
12
15
|
"",
|
|
13
16
|
"## Pull requests",
|
|
14
17
|
"",
|
|
15
18
|
...result.prs.map(formatItem),
|
|
19
|
+
...formatTransportEvidence(result),
|
|
16
20
|
];
|
|
17
21
|
if (result.stackAncestry?.length) {
|
|
18
22
|
lines.push("", "## Stack ancestry", "");
|
|
@@ -44,11 +48,14 @@ function formatItem(item) {
|
|
|
44
48
|
: "";
|
|
45
49
|
const readyDelay = item.remainingSeconds !== undefined ? ` · ready delay \`${item.remainingSeconds}s\`` : "";
|
|
46
50
|
const readyReceipt = item.readyReceipt ? " · Shepherd READY completion `verified`" : "";
|
|
51
|
+
const queuePolicy = item.requiresMergeQueue !== undefined
|
|
52
|
+
? ` · merge queue ${item.requiresMergeQueue ? "required" : "not required"}`
|
|
53
|
+
: "";
|
|
47
54
|
const checks = item.checks;
|
|
48
55
|
const review = item.review;
|
|
49
56
|
return [
|
|
50
57
|
`- [PR #${item.pr}: ${escapeMarkdownText(item.title)}](${item.url}) [${item.action.toUpperCase()}]`,
|
|
51
|
-
` - state \`${item.state}\` · mergeable \`${item.mergeable}\` · merge \`${item.mergeStateStatus}\`${reviewDecision}${stateFlags}${blockingReviewer}${readyDelay}${readyReceipt}${stack}`,
|
|
58
|
+
` - state \`${item.state}\` · mergeable \`${item.mergeable}\` · merge \`${item.mergeStateStatus}\`${reviewDecision}${stateFlags}${blockingReviewer}${readyDelay}${readyReceipt}${queuePolicy}${stack}`,
|
|
52
59
|
` - head \`${item.headRefName}\` at \`${item.headRefOid}\` · base \`${item.baseRefName}\``,
|
|
53
60
|
...(checks
|
|
54
61
|
? [` - checks: ${formatCounts(checks, checks.incomplete ? ", incomplete" : "")}`]
|
|
@@ -68,6 +75,8 @@ function formatItem(item) {
|
|
|
68
75
|
]
|
|
69
76
|
: []),
|
|
70
77
|
` - reasons: ${item.reasons.map((reason) => `\`${reason}\``).join(", ")}`,
|
|
78
|
+
...(item.transport ? [` - transport \`${item.transport}\``] : []),
|
|
79
|
+
...(item.transportUnavailable ?? []).map(({ field, reason }) => ` - unavailable \`${field}\`: ${reason}`),
|
|
71
80
|
...(item.pollCommand
|
|
72
81
|
? [` - pollCommand: \`${item.pollCommand}\`${item.pollProbe ? " · bounded probe" : ""}`]
|
|
73
82
|
: []),
|
package/bin/cli/poll-targets.mjs
CHANGED
|
@@ -15,11 +15,11 @@ export function warnPrrcThreadIds(ids) {
|
|
|
15
15
|
return prrcIds;
|
|
16
16
|
}
|
|
17
17
|
export function validateRequireSha(sha) {
|
|
18
|
-
if (sha === undefined)
|
|
18
|
+
if (sha === undefined || sha === "HEAD")
|
|
19
19
|
return true;
|
|
20
20
|
if (/^[0-9a-f]{40}$/.test(sha))
|
|
21
21
|
return true;
|
|
22
|
-
process.stderr.write(`pr-shepherd: apply review: --require-sha must be a full 40-character lowercase hex SHA, got "${sha}". Short SHAs will never match GitHub's headRefOid
|
|
22
|
+
process.stderr.write(`pr-shepherd: apply review: --require-sha must be HEAD or a full 40-character lowercase hex SHA, got "${sha}". Short SHAs will never match GitHub's headRefOid.\n`);
|
|
23
23
|
process.exitCode = EXIT.DATAERR;
|
|
24
24
|
return false;
|
|
25
25
|
}
|
package/bin/cli/runner.mjs
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import { loadConfig } from "../config/load.mjs";
|
|
2
|
+
import { getGithubTransport } from "../github/transport.mjs";
|
|
2
3
|
/** Every emitted pr-shepherd command starts with the configured `cliCommand` launcher. */
|
|
3
4
|
export function buildPrShepherdCommand(args) {
|
|
4
|
-
const
|
|
5
|
+
const transport = getGithubTransport() === "rest" &&
|
|
6
|
+
!args.some((arg) => arg === "--transport" || arg.startsWith("--transport="))
|
|
7
|
+
? ["--transport", "rest"]
|
|
8
|
+
: [];
|
|
9
|
+
const argv = [...loadConfig().cliCommand, ...args, ...transport];
|
|
5
10
|
return { argv, text: renderShellCommand(argv) };
|
|
6
11
|
}
|
|
7
12
|
export function renderShellCommand(argv) {
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { PollSummaryItem } from "../types.mts";
|
|
2
|
+
/** One lean stack row shared by Markdown, JSON, and MCP. */
|
|
3
|
+
export interface StackLayerView {
|
|
4
|
+
transport?: "rest";
|
|
5
|
+
transportUnavailable?: Array<{
|
|
6
|
+
field: string;
|
|
7
|
+
reason: string;
|
|
8
|
+
}>;
|
|
9
|
+
pr: number;
|
|
10
|
+
title: string;
|
|
11
|
+
url: string;
|
|
12
|
+
state: PollSummaryItem["state"];
|
|
13
|
+
shepherded?: true;
|
|
14
|
+
mergeable?: boolean;
|
|
15
|
+
blocker?: string;
|
|
16
|
+
author?: string;
|
|
17
|
+
owned?: true;
|
|
18
|
+
isDraft?: true;
|
|
19
|
+
isInMergeQueue?: true;
|
|
20
|
+
requiresMergeQueue?: boolean;
|
|
21
|
+
position?: number;
|
|
22
|
+
stackSize?: number;
|
|
23
|
+
baseRefName: string;
|
|
24
|
+
failing?: number;
|
|
25
|
+
inProgress?: number;
|
|
26
|
+
actionable?: number;
|
|
27
|
+
checksIncomplete?: true;
|
|
28
|
+
reviewIncomplete?: true;
|
|
29
|
+
queueRemoval?: {
|
|
30
|
+
reason: string | null;
|
|
31
|
+
actor?: string;
|
|
32
|
+
};
|
|
33
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|