pr-shepherd 0.56.6 → 0.57.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +150 -280
- package/bin/api.d.mts +25 -3
- package/bin/api.mjs +51 -13
- package/bin/checks/classify.d.mts +1 -0
- package/bin/checks/classify.mjs +1 -1
- package/bin/checks/conclusions.d.mts +5 -1
- package/bin/checks/conclusions.mjs +8 -2
- package/bin/checks/superseded.d.mts +8 -2
- package/bin/checks/superseded.mjs +24 -7
- package/bin/classify/loader.d.mts +2 -0
- package/bin/classify/loader.mjs +15 -0
- package/bin/classify/standard/author.d.mts +3 -0
- package/bin/classify/standard/author.mjs +10 -0
- package/bin/classify/standard/codecov-report.d.mts +4 -0
- package/bin/classify/standard/codecov-report.mjs +10 -0
- package/bin/classify/standard/coderabbit-notices.d.mts +8 -0
- package/bin/classify/standard/coderabbit-notices.mjs +38 -0
- package/bin/classify/standard/codex-notices.d.mts +8 -0
- package/bin/classify/standard/codex-notices.mjs +34 -0
- package/bin/classify/standard/dependabot-notices.d.mts +4 -0
- package/bin/classify/standard/dependabot-notices.mjs +15 -0
- package/bin/classify/standard/gemini-notices.d.mts +4 -0
- package/bin/classify/standard/gemini-notices.mjs +13 -0
- package/bin/classify/standard/index.d.mts +7 -0
- package/bin/classify/standard/index.mjs +21 -0
- package/bin/classify/standard/kilo-no-issues.d.mts +4 -0
- package/bin/classify/standard/kilo-no-issues.mjs +17 -0
- package/bin/classify/standard/sourcery-notices.d.mts +8 -0
- package/bin/classify/standard/sourcery-notices.mjs +20 -0
- package/bin/cli/api-usage-formatter.mjs +6 -1
- package/bin/cli/apply-merge-handler.d.mts +3 -0
- package/bin/cli/apply-merge-handler.mjs +73 -0
- package/bin/cli/arg-flags.d.mts +2 -0
- package/bin/cli/arg-flags.mjs +47 -0
- package/bin/cli/args.mjs +10 -41
- package/bin/cli/clean-handler.d.mts +1 -0
- package/bin/cli/clean-handler.mjs +71 -0
- package/bin/cli/default-poll.mjs +3 -0
- package/bin/cli/event-state-scope.d.mts +19 -0
- package/bin/cli/event-state-scope.mjs +60 -0
- package/bin/cli/fix-formatter.mjs +5 -11
- package/bin/cli/handlers.d.mts +0 -1
- package/bin/cli/handlers.mjs +8 -64
- package/bin/cli/help-command-pages.d.mts +62 -18
- package/bin/cli/help-command-pages.mjs +59 -15
- package/bin/cli/help-iterate-poll-pages.d.mts +2 -2
- package/bin/cli/help-iterate-poll-pages.mjs +6 -0
- package/bin/cli/help-log-file-page.d.mts +1 -1
- package/bin/cli/help-log-file-page.mjs +4 -1
- package/bin/cli/help-top-page.d.mts +1 -1
- package/bin/cli/help-top-page.mjs +5 -0
- package/bin/cli/help.d.mts +63 -19
- package/bin/cli/help.mjs +2 -0
- package/bin/cli/iterate-branch-segment.d.mts +2 -0
- package/bin/cli/iterate-branch-segment.mjs +12 -7
- package/bin/cli/iterate-flags.d.mts +7 -1
- package/bin/cli/iterate-flags.mjs +38 -0
- package/bin/cli/iterate-formatter.d.mts +6 -6
- package/bin/cli/iterate-formatter.mjs +56 -22
- package/bin/cli/iterate-instructions.mjs +45 -15
- package/bin/cli/iterate-lean.mjs +39 -14
- package/bin/cli/iterate-merge-formatter.d.mts +6 -0
- package/bin/cli/iterate-merge-formatter.mjs +24 -14
- package/bin/cli/iterate-verbose.mjs +3 -6
- package/bin/cli/list-formatters.mjs +3 -1
- package/bin/cli/mutate-formatter.mjs +10 -5
- package/bin/cli/next-check-format.d.mts +7 -0
- package/bin/cli/next-check-format.mjs +10 -0
- package/bin/cli/playbook-handler.d.mts +5 -0
- package/bin/cli/playbook-handler.mjs +40 -0
- package/bin/cli/poll-handler.mjs +7 -6
- package/bin/cli/poll-summary-formatter.mjs +11 -2
- package/bin/cli/poll-targets.mjs +2 -0
- package/bin/cli/resolve-validators.mjs +2 -2
- package/bin/cli/runner.mjs +6 -1
- package/bin/cli/stack-layer-view.d.mts +33 -0
- package/bin/cli/stack-layer-view.mjs +1 -0
- package/bin/cli/stack-overview.d.mts +10 -28
- package/bin/cli/stack-overview.mjs +39 -14
- package/bin/cli/transport-args.d.mts +5 -0
- package/bin/cli/transport-args.mjs +23 -0
- package/bin/cli/transport-formatter.d.mts +9 -0
- package/bin/cli/transport-formatter.mjs +13 -0
- package/bin/cli-parser.mjs +62 -7
- package/bin/commands/apply-merge-options.d.mts +4 -0
- package/bin/commands/apply-merge-options.mjs +34 -0
- package/bin/commands/apply-merge-output.d.mts +7 -0
- package/bin/commands/apply-merge-output.mjs +20 -0
- package/bin/commands/apply-merge-pull.d.mts +20 -0
- package/bin/commands/apply-merge-pull.mjs +15 -0
- package/bin/commands/apply-merge.d.mts +18 -0
- package/bin/commands/apply-merge.mjs +126 -0
- package/bin/commands/apply-queue-removal.mjs +7 -0
- package/bin/commands/check-annotations.mjs +28 -18
- package/bin/commands/check-execution-context.d.mts +5 -0
- package/bin/commands/check-execution-context.mjs +16 -1
- package/bin/commands/check-fingerprint.d.mts +26 -2
- package/bin/commands/check-fingerprint.mjs +64 -28
- package/bin/commands/check-terminal-report.mjs +11 -1
- package/bin/commands/check-unreported.d.mts +6 -2
- package/bin/commands/check-unreported.mjs +32 -12
- package/bin/commands/check-wait-detectors.d.mts +35 -0
- package/bin/commands/check-wait-detectors.mjs +107 -0
- package/bin/commands/check.d.mts +4 -2
- package/bin/commands/check.mjs +130 -40
- package/bin/commands/event-instructions.d.mts +11 -0
- package/bin/commands/event-instructions.mjs +27 -0
- package/bin/commands/event-mode.d.mts +14 -0
- package/bin/commands/event-mode.mjs +138 -0
- package/bin/commands/iterate/api-usage.mjs +4 -2
- package/bin/commands/iterate/base.mjs +4 -0
- package/bin/commands/iterate/check-blocker-gate.mjs +14 -2
- package/bin/commands/iterate/check-instructions.d.mts +9 -10
- package/bin/commands/iterate/check-instructions.mjs +23 -22
- package/bin/commands/iterate/classify.mjs +19 -5
- package/bin/commands/iterate/escalate.mjs +13 -3
- package/bin/commands/iterate/fix-code.mjs +26 -9
- package/bin/commands/iterate/fix-instruction-threads.d.mts +0 -8
- package/bin/commands/iterate/fix-instruction-threads.mjs +0 -16
- package/bin/commands/iterate/fix-loop-instruction.d.mts +9 -0
- package/bin/commands/iterate/fix-loop-instruction.mjs +35 -0
- package/bin/commands/iterate/helpers.mjs +15 -2
- package/bin/commands/iterate/index.mjs +57 -16
- package/bin/commands/iterate/mark-ready.mjs +50 -10
- package/bin/commands/iterate/merge-plan.d.mts +19 -0
- package/bin/commands/iterate/merge-plan.mjs +88 -0
- package/bin/commands/iterate/merge-state.mjs +3 -0
- package/bin/commands/iterate/merge.d.mts +4 -15
- package/bin/commands/iterate/merge.mjs +18 -51
- package/bin/commands/iterate/merged-base-pull-requests.d.mts +2 -6
- package/bin/commands/iterate/merged-base-pull-requests.mjs +15 -11
- package/bin/commands/iterate/native-stack-rebase.mjs +11 -0
- package/bin/commands/iterate/render.d.mts +8 -2
- package/bin/commands/iterate/render.mjs +28 -42
- package/bin/commands/iterate/stack-trunk-conflict.mjs +17 -1
- package/bin/commands/iterate/stale-ancestry.mjs +4 -1
- package/bin/commands/iterate/stall.d.mts +5 -1
- package/bin/commands/iterate/stall.mjs +19 -7
- package/bin/commands/iterate/thread-mutation-routing.d.mts +1 -0
- package/bin/commands/iterate/thread-mutation-routing.mjs +4 -2
- package/bin/commands/iterate/unreported-required.mjs +5 -2
- package/bin/commands/mark-files-as-viewed.mjs +7 -0
- package/bin/commands/next-check.d.mts +31 -0
- package/bin/commands/next-check.mjs +46 -0
- package/bin/commands/playbook.d.mts +13 -0
- package/bin/commands/playbook.mjs +48 -0
- package/bin/commands/poll-mode.d.mts +8 -0
- package/bin/commands/poll-mode.mjs +14 -0
- package/bin/commands/poll-progress.d.mts +1 -0
- package/bin/commands/poll-progress.mjs +6 -3
- package/bin/commands/poll-quota.d.mts +3 -2
- package/bin/commands/poll-quota.mjs +7 -3
- package/bin/commands/poll-summary-explicit-instructions.d.mts +2 -0
- package/bin/commands/poll-summary-explicit-instructions.mjs +10 -1
- package/bin/commands/poll-summary-instructions.mjs +16 -17
- package/bin/commands/poll-summary.mjs +42 -17
- package/bin/commands/poll.d.mts +0 -1
- package/bin/commands/poll.mjs +11 -19
- package/bin/commands/quota-selection.d.mts +2 -1
- package/bin/commands/quota-selection.mjs +12 -7
- package/bin/commands/resolve-mutate.mjs +33 -5
- package/bin/commands/rest-stack-merge-readiness.d.mts +4 -0
- package/bin/commands/rest-stack-merge-readiness.mjs +74 -0
- package/bin/commands/rule-auto-resolve.mjs +9 -3
- package/bin/commands/shepherd-journal.d.mts +5 -4
- package/bin/commands/shepherd-journal.mjs +9 -8
- package/bin/commands/stack-drain.d.mts +1 -9
- package/bin/commands/stack-drain.mjs +50 -37
- package/bin/commands/stack-handoffs.d.mts +10 -0
- package/bin/commands/stack-handoffs.mjs +25 -0
- package/bin/commands/stack-stall.d.mts +5 -0
- package/bin/commands/stack-stall.mjs +11 -0
- package/bin/commands/stack-work.d.mts +5 -0
- package/bin/commands/stack-work.mjs +32 -0
- package/bin/comments/existing-reply-scan.d.mts +17 -0
- package/bin/comments/existing-reply-scan.mjs +41 -0
- package/bin/comments/rate-limit.mjs +2 -2
- package/bin/comments/resolve.d.mts +7 -1
- package/bin/comments/resolve.mjs +108 -18
- package/bin/comments/rest-reply.d.mts +9 -0
- package/bin/comments/rest-reply.mjs +95 -0
- package/bin/comments/rest-review-mutations.d.mts +22 -0
- package/bin/comments/rest-review-mutations.mjs +125 -0
- package/bin/comments/review-visibility.d.mts +1 -1
- package/bin/comments/review-visibility.mjs +3 -2
- package/bin/comments/sha-poll.mjs +7 -3
- package/bin/comments/thread-visibility.mjs +10 -5
- package/bin/comments/uncertain-replies.d.mts +11 -0
- package/bin/comments/uncertain-replies.mjs +121 -0
- package/bin/comments/uncertain-reply-guards.d.mts +10 -0
- package/bin/comments/uncertain-reply-guards.mjs +94 -0
- package/bin/comments/visible-comments.d.mts +1 -1
- package/bin/comments/visible-comments.mjs +4 -2
- package/bin/config/load.d.mts +37 -1
- package/bin/config/load.mjs +73 -1
- package/bin/config.json +6 -2
- package/bin/exit-codes.d.mts +3 -0
- package/bin/exit-codes.mjs +8 -0
- package/bin/github/api-telemetry-aggregate.d.mts +15 -4
- package/bin/github/api-telemetry-aggregate.mjs +57 -18
- package/bin/github/api-telemetry.d.mts +4 -0
- package/bin/github/api-telemetry.mjs +22 -8
- package/bin/github/apply-review-preflight.d.mts +20 -0
- package/bin/github/apply-review-preflight.mjs +61 -0
- package/bin/github/base-behind-cache.d.mts +15 -0
- package/bin/github/base-behind-cache.mjs +18 -0
- package/bin/github/batch-parse-suites.d.mts +4 -2
- package/bin/github/batch-parse-suites.mjs +6 -1
- package/bin/github/batch-parser-helpers.mjs +40 -2
- package/bin/github/batch-parsers.mjs +1 -0
- package/bin/github/batch-raw-rules.d.mts +26 -0
- package/bin/github/batch-raw-types.d.mts +8 -6
- package/bin/github/batch-stack-evidence.d.mts +28 -0
- package/bin/github/batch-stack-evidence.mjs +62 -0
- package/bin/github/batch.d.mts +15 -2
- package/bin/github/batch.mjs +34 -17
- package/bin/github/captured-proxy-agent.d.mts +3 -0
- package/bin/github/captured-proxy-agent.mjs +8 -0
- package/bin/github/check-annotations-batch.d.mts +0 -5
- package/bin/github/check-annotations-batch.mjs +25 -4
- package/bin/github/check-annotations.mjs +3 -1
- package/bin/github/client.d.mts +8 -19
- package/bin/github/client.mjs +45 -13
- package/bin/github/fingerprint-fields.d.mts +8 -0
- package/bin/github/fingerprint-fields.mjs +6 -1
- package/bin/github/fingerprint.d.mts +4 -2
- package/bin/github/fingerprint.mjs +6 -38
- package/bin/github/github-fetch.d.mts +2 -0
- package/bin/github/github-fetch.mjs +32 -0
- package/bin/github/gql/base-behind.gql +3 -0
- package/bin/github/gql/batch-pr-page.gql +16 -0
- package/bin/github/gql/batch-pr.gql +57 -0
- package/bin/github/gql/commit-check-contexts.gql +17 -0
- package/bin/github/gql/get-pr-body.gql +1 -0
- package/bin/github/gql/poll-stack-summary.gql +1 -0
- package/bin/github/gql/poll-summary-check-contexts.gql +5 -0
- package/bin/github/gql/poll-summary-fragment.gql +65 -15
- package/bin/github/gql/stack-handoff-check-runs.gql +42 -0
- package/bin/github/graphql-http.mjs +9 -4
- package/bin/github/graphql-internal-retry.d.mts +2 -0
- package/bin/github/graphql-internal-retry.mjs +1 -1
- package/bin/github/graphql-quota-probe.d.mts +6 -0
- package/bin/github/graphql-quota-probe.mjs +56 -0
- package/bin/github/graphql-session-refusal.d.mts +8 -0
- package/bin/github/graphql-session-refusal.mjs +14 -0
- package/bin/github/http-request.d.mts +1 -1
- package/bin/github/http-request.mjs +22 -6
- package/bin/github/http-utils.mjs +6 -0
- package/bin/github/legacy-dispatcher.d.mts +6 -0
- package/bin/github/legacy-dispatcher.mjs +44 -0
- package/bin/github/merge-target-rules.d.mts +12 -3
- package/bin/github/merge-target-rules.mjs +71 -34
- package/bin/github/mutation-policy.d.mts +6 -0
- package/bin/github/mutation-policy.mjs +21 -0
- package/bin/github/poll-summary-annotation-probe.mjs +17 -10
- package/bin/github/poll-summary-check-blockers.d.mts +1 -1
- package/bin/github/poll-summary-check-blockers.mjs +2 -2
- package/bin/github/poll-summary-check-hydration.mjs +25 -10
- package/bin/github/poll-summary-checks.d.mts +2 -2
- package/bin/github/poll-summary-checks.mjs +9 -6
- package/bin/github/poll-summary-command.d.mts +2 -0
- package/bin/github/poll-summary-command.mjs +24 -0
- package/bin/github/poll-summary-fingerprint.d.mts +1 -1
- package/bin/github/poll-summary-fingerprint.mjs +4 -2
- package/bin/github/poll-summary-handoff-fields.d.mts +3 -0
- package/bin/github/poll-summary-handoff-fields.mjs +73 -0
- package/bin/github/poll-summary-projector.d.mts +1 -1
- package/bin/github/poll-summary-projector.mjs +17 -24
- package/bin/github/poll-summary-raw.d.mts +70 -10
- package/bin/github/poll-summary-readiness.d.mts +6 -1
- package/bin/github/poll-summary-readiness.mjs +13 -4
- package/bin/github/poll-summary-rest-queue.d.mts +3 -0
- package/bin/github/poll-summary-rest-queue.mjs +12 -0
- package/bin/github/poll-summary-review.d.mts +1 -1
- package/bin/github/poll-summary-review.mjs +35 -20
- package/bin/github/poll-summary-route.mjs +19 -3
- package/bin/github/poll-summary-stack-page.d.mts +11 -0
- package/bin/github/poll-summary-stack-page.mjs +27 -0
- package/bin/github/poll-summary-unreported.d.mts +3 -1
- package/bin/github/poll-summary-unreported.mjs +6 -3
- package/bin/github/poll-summary.d.mts +4 -1
- package/bin/github/poll-summary.mjs +47 -33
- package/bin/github/queries.d.mts +7 -3
- package/bin/github/queries.mjs +8 -4
- package/bin/github/rate-limit-sample.d.mts +7 -0
- package/bin/github/rate-limit-sample.mjs +12 -0
- package/bin/github/reply-recovery-read.d.mts +50 -0
- package/bin/github/reply-recovery-read.mjs +118 -0
- package/bin/github/reply-thread-transcripts.d.mts +0 -1
- package/bin/github/reply-thread-transcripts.mjs +24 -1
- package/bin/github/rest-annotation-read.d.mts +5 -0
- package/bin/github/rest-annotation-read.mjs +44 -0
- package/bin/github/rest-batch-read.d.mts +12 -0
- package/bin/github/rest-batch-read.mjs +57 -0
- package/bin/github/rest-batch-snapshot.d.mts +30 -0
- package/bin/github/rest-batch-snapshot.mjs +115 -0
- package/bin/github/rest-batch-unavailable.d.mts +5 -0
- package/bin/github/rest-batch-unavailable.mjs +16 -0
- package/bin/github/rest-check-read.d.mts +34 -0
- package/bin/github/rest-check-read.mjs +124 -0
- package/bin/github/rest-comment-authorship.d.mts +7 -0
- package/bin/github/rest-comment-authorship.mjs +11 -0
- package/bin/github/rest-conditional-scope.d.mts +20 -0
- package/bin/github/rest-conditional-scope.mjs +44 -0
- package/bin/github/rest-explicit-summary-read.d.mts +3 -0
- package/bin/github/rest-explicit-summary-read.mjs +8 -0
- package/bin/github/rest-feedback-read.d.mts +36 -0
- package/bin/github/rest-feedback-read.mjs +147 -0
- package/bin/github/rest-feedback-validation.d.mts +5 -0
- package/bin/github/rest-feedback-validation.mjs +28 -0
- package/bin/github/rest-http.d.mts +12 -0
- package/bin/github/rest-http.mjs +108 -23
- package/bin/github/rest-identities.d.mts +22 -0
- package/bin/github/rest-identities.mjs +134 -0
- package/bin/github/rest-merge-stack-guard.d.mts +14 -0
- package/bin/github/rest-merge-stack-guard.mjs +41 -0
- package/bin/github/rest-merge.d.mts +29 -0
- package/bin/github/rest-merge.mjs +56 -0
- package/bin/github/rest-merged-base-read.d.mts +9 -0
- package/bin/github/rest-merged-base-read.mjs +48 -0
- package/bin/github/rest-pr-core.d.mts +52 -0
- package/bin/github/rest-pr-core.mjs +60 -0
- package/bin/github/rest-reader-core.d.mts +16 -0
- package/bin/github/rest-reader-core.mjs +154 -0
- package/bin/github/rest-review-read.d.mts +11 -0
- package/bin/github/rest-review-read.mjs +47 -0
- package/bin/github/rest-rules-read.d.mts +9 -0
- package/bin/github/rest-rules-read.mjs +154 -0
- package/bin/github/rest-session-refusal.d.mts +5 -0
- package/bin/github/rest-session-refusal.mjs +21 -0
- package/bin/github/rest-snapshot-context.d.mts +10 -0
- package/bin/github/rest-snapshot-context.mjs +1 -0
- package/bin/github/rest-stack-read.d.mts +21 -0
- package/bin/github/rest-stack-read.mjs +47 -0
- package/bin/github/rest-stack-summary.d.mts +8 -0
- package/bin/github/rest-stack-summary.mjs +62 -0
- package/bin/github/rest-summary-read.d.mts +7 -0
- package/bin/github/rest-summary-read.mjs +112 -0
- package/bin/github/rest-terminal-batch.d.mts +14 -0
- package/bin/github/rest-terminal-batch.mjs +45 -0
- package/bin/github/rest-text.mjs +7 -3
- package/bin/github/rest-thread-read.d.mts +4 -0
- package/bin/github/rest-thread-read.mjs +35 -0
- package/bin/github/rest-viewer-read.d.mts +2 -0
- package/bin/github/rest-viewer-read.mjs +41 -0
- package/bin/github/stack-bottom.d.mts +3 -0
- package/bin/github/stack-bottom.mjs +14 -0
- package/bin/github/stack-handoff-context.d.mts +25 -0
- package/bin/github/stack-handoff-context.mjs +12 -0
- package/bin/github/stack-handoff-page.d.mts +17 -0
- package/bin/github/stack-handoff-page.mjs +306 -0
- package/bin/github/stack-handoff.d.mts +16 -0
- package/bin/github/stack-handoff.mjs +115 -0
- package/bin/github/stack-order.d.mts +6 -0
- package/bin/github/stack-order.mjs +13 -0
- package/bin/github/stack-read.d.mts +7 -5
- package/bin/github/stack-read.mjs +22 -24
- package/bin/github/stack-size-hint.d.mts +3 -0
- package/bin/github/stack-size-hint.mjs +14 -0
- package/bin/github/suggestion-thread.mjs +27 -1
- package/bin/github/thread-comments.mjs +9 -1
- package/bin/github/transport-evidence.d.mts +20 -0
- package/bin/github/transport-evidence.mjs +26 -0
- package/bin/github/transport-mode.d.mts +2 -0
- package/bin/github/transport-mode.mjs +5 -0
- package/bin/github/transport.d.mts +19 -0
- package/bin/github/transport.mjs +126 -0
- package/bin/github/unsupported-rest.d.mts +4 -0
- package/bin/github/unsupported-rest.mjs +7 -0
- package/bin/mcp/server.mjs +52 -3
- package/bin/merge-status/derive.d.mts +2 -0
- package/bin/merge-status/derive.mjs +17 -13
- package/bin/merge-status/required-check-requirements.d.mts +7 -0
- package/bin/merge-status/required-check-requirements.mjs +15 -0
- package/bin/merge-status/requirements-format.d.mts +5 -0
- package/bin/merge-status/requirements-format.mjs +41 -12
- package/bin/merge-status/requirements.mjs +18 -7
- package/bin/state/base.mjs +41 -0
- package/bin/state/durable-state.d.mts +6 -0
- package/bin/state/durable-state.mjs +41 -0
- package/bin/state/graphql-quota-policy.mjs +23 -16
- package/bin/state/merge-request.d.mts +25 -0
- package/bin/state/merge-request.mjs +145 -0
- package/bin/state/pr-fingerprint.d.mts +15 -0
- package/bin/state/pr-fingerprint.mjs +22 -7
- package/bin/state/rest-cache.d.mts +3 -0
- package/bin/state/rest-cache.mjs +1 -0
- package/bin/state/rest-snapshot-report.d.mts +21 -0
- package/bin/state/rest-snapshot-report.mjs +52 -0
- package/bin/state/seen-comments.d.mts +3 -0
- package/bin/state/seen-comments.mjs +18 -0
- package/bin/types/api-usage.d.mts +9 -1
- package/bin/types/escalate.d.mts +1 -1
- package/bin/types/github.d.mts +23 -9
- package/bin/types/iterate.d.mts +24 -2
- package/bin/types/merge-action.d.mts +1 -1
- package/bin/types/merge-requirements.d.mts +7 -7
- package/bin/types/next-check.d.mts +12 -0
- package/bin/types/next-check.mjs +1 -0
- package/bin/types/poll-summary.d.mts +21 -0
- package/bin/types/report.d.mts +13 -1
- package/bin/types/review-thread.d.mts +1 -1
- package/bin/types.d.mts +1 -0
- package/bin/types.mjs +1 -0
- package/package.json +4 -3
- package/plugins/pr-shepherd/.codex-plugin/plugin.json +1 -1
- package/plugins/pr-shepherd/.codex.mcp.json +1 -1
- package/plugins/pr-shepherd/.mcp.json +1 -1
- package/plugins/pr-shepherd/skills/mark-files-as-viewed/SKILL.md +1 -1
- package/plugins/pr-shepherd/skills/pr-shepherd/SKILL.md +14 -51
- package/plugins/pr-shepherd/skills/pr-shepherd/references/ci-failure-triage.md +12 -16
- package/plugins/pr-shepherd/skills/pr-shepherd/references/cloud-event-loop.md +14 -0
- package/plugins/pr-shepherd/skills/pr-shepherd/references/create-pr.md +10 -0
- package/plugins/pr-shepherd/skills/pr-shepherd/references/fix-code-loop.md +10 -0
- package/plugins/pr-shepherd/skills/pr-shepherd/references/mcp-fallback.md +9 -0
- package/plugins/pr-shepherd/skills/reduce-pr-noise/references/classifiers.md +3 -1
- package/bin/github/gql/pr-fingerprint.gql +0 -75
- package/plugins/pr-shepherd/skills/pr-shepherd/references/journal.md +0 -7
- package/plugins/pr-shepherd/skills/pr-shepherd/references/review-mutations.md +0 -9
- package/plugins/pr-shepherd/skills/pr-shepherd/references/stack-merge.md +0 -7
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { isBotItem } from "./author.mjs";
|
|
2
|
+
const STATUS_LINE = /^[^\S\n]*(?:\*\*)?Status:?(?:\*\*)?:?[^\S\n]*(?:\p{Extended_Pictographic}️?[^\S\n]*)?No Issues Found\b/imu;
|
|
3
|
+
/** Headings a no-issues report carries; any other heading means real feedback. */
|
|
4
|
+
const REPORT_HEADING = /^(?:Code Review Summary|Files Reviewed\b.*)$/i;
|
|
5
|
+
/** Kilo Code conversation comment whose status line reads "No Issues Found" and that carries no findings. */
|
|
6
|
+
const rule = (item) => {
|
|
7
|
+
if (!isBotItem(item, ["kilo-code-bot"], ["pr-comment"]))
|
|
8
|
+
return null;
|
|
9
|
+
if (!STATUS_LINE.test(item.body))
|
|
10
|
+
return null;
|
|
11
|
+
for (const [, heading] of item.body.matchAll(/^#{1,6}\s+(.*)$/gm)) {
|
|
12
|
+
if (!REPORT_HEADING.test(heading.trim()))
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
return { autoResolve: true, suppress: true, reason: "Kilo Code no-issues report" };
|
|
16
|
+
};
|
|
17
|
+
export default rule;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ClassifyRule } from "../types.mts";
|
|
2
|
+
/**
|
|
3
|
+
* Sourcery's private-repo upsell and weekly rate-limit notices on conversation comments. A real review opens
|
|
4
|
+
* with a Markdown heading ("Reviewer's Guide", "Summary by Sourcery"); the notices carry none,
|
|
5
|
+
* so a heading means genuine feedback that merely quotes the phrase.
|
|
6
|
+
*/
|
|
7
|
+
declare const rule: ClassifyRule;
|
|
8
|
+
export default rule;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { isBotItem } from "./author.mjs";
|
|
2
|
+
/**
|
|
3
|
+
* Sourcery's private-repo upsell and weekly rate-limit notices on conversation comments. A real review opens
|
|
4
|
+
* with a Markdown heading ("Reviewer's Guide", "Summary by Sourcery"); the notices carry none,
|
|
5
|
+
* so a heading means genuine feedback that merely quotes the phrase.
|
|
6
|
+
*/
|
|
7
|
+
const rule = (item) => {
|
|
8
|
+
if (!isBotItem(item, ["sourcery-ai"], ["pr-comment"]))
|
|
9
|
+
return null;
|
|
10
|
+
if (/^#{1,6}\s/m.test(item.body))
|
|
11
|
+
return null;
|
|
12
|
+
if (/does not have access to Sourcery/i.test(item.body)) {
|
|
13
|
+
return { autoResolve: true, suppress: true, reason: "Sourcery no-access upsell" };
|
|
14
|
+
}
|
|
15
|
+
if (/reached your weekly rate limit/i.test(item.body)) {
|
|
16
|
+
return { autoResolve: true, suppress: true, reason: "Sourcery rate-limit notice" };
|
|
17
|
+
}
|
|
18
|
+
return null;
|
|
19
|
+
};
|
|
20
|
+
export default rule;
|
|
@@ -3,7 +3,9 @@ function resetTime(resetAt) {
|
|
|
3
3
|
}
|
|
4
4
|
function formatResource(resource) {
|
|
5
5
|
const used = resource.used === undefined ? "" : ` · used ${resource.used}`;
|
|
6
|
-
|
|
6
|
+
const notModified = resource.notModified === undefined ? "" : ` · ${resource.notModified} not modified (304)`;
|
|
7
|
+
const requests = resource.requestCount === undefined ? "" : ` · ${resource.requestCount} requests`;
|
|
8
|
+
return `- \`${resource.resource}\`: ${resource.remaining}/${resource.limit} remaining${used}${requests}${notModified} · resets ${resetTime(resource.resetAt)}`;
|
|
7
9
|
}
|
|
8
10
|
export function formatQuotaWarning(warning) {
|
|
9
11
|
if (warning === undefined)
|
|
@@ -46,5 +48,8 @@ export function formatApiUsage(usage) {
|
|
|
46
48
|
}
|
|
47
49
|
for (const resource of usage.rest ?? [])
|
|
48
50
|
lines.push(formatResource(resource));
|
|
51
|
+
if (usage.unmeteredRestRequestCount !== undefined) {
|
|
52
|
+
lines.push(`- REST requests without rate-limit headers (unmetered): ${usage.unmeteredRestRequestCount}`);
|
|
53
|
+
}
|
|
49
54
|
return lines.join("\n");
|
|
50
55
|
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { EXIT, ShepherdError, errorToExitCode } from "../exit-codes.mjs";
|
|
2
|
+
import { runApplyMerge } from "../commands/apply-merge.mjs";
|
|
3
|
+
import { getFlag, parseCommonArgs } from "./args.mjs";
|
|
4
|
+
import { maybePrintHelp, USAGE } from "./help.mjs";
|
|
5
|
+
const flags = new Set(["--require-sha", "--merge-action", "--method", "--expected-stack"]);
|
|
6
|
+
export async function handleApplyMerge(args) {
|
|
7
|
+
if (maybePrintHelp(args, "apply merge"))
|
|
8
|
+
return;
|
|
9
|
+
try {
|
|
10
|
+
const { prNumber, global, extra } = parseCommonArgs(args);
|
|
11
|
+
for (let index = 0; index < extra.length; index += 1) {
|
|
12
|
+
const arg = extra[index];
|
|
13
|
+
const name = arg.split("=", 1)[0];
|
|
14
|
+
if (!flags.has(name))
|
|
15
|
+
throw new ShepherdError(`Unknown apply merge argument: ${arg}`, EXIT.USAGE);
|
|
16
|
+
if (!arg.includes("=")) {
|
|
17
|
+
if (!extra[index + 1] || extra[index + 1].startsWith("--"))
|
|
18
|
+
throw new ShepherdError(`${name} requires a value`, EXIT.USAGE);
|
|
19
|
+
index += 1;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
const requireSha = getFlag(extra, "--require-sha");
|
|
23
|
+
const mergeAction = getFlag(extra, "--merge-action");
|
|
24
|
+
if (requireSha === null || mergeAction === null) {
|
|
25
|
+
process.stderr.write(`${USAGE["apply merge"]}\n`);
|
|
26
|
+
process.exitCode = EXIT.USAGE;
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
const result = await runApplyMerge({
|
|
30
|
+
prNumber,
|
|
31
|
+
targetRepository: global.targetRepository,
|
|
32
|
+
requireSha,
|
|
33
|
+
mergeAction: mergeAction,
|
|
34
|
+
mergeMethod: (getFlag(extra, "--method") ?? undefined),
|
|
35
|
+
expectedStack: parseExpectedStack(getFlag(extra, "--expected-stack")),
|
|
36
|
+
});
|
|
37
|
+
process.stdout.write(`${global.format === "json" ? JSON.stringify(result, null, 2) : formatApplyMergeResult(result)}\n`);
|
|
38
|
+
process.exitCode =
|
|
39
|
+
result.status === "pending"
|
|
40
|
+
? EXIT.WAIT
|
|
41
|
+
: result.status === "failed"
|
|
42
|
+
? result.uncertain
|
|
43
|
+
? EXIT.TEMPFAIL
|
|
44
|
+
: EXIT.UNAVAILABLE
|
|
45
|
+
: EXIT.OK;
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
process.stderr.write(`pr-shepherd: apply merge: ${error instanceof Error ? error.message : String(error)}\n`);
|
|
49
|
+
process.exitCode = errorToExitCode(error);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
function parseExpectedStack(raw) {
|
|
53
|
+
if (raw === null)
|
|
54
|
+
return undefined;
|
|
55
|
+
try {
|
|
56
|
+
return JSON.parse(raw);
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
throw new ShepherdError("--expected-stack must be valid JSON", EXIT.DATAERR);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
export function formatApplyMergeResult(result) {
|
|
63
|
+
const lines = [`PR: ${result.repo}#${result.pr}`, `status: ${result.status}`];
|
|
64
|
+
if (result.uncertain)
|
|
65
|
+
lines.push("uncertain: true");
|
|
66
|
+
if (result.note)
|
|
67
|
+
lines.push(`note: ${result.note}`);
|
|
68
|
+
for (const [name, value] of Object.entries(result.details)) {
|
|
69
|
+
if (value !== undefined)
|
|
70
|
+
lines.push(`- ${name}: ${typeof value === "string" ? value : JSON.stringify(value)}`);
|
|
71
|
+
}
|
|
72
|
+
return lines.join("\n");
|
|
73
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// Flags that consume the next argument as their value (used for PR-number
|
|
2
|
+
// detection only — prevents a flag's value from being mistaken for a PR number).
|
|
3
|
+
export const FLAGS_WITH_VALUES = new Set([
|
|
4
|
+
"--transport",
|
|
5
|
+
"--merge-action",
|
|
6
|
+
"--method",
|
|
7
|
+
"--format",
|
|
8
|
+
"--ready-delay",
|
|
9
|
+
"--stall-timeout",
|
|
10
|
+
"--instructions",
|
|
11
|
+
"--poll-mode",
|
|
12
|
+
"--require-sha",
|
|
13
|
+
"--message",
|
|
14
|
+
"--description",
|
|
15
|
+
"--body-file",
|
|
16
|
+
"--file",
|
|
17
|
+
"--stack",
|
|
18
|
+
"--thread-id",
|
|
19
|
+
"--resolve-thread-ids",
|
|
20
|
+
"--reply-thread-ids",
|
|
21
|
+
"--minimize-comment-ids",
|
|
22
|
+
"--dismiss-review-ids",
|
|
23
|
+
"--interval",
|
|
24
|
+
"--timeout",
|
|
25
|
+
"--debounce",
|
|
26
|
+
"--match",
|
|
27
|
+
"--check",
|
|
28
|
+
"--blocked-by",
|
|
29
|
+
"--queue-commit",
|
|
30
|
+
"--removed-at",
|
|
31
|
+
]);
|
|
32
|
+
// Boolean flags that do NOT consume the next argument. Any --flag not in this
|
|
33
|
+
// set and not in FLAGS_WITH_VALUES is treated conservatively as value-taking
|
|
34
|
+
// for PR-number detection — so removed flags don't silently cause their
|
|
35
|
+
// numeric value to be misidentified as the PR number.
|
|
36
|
+
export const BOOLEAN_FLAGS = new Set([
|
|
37
|
+
"--no-auto-mark-ready",
|
|
38
|
+
"--no-auto-cancel-actionable",
|
|
39
|
+
"--quiet-status",
|
|
40
|
+
"--no-quiet-status",
|
|
41
|
+
"--until-terminal",
|
|
42
|
+
"--merge",
|
|
43
|
+
"--dry-run",
|
|
44
|
+
"--verbose",
|
|
45
|
+
"--clear",
|
|
46
|
+
"--adopt-existing-replies",
|
|
47
|
+
]);
|
package/bin/cli/args.mjs
CHANGED
|
@@ -3,45 +3,8 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { parseArgs } from "node:util";
|
|
5
5
|
import { parseCliPrReference, resolveParsedPrTarget } from "../pr-reference.mjs";
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const FLAGS_WITH_VALUES = new Set([
|
|
9
|
-
"--format",
|
|
10
|
-
"--ready-delay",
|
|
11
|
-
"--stall-timeout",
|
|
12
|
-
"--require-sha",
|
|
13
|
-
"--message",
|
|
14
|
-
"--description",
|
|
15
|
-
"--thread-id",
|
|
16
|
-
"--resolve-thread-ids",
|
|
17
|
-
"--reply-thread-ids",
|
|
18
|
-
"--minimize-comment-ids",
|
|
19
|
-
"--dismiss-review-ids",
|
|
20
|
-
"--interval",
|
|
21
|
-
"--timeout",
|
|
22
|
-
"--debounce",
|
|
23
|
-
"--match",
|
|
24
|
-
"--check",
|
|
25
|
-
"--blocked-by",
|
|
26
|
-
"--require-sha",
|
|
27
|
-
"--queue-commit",
|
|
28
|
-
"--removed-at",
|
|
29
|
-
]);
|
|
30
|
-
// Boolean flags that do NOT consume the next argument. Any --flag not in this
|
|
31
|
-
// set and not in FLAGS_WITH_VALUES is treated conservatively as value-taking
|
|
32
|
-
// for PR-number detection — so removed flags don't silently cause their
|
|
33
|
-
// numeric value to be misidentified as the PR number.
|
|
34
|
-
const BOOLEAN_FLAGS = new Set([
|
|
35
|
-
"--no-auto-mark-ready",
|
|
36
|
-
"--no-auto-cancel-actionable",
|
|
37
|
-
"--quiet-status",
|
|
38
|
-
"--no-quiet-status",
|
|
39
|
-
"--until-terminal",
|
|
40
|
-
"--merge",
|
|
41
|
-
"--dry-run",
|
|
42
|
-
"--verbose",
|
|
43
|
-
"--clear",
|
|
44
|
-
]);
|
|
6
|
+
import { parseGithubTransport } from "../github/transport-mode.mjs";
|
|
7
|
+
import { FLAGS_WITH_VALUES, BOOLEAN_FLAGS } from "./arg-flags.mjs";
|
|
45
8
|
// ---------------------------------------------------------------------------
|
|
46
9
|
// Strict integer parsing
|
|
47
10
|
// ---------------------------------------------------------------------------
|
|
@@ -58,7 +21,9 @@ export function parseCommonArgs(args) {
|
|
|
58
21
|
allowPositionals: true,
|
|
59
22
|
tokens: true,
|
|
60
23
|
options: {
|
|
24
|
+
...Object.fromEntries([...FLAGS_WITH_VALUES].map((flag) => [flag.slice(2), { type: "string" }])),
|
|
61
25
|
format: { type: "string" },
|
|
26
|
+
transport: { type: "string" },
|
|
62
27
|
verbose: { type: "boolean" },
|
|
63
28
|
},
|
|
64
29
|
});
|
|
@@ -68,11 +33,12 @@ export function parseCommonArgs(args) {
|
|
|
68
33
|
// them from `extra`. Subcommand-specific flags are left untouched.
|
|
69
34
|
const consumedIndices = new Set();
|
|
70
35
|
for (const tok of tokens ?? []) {
|
|
71
|
-
if (tok.kind === "option" &&
|
|
36
|
+
if (tok.kind === "option" &&
|
|
37
|
+
(tok.name === "format" || tok.name === "verbose" || tok.name === "transport")) {
|
|
72
38
|
consumedIndices.add(tok.index);
|
|
73
39
|
// When the value is a separate arg (--flag value, not --flag=value),
|
|
74
40
|
// inlineValue is false and the value occupies tok.index + 1.
|
|
75
|
-
if (tok.name === "format" &&
|
|
41
|
+
if ((tok.name === "format" || tok.name === "transport") &&
|
|
76
42
|
"inlineValue" in tok &&
|
|
77
43
|
tok.inlineValue === false &&
|
|
78
44
|
tok.value != null) {
|
|
@@ -122,6 +88,9 @@ export function parseCommonArgs(args) {
|
|
|
122
88
|
global: {
|
|
123
89
|
format,
|
|
124
90
|
verbose,
|
|
91
|
+
...(values.transport !== undefined
|
|
92
|
+
? { transport: parseGithubTransport(values.transport) }
|
|
93
|
+
: {}),
|
|
125
94
|
...(target.targetRepository !== undefined
|
|
126
95
|
? { targetRepository: target.targetRepository }
|
|
127
96
|
: undefined),
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function handleClean(args: string[], command?: "admin clean" | "clean"): Promise<void>;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { runClean } from "../commands/clean.mjs";
|
|
2
|
+
import { EXIT } from "../exit-codes.mjs";
|
|
3
|
+
import { USAGE } from "./help.mjs";
|
|
4
|
+
import { formatCleanResult } from "./formatters.mjs";
|
|
5
|
+
import { rejectInvalidPollModeFlag, runInPollModeScope } from "./event-state-scope.mjs";
|
|
6
|
+
const CLEAN_VARIANTS = new Set(["pr", "branch", "current", "repo", "all"]);
|
|
7
|
+
export async function handleClean(args, command = "admin clean") {
|
|
8
|
+
const usage = command === "admin clean" ? USAGE["admin clean"] : USAGE.clean;
|
|
9
|
+
const variant = args[0];
|
|
10
|
+
if (!variant || !CLEAN_VARIANTS.has(variant)) {
|
|
11
|
+
process.stderr.write(`${usage}\n`);
|
|
12
|
+
process.exitCode = EXIT.USAGE;
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
const rest = args.slice(1);
|
|
16
|
+
for (const a of rest) {
|
|
17
|
+
if (!a.startsWith("--"))
|
|
18
|
+
continue;
|
|
19
|
+
if (a === "--dry-run" || a === "--format" || a.startsWith("--format="))
|
|
20
|
+
continue;
|
|
21
|
+
if (a === "--poll-mode" || a.startsWith("--poll-mode="))
|
|
22
|
+
continue;
|
|
23
|
+
process.stderr.write(`pr-shepherd: ${command}: unknown flag: "${a}"\n`);
|
|
24
|
+
process.exitCode = EXIT.USAGE;
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
const fmtIdx = rest.indexOf("--format");
|
|
28
|
+
const fmtEqEntry = rest.find((a) => a.startsWith("--format="));
|
|
29
|
+
let formatValue;
|
|
30
|
+
if (fmtEqEntry !== undefined) {
|
|
31
|
+
formatValue = fmtEqEntry.slice("--format=".length);
|
|
32
|
+
}
|
|
33
|
+
else if (fmtIdx !== -1 && fmtIdx + 1 < rest.length && !rest[fmtIdx + 1].startsWith("--")) {
|
|
34
|
+
formatValue = rest[fmtIdx + 1];
|
|
35
|
+
}
|
|
36
|
+
if (formatValue !== undefined && formatValue !== "text" && formatValue !== "json") {
|
|
37
|
+
process.stderr.write(`pr-shepherd: ${command}: invalid --format value: "${formatValue}". Expected "text" or "json".\n`);
|
|
38
|
+
process.exitCode = EXIT.USAGE;
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
if (rejectInvalidPollModeFlag(rest, command))
|
|
42
|
+
return;
|
|
43
|
+
const jsonOut = formatValue === "json";
|
|
44
|
+
const dryRun = rest.includes("--dry-run");
|
|
45
|
+
// Skip values consumed by --format <value> / --poll-mode <value> so they aren't positionals.
|
|
46
|
+
const flagConsumedIndices = new Set();
|
|
47
|
+
if (fmtIdx !== -1 && fmtIdx + 1 < rest.length && !rest[fmtIdx + 1].startsWith("--")) {
|
|
48
|
+
flagConsumedIndices.add(fmtIdx);
|
|
49
|
+
flagConsumedIndices.add(fmtIdx + 1);
|
|
50
|
+
}
|
|
51
|
+
const pollModeIdx = rest.indexOf("--poll-mode");
|
|
52
|
+
if (pollModeIdx !== -1) {
|
|
53
|
+
flagConsumedIndices.add(pollModeIdx);
|
|
54
|
+
flagConsumedIndices.add(pollModeIdx + 1);
|
|
55
|
+
}
|
|
56
|
+
const positionals = rest.filter((a, i) => !flagConsumedIndices.has(i) && !a.startsWith("--"));
|
|
57
|
+
if (positionals.length > 1) {
|
|
58
|
+
process.stderr.write(`pr-shepherd: ${command}: too many positional arguments (expected at most 1, got ${positionals.length})\n`);
|
|
59
|
+
process.exitCode = EXIT.USAGE;
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
const value = positionals[0];
|
|
63
|
+
// Event mode keeps its state under the durable state base; clean must target that same scope.
|
|
64
|
+
const result = await runInPollModeScope(rest, () => runClean({ variant: variant, value, dryRun }));
|
|
65
|
+
if (!result.ok) {
|
|
66
|
+
process.stderr.write(`pr-shepherd: ${command}: ${result.error}\n`);
|
|
67
|
+
process.exitCode = EXIT.SOFTWARE;
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
process.stdout.write(jsonOut ? `${JSON.stringify(result, null, 2)}\n` : `${formatCleanResult(result)}\n`);
|
|
71
|
+
}
|
package/bin/cli/default-poll.mjs
CHANGED
|
@@ -3,9 +3,12 @@ import { parsePrNumber } from "./args.mjs";
|
|
|
3
3
|
import { validateDefaultArgs } from "./validate-default-args.mjs";
|
|
4
4
|
import { USAGE } from "./help.mjs";
|
|
5
5
|
const DEFAULT_POLL_FLAGS_WITH_VALUES = new Set([
|
|
6
|
+
"--transport",
|
|
6
7
|
"--format",
|
|
7
8
|
"--ready-delay",
|
|
8
9
|
"--stall-timeout",
|
|
10
|
+
"--instructions",
|
|
11
|
+
"--poll-mode",
|
|
9
12
|
"--interval",
|
|
10
13
|
"--timeout",
|
|
11
14
|
"--debounce",
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Run a dispatched command, entering the durable state scope first when it resolves to event
|
|
3
|
+
* mode. Entering before log setup keeps the per-worktree log a peer of the seen markers and
|
|
4
|
+
* stall state an event session writes. Invalid flags or config fall through unscoped so the
|
|
5
|
+
* command handler reports them.
|
|
6
|
+
*/
|
|
7
|
+
export declare function runInEventStateScope<T>(args: string[], work: () => Promise<T>): Promise<T>;
|
|
8
|
+
/**
|
|
9
|
+
* Report an invalid `--poll-mode` value as a usage error. Commands that only use the flag to
|
|
10
|
+
* pick a state scope (`log-file`, `clean`) call this before `runInPollModeScope`, because no
|
|
11
|
+
* later handler would reject a typo there. Returns true after printing the error.
|
|
12
|
+
*/
|
|
13
|
+
export declare function rejectInvalidPollModeFlag(args: string[], command: string): boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Run `work` in the durable state scope when `--poll-mode` in `args`, or else `poll.mode`,
|
|
16
|
+
* resolves to event mode. `log-file` and `clean` use this to reach the state an event tick
|
|
17
|
+
* writes.
|
|
18
|
+
*/
|
|
19
|
+
export declare function runInPollModeScope<T>(args: string[], work: () => Promise<T>): Promise<T>;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { loadConfig } from "../config/load.mjs";
|
|
2
|
+
import { EXIT } from "../exit-codes.mjs";
|
|
3
|
+
import { resolvePollMode } from "../commands/poll-mode.mjs";
|
|
4
|
+
import { runWithDurableState } from "../state/durable-state.mjs";
|
|
5
|
+
import { getFlag } from "./args.mjs";
|
|
6
|
+
import { isDefaultPollInvocation } from "./default-poll.mjs";
|
|
7
|
+
/** Subcommands that honor `--poll-mode`; the default poll invocation honors it too. */
|
|
8
|
+
const POLL_MODE_SUBCOMMANDS = new Set(["iterate", "poll"]);
|
|
9
|
+
const REQUESTABLE = ["auto", "poll", "event"];
|
|
10
|
+
function requestedPollMode(value) {
|
|
11
|
+
return REQUESTABLE.find((mode) => mode === value);
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Run a dispatched command, entering the durable state scope first when it resolves to event
|
|
15
|
+
* mode. Entering before log setup keeps the per-worktree log a peer of the seen markers and
|
|
16
|
+
* stall state an event session writes. Invalid flags or config fall through unscoped so the
|
|
17
|
+
* command handler reports them.
|
|
18
|
+
*/
|
|
19
|
+
export function runInEventStateScope(args, work) {
|
|
20
|
+
const subcommand = args[0];
|
|
21
|
+
const honorsPollMode = isDefaultPollInvocation(subcommand) || POLL_MODE_SUBCOMMANDS.has(subcommand ?? "");
|
|
22
|
+
return honorsPollMode ? runInPollModeScope(args, work) : work();
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Report an invalid `--poll-mode` value as a usage error. Commands that only use the flag to
|
|
26
|
+
* pick a state scope (`log-file`, `clean`) call this before `runInPollModeScope`, because no
|
|
27
|
+
* later handler would reject a typo there. Returns true after printing the error.
|
|
28
|
+
*/
|
|
29
|
+
export function rejectInvalidPollModeFlag(args, command) {
|
|
30
|
+
if (!args.some((arg) => arg === "--poll-mode" || arg.startsWith("--poll-mode=")))
|
|
31
|
+
return false;
|
|
32
|
+
const value = getFlag(args, "--poll-mode");
|
|
33
|
+
if (requestedPollMode(value))
|
|
34
|
+
return false;
|
|
35
|
+
process.stderr.write(`pr-shepherd: ${command}: --poll-mode must be one of ${REQUESTABLE.join(", ")}, got ${JSON.stringify(value ?? "")}\n`);
|
|
36
|
+
process.exitCode = EXIT.USAGE;
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Run `work` in the durable state scope when `--poll-mode` in `args`, or else `poll.mode`,
|
|
41
|
+
* resolves to event mode. `log-file` and `clean` use this to reach the state an event tick
|
|
42
|
+
* writes.
|
|
43
|
+
*/
|
|
44
|
+
export function runInPollModeScope(args, work) {
|
|
45
|
+
return resolvesToEvent(args) ? runWithDurableState(work) : work();
|
|
46
|
+
}
|
|
47
|
+
function resolvesToEvent(args) {
|
|
48
|
+
const flag = getFlag(args, "--poll-mode");
|
|
49
|
+
const requested = requestedPollMode(flag);
|
|
50
|
+
// An explicit poll or event request wins without reading config, so a malformed config
|
|
51
|
+
// cannot drop an explicit `--poll-mode event` out of the durable scope.
|
|
52
|
+
if (requested === "event" || requested === "poll")
|
|
53
|
+
return requested === "event";
|
|
54
|
+
try {
|
|
55
|
+
return resolvePollMode(requested, loadConfig().poll.mode) === "event";
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
/* eslint-disable max-lines */
|
|
2
|
-
import { renderResolveCommand } from "../commands/iterate/render.mjs";
|
|
3
2
|
import { inlineCode, joinSections } from "../util/markdown.mjs";
|
|
4
3
|
import { renderSuggestionBlock, renderLineRange } from "./suggestion-renderer.mjs";
|
|
5
4
|
import { renderThreadBullet, renderReviewBullet, renderThreadResolutionStatusTag, renderAuthor, buildFirstLookBullets, renderThreadConversation, blockquote, } from "./list-formatters.mjs";
|
|
@@ -77,9 +76,8 @@ export function formatFixCodeResult(header, result, opts = {}) {
|
|
|
77
76
|
const scopeTag = ch.scope
|
|
78
77
|
? ` [scope: ${ch.scope}${ch.commitOid ? `, commit: ${ch.commitOid}` : ""}]`
|
|
79
78
|
: "";
|
|
80
|
-
const rerunTag = ch.rerunCommand ? " [rerun authorized]" : "";
|
|
81
79
|
const lines = [
|
|
82
|
-
`- ${locator} — \`${workflowPrefix}${jobLabel}\`${conclusionTag}${attemptTag}${scopeTag}
|
|
80
|
+
`- ${locator} — \`${workflowPrefix}${jobLabel}\`${conclusionTag}${attemptTag}${scopeTag}`,
|
|
83
81
|
];
|
|
84
82
|
if (ch.conclusion !== "CANCELLED") {
|
|
85
83
|
if (ch.failedStep)
|
|
@@ -184,13 +182,8 @@ export function formatFixCodeResult(header, result, opts = {}) {
|
|
|
184
182
|
sections.push("## Cancelled runs");
|
|
185
183
|
sections.push(result.cancelled.map((id) => `- \`${id}\``).join("\n"));
|
|
186
184
|
}
|
|
187
|
-
|
|
188
|
-
const postFixLines = [`- base: \`${result.baseBranch}\``];
|
|
189
|
-
if (result.fix.resolveOnlyCommand?.hasMutations)
|
|
190
|
-
postFixLines.push(`- resolve-only: \`${renderResolveCommand(result.fix.resolveOnlyCommand)}\``);
|
|
191
|
-
if (result.fix.resolveCommand.hasMutations) {
|
|
192
|
-
postFixLines.push(`- apply review: \`${renderResolveCommand(result.fix.resolveCommand)}\``);
|
|
193
|
-
}
|
|
185
|
+
// The review mutation commands render inline in their `## Instructions` steps.
|
|
186
|
+
const postFixLines = verbose ? [`- base: \`${result.baseBranch}\``] : [];
|
|
194
187
|
if (result.fix.requeue) {
|
|
195
188
|
postFixLines.push(`- requeue: ${inlineCode(renderMergeCommand(result.fix.requeue.command))}`);
|
|
196
189
|
if (result.fix.requeue.queueApiFallbackCommand) {
|
|
@@ -200,7 +193,8 @@ export function formatFixCodeResult(header, result, opts = {}) {
|
|
|
200
193
|
if (result.fix.queueRemovalAcknowledgment) {
|
|
201
194
|
postFixLines.push(`- acknowledge queue removal: ${inlineCode(renderMergeCommand(result.fix.queueRemovalAcknowledgment))}`);
|
|
202
195
|
}
|
|
203
|
-
|
|
196
|
+
if (postFixLines.length > 0)
|
|
197
|
+
sections.push("## Post-fix actions", postFixLines.join("\n"));
|
|
204
198
|
sections.push("## Instructions");
|
|
205
199
|
sections.push(numberInstructions(result.fix.instructions));
|
|
206
200
|
return joinSections(sections);
|
package/bin/cli/handlers.d.mts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
export declare function handleClean(args: string[], command?: "admin clean" | "clean"): Promise<void>;
|
|
2
1
|
export declare function handleCommitSuggestion(args: string[], command?: "build-suggestion-patch" | "commit-suggestion"): Promise<void>;
|
|
3
2
|
export declare function handleSuggestionPatches(args: string[]): Promise<void>;
|
|
4
3
|
export declare function handleIterate(args: string[]): Promise<void>;
|
package/bin/cli/handlers.mjs
CHANGED
|
@@ -1,73 +1,16 @@
|
|
|
1
1
|
import { runCommitSuggestion } from "../commands/commit-suggestion.mjs";
|
|
2
2
|
import { runSuggestionPatches } from "../commands/suggestion-patches.mjs";
|
|
3
3
|
import { runMarkFilesAsViewed } from "../commands/mark-files-as-viewed.mjs";
|
|
4
|
-
import {
|
|
5
|
-
import { runClean } from "../commands/clean.mjs";
|
|
4
|
+
import { runIterateForMode } from "../commands/event-mode.mjs";
|
|
6
5
|
import { loadConfig } from "../config/load.mjs";
|
|
7
6
|
import { EXIT } from "../exit-codes.mjs";
|
|
8
7
|
import { parseCommonArgs, getFlag } from "./args.mjs";
|
|
9
8
|
import { USAGE } from "./help.mjs";
|
|
10
|
-
import { formatCommitSuggestionResult, formatSuggestionPatchesResult,
|
|
9
|
+
import { formatCommitSuggestionResult, formatSuggestionPatchesResult, formatMarkFilesAsViewedResult, } from "./formatters.mjs";
|
|
11
10
|
import { parseSuggestionPatchGroups } from "./suggestion-patch-flags.mjs";
|
|
12
|
-
import { parseIterateFlags } from "./iterate-flags.mjs";
|
|
11
|
+
import { hasInvalidIterateFlags, parseIterateFlags } from "./iterate-flags.mjs";
|
|
13
12
|
import { emitIterateResult } from "./iterate-emitter.mjs";
|
|
14
13
|
import { parseMarkFilesAsViewedArgs } from "./mark-files-as-viewed-flags.mjs";
|
|
15
|
-
const CLEAN_VARIANTS = new Set(["pr", "branch", "current", "repo", "all"]);
|
|
16
|
-
export async function handleClean(args, command = "admin clean") {
|
|
17
|
-
const usage = command === "admin clean" ? USAGE["admin clean"] : USAGE.clean;
|
|
18
|
-
const variant = args[0];
|
|
19
|
-
if (!variant || !CLEAN_VARIANTS.has(variant)) {
|
|
20
|
-
process.stderr.write(`${usage}\n`);
|
|
21
|
-
process.exitCode = EXIT.USAGE;
|
|
22
|
-
return;
|
|
23
|
-
}
|
|
24
|
-
const rest = args.slice(1);
|
|
25
|
-
for (const a of rest) {
|
|
26
|
-
if (!a.startsWith("--"))
|
|
27
|
-
continue;
|
|
28
|
-
if (a === "--dry-run" || a === "--format" || a.startsWith("--format="))
|
|
29
|
-
continue;
|
|
30
|
-
process.stderr.write(`pr-shepherd: ${command}: unknown flag: "${a}"\n`);
|
|
31
|
-
process.exitCode = EXIT.USAGE;
|
|
32
|
-
return;
|
|
33
|
-
}
|
|
34
|
-
const fmtIdx = rest.indexOf("--format");
|
|
35
|
-
const fmtEqEntry = rest.find((a) => a.startsWith("--format="));
|
|
36
|
-
let formatValue;
|
|
37
|
-
if (fmtEqEntry !== undefined) {
|
|
38
|
-
formatValue = fmtEqEntry.slice("--format=".length);
|
|
39
|
-
}
|
|
40
|
-
else if (fmtIdx !== -1 && fmtIdx + 1 < rest.length && !rest[fmtIdx + 1].startsWith("--")) {
|
|
41
|
-
formatValue = rest[fmtIdx + 1];
|
|
42
|
-
}
|
|
43
|
-
if (formatValue !== undefined && formatValue !== "text" && formatValue !== "json") {
|
|
44
|
-
process.stderr.write(`pr-shepherd: ${command}: invalid --format value: "${formatValue}". Expected "text" or "json".\n`);
|
|
45
|
-
process.exitCode = EXIT.USAGE;
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
|
-
const jsonOut = formatValue === "json";
|
|
49
|
-
const dryRun = rest.includes("--dry-run");
|
|
50
|
-
// Skip the value consumed by --format <value> so it isn't mistaken for the positional.
|
|
51
|
-
const flagConsumedIndices = new Set();
|
|
52
|
-
if (fmtIdx !== -1 && fmtIdx + 1 < rest.length && !rest[fmtIdx + 1].startsWith("--")) {
|
|
53
|
-
flagConsumedIndices.add(fmtIdx);
|
|
54
|
-
flagConsumedIndices.add(fmtIdx + 1);
|
|
55
|
-
}
|
|
56
|
-
const positionals = rest.filter((a, i) => !flagConsumedIndices.has(i) && !a.startsWith("--"));
|
|
57
|
-
if (positionals.length > 1) {
|
|
58
|
-
process.stderr.write(`pr-shepherd: ${command}: too many positional arguments (expected at most 1, got ${positionals.length})\n`);
|
|
59
|
-
process.exitCode = EXIT.USAGE;
|
|
60
|
-
return;
|
|
61
|
-
}
|
|
62
|
-
const value = positionals[0];
|
|
63
|
-
const result = await runClean({ variant: variant, value, dryRun });
|
|
64
|
-
if (!result.ok) {
|
|
65
|
-
process.stderr.write(`pr-shepherd: ${command}: ${result.error}\n`);
|
|
66
|
-
process.exitCode = EXIT.SOFTWARE;
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
69
|
-
process.stdout.write(jsonOut ? `${JSON.stringify(result, null, 2)}\n` : `${formatCleanResult(result)}\n`);
|
|
70
|
-
}
|
|
71
14
|
export async function handleCommitSuggestion(args, command = "build-suggestion-patch") {
|
|
72
15
|
const { prNumber, global: globalOpts, extra } = parseCommonArgs(args);
|
|
73
16
|
const threadId = getFlag(extra, "--thread-id");
|
|
@@ -113,11 +56,10 @@ export async function handleSuggestionPatches(args) {
|
|
|
113
56
|
}
|
|
114
57
|
export async function handleIterate(args) {
|
|
115
58
|
const { prNumber, global: globalOpts, extra } = parseCommonArgs(args);
|
|
116
|
-
const
|
|
117
|
-
|
|
118
|
-
if (flags.readyDelaySuffix === null || flags.stallTimeoutSuffix === null)
|
|
59
|
+
const flags = parseIterateFlags(extra, loadConfig());
|
|
60
|
+
if (hasInvalidIterateFlags(flags))
|
|
119
61
|
return;
|
|
120
|
-
const result = await
|
|
62
|
+
const result = await runIterateForMode({
|
|
121
63
|
...globalOpts,
|
|
122
64
|
prNumber,
|
|
123
65
|
readyDelaySeconds: flags.readyDelaySeconds,
|
|
@@ -125,6 +67,8 @@ export async function handleIterate(args) {
|
|
|
125
67
|
noAutoMarkReady: flags.noAutoMarkReady,
|
|
126
68
|
noAutoCancelActionable: flags.noAutoCancelActionable,
|
|
127
69
|
merge: flags.merge,
|
|
70
|
+
instructions: flags.instructions ?? undefined,
|
|
71
|
+
pollMode: flags.pollMode ?? undefined,
|
|
128
72
|
});
|
|
129
73
|
emitIterateResult(result, {
|
|
130
74
|
format: globalOpts.format,
|