pr-shepherd 0.41.0 → 0.43.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 +14 -9
- package/bin/api.d.mts +12 -1
- package/bin/api.mjs +34 -1
- package/bin/checks/classify.d.mts +3 -1
- package/bin/checks/classify.mjs +5 -2
- package/bin/cli/args.mjs +1 -0
- package/bin/cli/default-poll.mjs +1 -0
- package/bin/cli/fix-formatter.mjs +12 -2
- package/bin/cli/formatters.d.mts +2 -1
- package/bin/cli/formatters.mjs +33 -0
- package/bin/cli/handlers.d.mts +1 -0
- package/bin/cli/handlers.mjs +21 -1
- package/bin/cli/help-command-pages.d.mts +22 -6
- package/bin/cli/help-command-pages.mjs +20 -4
- package/bin/cli/help-iterate-poll-pages.d.mts +2 -2
- package/bin/cli/help-iterate-poll-pages.mjs +7 -2
- package/bin/cli/help-top-page.d.mts +1 -1
- package/bin/cli/help-top-page.mjs +3 -3
- package/bin/cli/help.d.mts +23 -7
- package/bin/cli/iterate-flags.d.mts +1 -0
- package/bin/cli/iterate-flags.mjs +2 -0
- package/bin/cli/iterate-formatter.mjs +4 -1
- package/bin/cli/iterate-instructions.mjs +15 -0
- package/bin/cli/iterate-lean.d.mts +1 -2
- package/bin/cli/iterate-lean.mjs +12 -17
- package/bin/cli/iterate-merge-formatter.d.mts +3 -0
- package/bin/cli/iterate-merge-formatter.mjs +52 -0
- package/bin/cli/iterate-verbose.d.mts +6 -0
- package/bin/cli/iterate-verbose.mjs +14 -0
- package/bin/cli/poll-handler.mjs +1 -0
- package/bin/cli/runner.mjs +4 -3
- package/bin/cli/suggestion-patch-flags.d.mts +11 -0
- package/bin/cli/suggestion-patch-flags.mjs +83 -0
- package/bin/cli-parser.mjs +6 -2
- package/bin/commands/check-terminal-report.mjs +1 -0
- package/bin/commands/check.mjs +42 -1
- package/bin/commands/commit-suggestion-instruction.d.mts +1 -1
- package/bin/commands/commit-suggestion-instruction.mjs +3 -3
- package/bin/commands/commit-suggestion.d.mts +1 -1
- package/bin/commands/commit-suggestion.mjs +19 -138
- package/bin/commands/iterate/base.d.mts +5 -0
- package/bin/commands/iterate/base.mjs +25 -0
- package/bin/commands/iterate/escalate.d.mts +3 -1
- package/bin/commands/iterate/escalate.mjs +18 -2
- package/bin/commands/iterate/fix-code.mjs +16 -0
- package/bin/commands/iterate/helpers.mjs +6 -2
- package/bin/commands/iterate/index.mjs +29 -35
- package/bin/commands/iterate/merge-state.d.mts +15 -0
- package/bin/commands/iterate/merge-state.mjs +53 -0
- package/bin/commands/iterate/merge.d.mts +13 -0
- package/bin/commands/iterate/merge.mjs +46 -0
- package/bin/commands/poll.mjs +3 -1
- package/bin/commands/suggestion-patch-git.d.mts +6 -0
- package/bin/commands/suggestion-patch-git.mjs +54 -0
- package/bin/commands/suggestion-patch-item.d.mts +15 -0
- package/bin/commands/suggestion-patch-item.mjs +106 -0
- package/bin/commands/suggestion-patches.d.mts +6 -0
- package/bin/commands/suggestion-patches.mjs +108 -0
- package/bin/config/load.d.mts +4 -0
- package/bin/config/load.mjs +34 -0
- package/bin/config/merge-command-args.d.mts +2 -0
- package/bin/config/merge-command-args.mjs +44 -0
- package/bin/config.json +3 -0
- package/bin/exit-codes.d.mts +2 -0
- package/bin/exit-codes.mjs +4 -0
- package/bin/github/batch-parse-checks.d.mts +3 -0
- package/bin/github/batch-parse-checks.mjs +29 -0
- package/bin/github/batch-parsers-rules.d.mts +3 -1
- package/bin/github/batch-parsers-rules.mjs +33 -0
- package/bin/github/batch-parsers.mjs +23 -26
- package/bin/github/batch-raw-rules.d.mts +48 -0
- package/bin/github/batch-raw-types.mjs +0 -1
- package/bin/github/batch.mjs +2 -0
- package/bin/github/gql/batch-pr.gql +92 -0
- package/bin/github/gql/commit-check-contexts.gql +58 -0
- package/bin/github/gql/{commit-suggestion-thread.gql → suggestion-threads.gql} +2 -2
- package/bin/github/merge-queue-checks.d.mts +4 -0
- package/bin/github/merge-queue-checks.mjs +48 -0
- package/bin/github/queries.d.mts +3 -1
- package/bin/github/queries.mjs +3 -1
- package/bin/github/suggestion-thread.d.mts +3 -3
- package/bin/github/suggestion-thread.mjs +8 -5
- package/bin/mcp/server.d.mts +1 -1
- package/bin/mcp/server.mjs +24 -3
- package/bin/reporters/agent.mjs +6 -3
- package/bin/types/activity.d.mts +2 -0
- package/bin/types/escalate.d.mts +30 -0
- package/bin/types/escalate.mjs +1 -0
- package/bin/types/github.d.mts +8 -0
- package/bin/types/github.mjs +0 -3
- package/bin/types/iterate.d.mts +14 -31
- package/bin/types/merge-action.d.mts +12 -0
- package/bin/types/merge-action.mjs +1 -0
- package/bin/types/merge-queue.d.mts +13 -0
- package/bin/types/merge-queue.mjs +1 -0
- package/bin/types/merge-requirements.d.mts +17 -0
- package/bin/types/report.d.mts +8 -19
- package/bin/types/suggestion-patch.d.mts +30 -0
- package/bin/types/suggestion-patch.mjs +1 -0
- package/bin/types.d.mts +4 -0
- package/bin/types.mjs +4 -0
- package/bin/util/markdown.d.mts +2 -0
- package/bin/util/markdown.mjs +7 -0
- package/package.json +1 -1
- 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/pr-shepherd/SKILL.md +11 -10
|
@@ -10,7 +10,7 @@ Usage:
|
|
|
10
10
|
pr-shepherd apply review [PR] [review-flags]
|
|
11
11
|
pr-shepherd apply files [PR] [files...] [--tests] [--match REGEX]
|
|
12
12
|
pr-shepherd apply journal [PR] <item> [--dry-run] [--format text|json]
|
|
13
|
-
pr-shepherd build-suggestion-
|
|
13
|
+
pr-shepherd build-suggestion-patches [PR] --thread-id ID --message MSG [groups...]
|
|
14
14
|
pr-shepherd admin clean <pr|branch|current|repo|all> [value] [flags]
|
|
15
15
|
pr-shepherd admin log-file [--format text|json]
|
|
16
16
|
|
|
@@ -20,8 +20,8 @@ Commands:
|
|
|
20
20
|
apply review Apply review-state mutations after fixes.
|
|
21
21
|
apply files Mark changed files as viewed in GitHub.
|
|
22
22
|
apply journal Append a list item to the Shepherd Journal details block of a PR body.
|
|
23
|
-
build-suggestion-
|
|
24
|
-
Convert
|
|
23
|
+
build-suggestion-patches
|
|
24
|
+
Convert ordered GitHub suggestion threads into patches and commit instructions.
|
|
25
25
|
admin clean Remove pr-shepherd state files.
|
|
26
26
|
admin log-file Print the per-worktree debug log path.
|
|
27
27
|
|
package/bin/cli/help.d.mts
CHANGED
|
@@ -61,11 +61,27 @@ PR may be a number or GitHub pull request URL. An item must start with '- ' foll
|
|
|
61
61
|
Use --file to read an item from a file, or --file - to read it from stdin. Exactly one item source
|
|
62
62
|
is required. --dry-run previews the resulting body without writing it.
|
|
63
63
|
--help, -h Print this help and exit before GitHub I/O.`;
|
|
64
|
-
readonly "build-suggestion-
|
|
64
|
+
readonly "build-suggestion-patches": `pr-shepherd build-suggestion-patches
|
|
65
65
|
|
|
66
|
-
Build
|
|
66
|
+
Build an ordered list of patches and commit instructions from GitHub review suggestions.
|
|
67
67
|
The command does not edit files or mutate git history.
|
|
68
68
|
|
|
69
|
+
Usage:
|
|
70
|
+
pr-shepherd build-suggestion-patches [PR]
|
|
71
|
+
--thread-id ID --message MSG [--description DESC]
|
|
72
|
+
[--thread-id ID --message MSG [--description DESC] ...]
|
|
73
|
+
[--format text|json]
|
|
74
|
+
|
|
75
|
+
Each --thread-id starts a suggestion group. Its following --message and optional --description
|
|
76
|
+
belong to that suggestion. Groups are validated and returned in command-line order.
|
|
77
|
+
|
|
78
|
+
The current branch must match the PR head ref. Local HEAD may equal or descend from the PR head;
|
|
79
|
+
every generated patch is dry-run in order with git apply --check before output.
|
|
80
|
+
--help, -h Print this help and exit before GitHub, git, config, or log I/O.`;
|
|
81
|
+
readonly "build-suggestion-patch": `pr-shepherd build-suggestion-patch
|
|
82
|
+
|
|
83
|
+
Deprecated one-suggestion adapter. Use build-suggestion-patches.
|
|
84
|
+
|
|
69
85
|
Usage:
|
|
70
86
|
pr-shepherd build-suggestion-patch [PR] --thread-id ID --message MSG
|
|
71
87
|
[--description DESC] [--format text|json]
|
|
@@ -76,7 +92,7 @@ Flags:
|
|
|
76
92
|
--description <text> Optional longer commit body.
|
|
77
93
|
--format text|json Output format. Default: text.
|
|
78
94
|
|
|
79
|
-
The current branch must match the PR head ref
|
|
95
|
+
The current branch must match the PR head ref. Local HEAD may equal or descend from the PR head.
|
|
80
96
|
--help, -h Print this help and exit before GitHub, git, config, or log I/O.`;
|
|
81
97
|
readonly admin: `pr-shepherd admin
|
|
82
98
|
|
|
@@ -149,7 +165,7 @@ Flags:
|
|
|
149
165
|
--help, -h Print this help and exit before GitHub, git, config, or log I/O.
|
|
150
166
|
|
|
151
167
|
Preconditions:
|
|
152
|
-
The current branch must match the PR head ref
|
|
168
|
+
The current branch must match the PR head ref. Local HEAD may equal or descend from the PR head.
|
|
153
169
|
|
|
154
170
|
Exit codes:
|
|
155
171
|
0 suggestion patch and instructions produced
|
|
@@ -176,8 +192,8 @@ Flags:
|
|
|
176
192
|
|
|
177
193
|
PR may be a number or GitHub pull request URL. When omitted, the current branch PR is inferred.
|
|
178
194
|
Exit code: 0 on success; nonzero on failure (sysexits.h — see docs/exit-codes.md).`;
|
|
179
|
-
readonly iterate: "pr-shepherd iterate\n\nRun one iterate tick for a pull request. The no-subcommand form polls; use this subcommand for a single tick.\nThe output contains one action and an action-specific ## Instructions section.\n\nUsage:\n pr-shepherd iterate [PR] [iterate-flags]\n\nIterate flags:\n --ready-delay <duration> Settle window before a clean PR cancels. Bare number = minutes. Example: 15m.\n --stall-timeout <duration> Escalate repeated unchanged failures after this duration. Bare number = minutes. 0 disables.\n --no-auto-mark-ready Do not convert draft PRs to ready for review.\n --no-auto-cancel-actionable Do not cancel in-progress runs before actionable fixes.\n --format text|json Output Markdown text or JSON. Default: text.\n --verbose Include verbose iterate fields.\n --help, -h Print this help and exit before GitHub, git, config, or log I/O.\n\nDurations accept s/m/h suffixes: 30s, 4.5m, 1h. A bare number is minutes; decimals are allowed only with an explicit unit (4.5m).\n\nActions:\n WAIT No immediate action; continue with the next poll.\n MARK_READY Draft PR was marked ready; continue with the next poll.\n FIX_CODE Agent action is required; follow the instructions, then continue polling.\n CANCEL Stop polling: merged/closed or ready-delay elapsed.\n ESCALATE Stop polling until a human provides direction.\n\nExit codes:\n 0 CANCEL (merged or ready-delay elapsed)\n 10 WAIT\n 11 MARK_READY\n 12 FIX_CODE\n 13 ESCALATE\n 14 CANCEL (closed without merging)\n A command/validation/GitHub failure exits with a sysexits.h code instead (see docs/exit-codes.md).";
|
|
180
|
-
readonly poll: "pr-shepherd poll\n\nRun iterate repeatedly for WAIT ticks and during the FIX_CODE debounce window. Print only the\nfinal tick to stdout.\nPoll exits as soon as iterate returns MARK_READY, CANCEL, or ESCALATE, or when timeout\nreturns the last WAIT result. FIX_CODE starts a --debounce settle window (default 1m): poll keeps\niterating at --interval, then runs one more tick after the window and returns that result.\nWith --until-terminal, poll also continues through MARK_READY.\n\nUsage:\n pr-shepherd poll [PR] [poll-flags] [iterate-flags]\n\nPoll flags:\n --interval <duration> Sleep between WAIT ticks. Bare number = seconds. Default: 60s.\n --timeout <duration> Maximum wall-clock wait for WAIT ticks. Bare number = seconds. Default: 4.5m.\n --debounce <duration> Settle window after first FIX_CODE before returning. Bare number = seconds. Default: 60s. 0 disables.\n --quiet-status During WAIT polling, print only changed status snapshots.\n --until-terminal Continue through WAIT/MARK_READY until FIX_CODE/CANCEL/ESCALATE.\n\nForwarded iterate flags:\n --ready-delay <duration> Settle window before a clean PR cancels. Bare number = minutes. Example: 15m.\n --stall-timeout <duration> Escalate repeated unchanged failures after this duration. Bare number = minutes. 0 disables.\n --no-auto-mark-ready Do not convert draft PRs to ready for review.\n --no-auto-cancel-actionable Do not cancel in-progress runs before actionable fixes.\n --format text|json Output Markdown text or JSON. Default: text.\n --verbose Include verbose iterate fields and detailed per-tick lines.\n --help, -h Print this help and exit before GitHub, git, config, or log I/O.\n\nDurations accept s/m/h suffixes: 30s, 4.5m, 1h. A bare number uses each flag's default unit (seconds\nfor --interval/--timeout/--debounce, minutes for --ready-delay/--stall-timeout); decimals are allowed only with\nan explicit unit (4.5m).\nEach WAIT tick writes an explicit still-running line to stderr by default; --quiet-status prints only changed WAIT snapshots, and --verbose emits detailed per-tick lines.\nFIX_CODE debounce writes a remaining-seconds line to stderr. --timeout does not cut an in-flight debounce short.\nWith --until-terminal, --timeout is ignored for WAIT ticks and polling continues until FIX_CODE, CANCEL, or ESCALATE.\n\nExit codes: same as iterate (the final tick's action/reason decides the code).\n 0 CANCEL (merged or ready-delay elapsed)\n 10 WAIT (including a WAIT returned by --timeout)\n 11 MARK_READY\n 12 FIX_CODE\n 13 ESCALATE\n 14 CANCEL (closed without merging)\n A command/validation/GitHub failure exits with a sysexits.h code instead (see docs/exit-codes.md).";
|
|
195
|
+
readonly iterate: "pr-shepherd iterate\n\nRun one iterate tick for a pull request. The no-subcommand form polls; use this subcommand for a single tick.\nThe output contains one action and an action-specific ## Instructions section.\n\nUsage:\n pr-shepherd iterate [PR] [iterate-flags]\n\nIterate flags:\n --ready-delay <duration> Settle window before a clean PR cancels. Bare number = minutes. Example: 15m.\n --stall-timeout <duration> Escalate repeated unchanged failures after this duration. Bare number = minutes. 0 disables.\n --no-auto-mark-ready Do not convert draft PRs to ready for review.\n --no-auto-cancel-actionable Do not cancel in-progress runs before actionable fixes.\n --merge Shepherd through readiness, then emit a merge or merge-queue command.\n --format text|json Output Markdown text or JSON. Default: text.\n --verbose Include verbose iterate fields.\n --help, -h Print this help and exit before GitHub, git, config, or log I/O.\n\nDurations accept s/m/h suffixes: 30s, 4.5m, 1h. A bare number is minutes; decimals are allowed only with an explicit unit (4.5m).\n\nActions:\n WAIT No immediate action; continue with the next poll.\n MARK_READY Draft PR was marked ready; continue with the next poll.\n FIX_CODE Agent action is required; follow the instructions, then continue polling.\n CANCEL Stop polling: merged/closed or ready-delay elapsed.\n ESCALATE Stop polling until a human provides direction.\n MERGE Run the emitted merge/queue command, then continue monitoring.\n\nExit codes:\n 0 CANCEL (merged or ready-delay elapsed)\n 10 WAIT\n 11 MARK_READY\n 12 FIX_CODE\n 13 ESCALATE\n 14 CANCEL (closed without merging)\n 15 MERGE\n A command/validation/GitHub failure exits with a sysexits.h code instead (see docs/exit-codes.md).";
|
|
196
|
+
readonly poll: "pr-shepherd poll\n\nRun iterate repeatedly for WAIT ticks and during the FIX_CODE debounce window. Print only the\nfinal tick to stdout.\nPoll exits as soon as iterate returns MARK_READY, CANCEL, or ESCALATE, or when timeout\nreturns the last WAIT result. FIX_CODE starts a --debounce settle window (default 1m): poll keeps\niterating at --interval, then runs one more tick after the window and returns that result.\nWith --until-terminal or --merge, poll also continues through MARK_READY.\n\nUsage:\n pr-shepherd poll [PR] [poll-flags] [iterate-flags]\n\nPoll flags:\n --interval <duration> Sleep between WAIT ticks. Bare number = seconds. Default: 60s.\n --timeout <duration> Maximum wall-clock wait for WAIT ticks. Bare number = seconds. Default: 4.5m.\n --debounce <duration> Settle window after first FIX_CODE before returning. Bare number = seconds. Default: 60s. 0 disables.\n --quiet-status During WAIT polling, print only changed status snapshots.\n --until-terminal Continue through WAIT/MARK_READY until FIX_CODE/CANCEL/ESCALATE.\n\nForwarded iterate flags:\n --ready-delay <duration> Settle window before a clean PR cancels. Bare number = minutes. Example: 15m.\n --stall-timeout <duration> Escalate repeated unchanged failures after this duration. Bare number = minutes. 0 disables.\n --no-auto-mark-ready Do not convert draft PRs to ready for review.\n --no-auto-cancel-actionable Do not cancel in-progress runs before actionable fixes.\n --merge Shepherd through readiness, then emit a merge or merge-queue command.\n --format text|json Output Markdown text or JSON. Default: text.\n --verbose Include verbose iterate fields and detailed per-tick lines.\n --help, -h Print this help and exit before GitHub, git, config, or log I/O.\n\nDurations accept s/m/h suffixes: 30s, 4.5m, 1h. A bare number uses each flag's default unit (seconds\nfor --interval/--timeout/--debounce, minutes for --ready-delay/--stall-timeout); decimals are allowed only with\nan explicit unit (4.5m).\nEach WAIT tick writes an explicit still-running line to stderr by default; --quiet-status prints only changed WAIT snapshots, and --verbose emits detailed per-tick lines.\nFIX_CODE debounce writes a remaining-seconds line to stderr. --timeout does not cut an in-flight debounce short.\nWith --until-terminal, --timeout is ignored for WAIT ticks and polling continues until FIX_CODE, MERGE, CANCEL, or ESCALATE. With --merge, --timeout still bounds WAIT ticks; it only continues through MARK_READY while polling remains within that timeout.\n\nExit codes: same as iterate (the final tick's action/reason decides the code).\n 0 CANCEL (merged or ready-delay elapsed)\n 10 WAIT (including a WAIT returned by --timeout)\n 11 MARK_READY\n 12 FIX_CODE\n 13 ESCALATE\n 14 CANCEL (closed without merging)\n 15 MERGE\n A command/validation/GitHub failure exits with a sysexits.h code instead (see docs/exit-codes.md).";
|
|
181
197
|
readonly clean: `pr-shepherd clean
|
|
182
198
|
|
|
183
199
|
Remove pr-shepherd state files from PR_SHEPHERD_STATE_DIR.
|
|
@@ -228,7 +244,7 @@ Flags:
|
|
|
228
244
|
|
|
229
245
|
Exit code: 0 on success (including no-change no-op); nonzero on failure (sysexits.h — see docs/exit-codes.md).`;
|
|
230
246
|
readonly "log-file": "pr-shepherd log-file\n\nPrint the per-worktree append-only debug log path for the current repository.\nThe log is created by the first non-help pr-shepherd command that initializes logging.\n\nUsage:\n pr-shepherd log-file [--format text|json]\n\nFlags:\n --format text|json Print a raw path or {\"path\": \"...\"} JSON. Default: text.\n --help, -h Print this help and exit before logging setup.\n\nEnvironment:\n PR_SHEPHERD_LOG_DISABLED=1 disables logging.\n PR_SHEPHERD_STATE_DIR overrides the base state directory.\n\nExit code: 0 on success; 1 if repository identity cannot be resolved.";
|
|
231
|
-
readonly top: "pr-shepherd\n\nAutonomous PR CI monitor and review-comment resolver for agentic coding tools.\n\nUsage:\n pr-shepherd --version | -v\n pr-shepherd --help | -h\n pr-shepherd [PR] [poll-flags] [iterate-flags]\n pr-shepherd iterate [PR] [iterate-flags]\n pr-shepherd apply review [PR] [review-flags]\n pr-shepherd apply files [PR] [files...] [--tests] [--match REGEX]\n pr-shepherd apply journal [PR] <item> [--dry-run] [--format text|json]\n pr-shepherd build-suggestion-
|
|
247
|
+
readonly top: "pr-shepherd\n\nAutonomous PR CI monitor and review-comment resolver for agentic coding tools.\n\nUsage:\n pr-shepherd --version | -v\n pr-shepherd --help | -h\n pr-shepherd [PR] [poll-flags] [iterate-flags]\n pr-shepherd iterate [PR] [iterate-flags]\n pr-shepherd apply review [PR] [review-flags]\n pr-shepherd apply files [PR] [files...] [--tests] [--match REGEX]\n pr-shepherd apply journal [PR] <item> [--dry-run] [--format text|json]\n pr-shepherd build-suggestion-patches [PR] --thread-id ID --message MSG [groups...]\n pr-shepherd admin clean <pr|branch|current|repo|all> [value] [flags]\n pr-shepherd admin log-file [--format text|json]\n\nCommands:\n [PR] Poll until non-WAIT or timeout. This is the default command.\n iterate Run one iterate tick (single-tick alias).\n apply review Apply review-state mutations after fixes.\n apply files Mark changed files as viewed in GitHub.\n apply journal Append a list item to the Shepherd Journal details block of a PR body.\n build-suggestion-patches\n Convert ordered GitHub suggestion threads into patches and commit instructions.\n admin clean Remove pr-shepherd state files.\n admin log-file Print the per-worktree debug log path.\n\nPR argument:\n PR may be a number such as 42 or a GitHub pull request URL.\n When omitted, pr-shepherd infers the current branch's pull request.\n\nCommon flags:\n --format text|json Output Markdown text or JSON. Default: text.\n --verbose Include verbose iterate fields and detailed poll-tick lines.\n --help, -h Print help and exit before any GitHub, git, config, or log I/O.\n\nIterate flags:\n --ready-delay <duration> Settle window before a clean PR cancels. Bare number = minutes. Example: 15m.\n --stall-timeout <duration> Escalate repeated unchanged failures after this duration. Bare number = minutes. 0 disables.\n --no-auto-mark-ready Do not convert draft PRs to ready for review.\n --no-auto-cancel-actionable Do not cancel in-progress runs before actionable fixes.\n\nPolling flags:\n --interval <duration> Delay between WAIT ticks. Bare number = seconds. Default: 60s.\n --timeout <duration> Poll wall-clock cap for WAIT ticks. Bare number = seconds. Default: 4.5m.\n --debounce <duration> Settle window after first FIX_CODE before returning. Bare number = seconds. Default: 60s. 0 disables.\n --quiet-status During WAIT polling, print only changed status snapshots.\n --until-terminal Continue through WAIT/MARK_READY until FIX_CODE/CANCEL/ESCALATE.\n\nClean variants:\n pr [number] Remove state for one PR. Defaults to current branch PR.\n branch [name] Remove state for a branch's PR. Defaults to current branch.\n current Alias for branch against the current branch.\n repo Remove all state for the current repository.\n all Remove all pr-shepherd state.\n\nExit codes: 0 done, 10-19 PR state, 64-78 shepherd failed (sysexits.h).\n 0 CANCEL (merged or ready-delay elapsed)\n 10 WAIT\n 11 MARK_READY\n 12 FIX_CODE\n 13 ESCALATE\n 14 CANCEL (closed without merging)\nSee docs/exit-codes.md for the full sysexits.h error-code table.\n\nDuration examples: 30s, 4.5m, 1h. A bare number uses each flag's default unit (see above); decimals are allowed with an explicit unit (4.5m).\n\nRun 'pr-shepherd <command> --help' for command-specific details.";
|
|
232
248
|
};
|
|
233
249
|
/** Resolve help keys for nested public commands before any command I/O. */
|
|
234
250
|
export declare function helpKeyForArgs(args: string[]): keyof typeof USAGE;
|
|
@@ -6,6 +6,7 @@ interface IterateFlags {
|
|
|
6
6
|
stallTimeoutSeconds: number;
|
|
7
7
|
noAutoMarkReady: boolean;
|
|
8
8
|
noAutoCancelActionable: boolean;
|
|
9
|
+
merge: boolean;
|
|
9
10
|
}
|
|
10
11
|
export declare function parseIterateFlags(extra: string[], cfg: ReturnType<typeof loadConfig>): IterateFlags;
|
|
11
12
|
export {};
|
|
@@ -10,6 +10,7 @@ export function parseIterateFlags(extra, cfg) {
|
|
|
10
10
|
const readyDelaySeconds = parseDurationToSeconds(readyDelaySuffix ?? "", cfg.watch.readyDelayMinutes * 60, MINUTE_FLAG_OPTS);
|
|
11
11
|
const noAutoMarkReady = hasFlag(extra, "--no-auto-mark-ready");
|
|
12
12
|
const noAutoCancelActionable = hasFlag(extra, "--no-auto-cancel-actionable");
|
|
13
|
+
const merge = hasFlag(extra, "--merge");
|
|
13
14
|
const stallTimeoutStr = getFlag(extra, "--stall-timeout");
|
|
14
15
|
const stallTimeoutSuffix = validateSecondsDurationFlag("pr-shepherd", "--stall-timeout", stallTimeoutStr, hasFlag(extra, "--stall-timeout"), MINUTE_FLAG_OPTS);
|
|
15
16
|
const stallTimeoutSeconds = parseDurationToSeconds(stallTimeoutSuffix ?? "", cfg.iterate.stallTimeoutMinutes * 60, MINUTE_FLAG_OPTS);
|
|
@@ -20,5 +21,6 @@ export function parseIterateFlags(extra, cfg) {
|
|
|
20
21
|
stallTimeoutSeconds,
|
|
21
22
|
noAutoMarkReady,
|
|
22
23
|
noAutoCancelActionable,
|
|
24
|
+
merge,
|
|
23
25
|
};
|
|
24
26
|
}
|
|
@@ -2,6 +2,7 @@ import { formatFixCodeResult } from "./fix-formatter.mjs";
|
|
|
2
2
|
import { joinSections } from "../util/markdown.mjs";
|
|
3
3
|
import { adaptIterateLog, buildSimpleIterateInstructions, numberInstructions, } from "./iterate-instructions.mjs";
|
|
4
4
|
import { formatMergeRequirementLines } from "../merge-status/requirements-format.mjs";
|
|
5
|
+
import { appendMergeQueueHeader, formatMergeAction } from "./iterate-merge-formatter.mjs";
|
|
5
6
|
function formatActivityLine(result) {
|
|
6
7
|
const activity = result.activity ?? {
|
|
7
8
|
commitCount: 0,
|
|
@@ -89,7 +90,6 @@ export function formatIterateResult(result, opts) {
|
|
|
89
90
|
}
|
|
90
91
|
// Surface an explicit `--ready-delay` override (set only when the user passed the flag)
|
|
91
92
|
// so the active settle window stays visible on every tick. Replaces the rerun command
|
|
92
|
-
// that previously carried the suffix in the (now removed) recheck instruction.
|
|
93
93
|
if (readyDelaySuffix) {
|
|
94
94
|
summaryLine += ` · **ready-delay** \`${readyDelaySuffix}\` (override)`;
|
|
95
95
|
}
|
|
@@ -127,6 +127,7 @@ export function formatIterateResult(result, opts) {
|
|
|
127
127
|
const names = result.supersededNames.map((n) => "`" + n + "`").join(", ");
|
|
128
128
|
headerLines.push(`**superseded** ${names}`);
|
|
129
129
|
}
|
|
130
|
+
appendMergeQueueHeader(headerLines, result);
|
|
130
131
|
const activityLine = formatActivityLine(result);
|
|
131
132
|
if (activityLine)
|
|
132
133
|
headerLines.push(activityLine);
|
|
@@ -144,6 +145,8 @@ export function formatIterateResult(result, opts) {
|
|
|
144
145
|
adaptIterateLog(result.log),
|
|
145
146
|
`## Instructions\n\n${numberInstructions(buildSimpleIterateInstructions(result))}`,
|
|
146
147
|
]);
|
|
148
|
+
case "merge":
|
|
149
|
+
return formatMergeAction(header, result);
|
|
147
150
|
case "cancel": {
|
|
148
151
|
const cancelHeaderLines = [`${heading} — ${result.reason}`, "", baseLine, summaryLine];
|
|
149
152
|
if (result.mergeRequirements) {
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { renderMergeCommand } from "../commands/iterate/merge.mjs";
|
|
2
|
+
import { inlineCode } from "../util/markdown.mjs";
|
|
1
3
|
export function buildSimpleIterateInstructions(result) {
|
|
2
4
|
switch (result.action) {
|
|
3
5
|
case "wait":
|
|
@@ -8,6 +10,19 @@ export function buildSimpleIterateInstructions(result) {
|
|
|
8
10
|
return [
|
|
9
11
|
"The CLI marked the PR ready for review. Iterate again with the same options to continue.",
|
|
10
12
|
];
|
|
13
|
+
case "merge": {
|
|
14
|
+
const instructions = [
|
|
15
|
+
`Run the \`${result.merge.mode === "queue" ? "merge queue" : "auto-merge"}\` command shown above exactly as printed.`,
|
|
16
|
+
];
|
|
17
|
+
if (result.merge.mode === "queue" && result.merge.queueApiFallbackCommand) {
|
|
18
|
+
instructions.push(`If the gh CLI says auto-merge is disabled instead of adding the PR to the queue, run the \`queue API fallback\` command: ${inlineCode(renderMergeCommand(result.merge.queueApiFallbackCommand))}.`);
|
|
19
|
+
}
|
|
20
|
+
else if (result.merge.fallbackCommand) {
|
|
21
|
+
instructions.push(`Only if GitHub reports that auto-merge is unavailable, run the \`plain merge fallback\` command: ${inlineCode(renderMergeCommand(result.merge.fallbackCommand))}.`);
|
|
22
|
+
}
|
|
23
|
+
instructions.push("Then iterate again with the same options to monitor until the PR merges or needs work.");
|
|
24
|
+
return instructions;
|
|
25
|
+
}
|
|
11
26
|
case "cancel":
|
|
12
27
|
return ["Stop — the PR loop is complete. No further polling is needed."];
|
|
13
28
|
case "escalate":
|
|
@@ -8,5 +8,4 @@ interface IterateProjectionOptions {
|
|
|
8
8
|
* outside the state where they are meaningful.
|
|
9
9
|
*/
|
|
10
10
|
export declare function projectIterateLean(result: IterateResult, opts?: IterateProjectionOptions): unknown;
|
|
11
|
-
export
|
|
12
|
-
export {};
|
|
11
|
+
export { projectIterateVerbose } from "./iterate-verbose.mts";
|
package/bin/cli/iterate-lean.mjs
CHANGED
|
@@ -42,6 +42,7 @@ export function projectIterateLean(result, opts) {
|
|
|
42
42
|
...(result.baseBranch && { baseBranch: result.baseBranch }),
|
|
43
43
|
...(result.branchProtection !== null && { branchProtection: result.branchProtection }),
|
|
44
44
|
...(result.mergeRequirements && { mergeRequirements: result.mergeRequirements }),
|
|
45
|
+
...(result.mergeQueue && { mergeQueue: result.mergeQueue }),
|
|
45
46
|
...(hasActivity && {
|
|
46
47
|
activity: {
|
|
47
48
|
commitCount: activity.commitCount,
|
|
@@ -85,6 +86,12 @@ export function projectIterateLean(result, opts) {
|
|
|
85
86
|
log: adaptIterateLog(result.log),
|
|
86
87
|
instructions: simpleInstructions(result),
|
|
87
88
|
};
|
|
89
|
+
case "merge":
|
|
90
|
+
return {
|
|
91
|
+
...base,
|
|
92
|
+
merge: result.merge,
|
|
93
|
+
instructions: simpleInstructions(result),
|
|
94
|
+
};
|
|
88
95
|
case "fix_code":
|
|
89
96
|
return {
|
|
90
97
|
...base,
|
|
@@ -122,6 +129,7 @@ export function projectIterateLean(result, opts) {
|
|
|
122
129
|
...(result.fix.protectedRuns.length > 0 && {
|
|
123
130
|
protectedRuns: result.fix.protectedRuns,
|
|
124
131
|
}),
|
|
132
|
+
...(result.fix.requeue && { requeue: result.fix.requeue }),
|
|
125
133
|
...(result.fix.checks.length > 0 && { checks: result.fix.checks }),
|
|
126
134
|
...(result.fix.changesRequestedReviews.length > 0 && {
|
|
127
135
|
changesRequestedReviews: result.fix.changesRequestedReviews,
|
|
@@ -157,6 +165,9 @@ export function projectIterateLean(result, opts) {
|
|
|
157
165
|
result.escalate.thrashHistory.length > 0 && {
|
|
158
166
|
thrashHistory: result.escalate.thrashHistory,
|
|
159
167
|
}),
|
|
168
|
+
...(result.escalate.mergeQueueRemoval && {
|
|
169
|
+
mergeQueueRemoval: result.escalate.mergeQueueRemoval,
|
|
170
|
+
}),
|
|
160
171
|
suggestion: result.escalate.suggestion,
|
|
161
172
|
humanMessage: result.escalate.humanMessage,
|
|
162
173
|
},
|
|
@@ -164,20 +175,4 @@ export function projectIterateLean(result, opts) {
|
|
|
164
175
|
};
|
|
165
176
|
}
|
|
166
177
|
}
|
|
167
|
-
export
|
|
168
|
-
const readyDelaySuffix = opts?.readyDelaySuffix;
|
|
169
|
-
const readyDelayOverride = readyDelaySuffix ? { readyDelayOverride: readyDelaySuffix } : {};
|
|
170
|
-
if (result.action === "fix_code") {
|
|
171
|
-
return {
|
|
172
|
-
...result,
|
|
173
|
-
...readyDelayOverride,
|
|
174
|
-
};
|
|
175
|
-
}
|
|
176
|
-
const log = "log" in result && typeof result.log === "string" ? { log: adaptIterateLog(result.log) } : {};
|
|
177
|
-
return {
|
|
178
|
-
...result,
|
|
179
|
-
...log,
|
|
180
|
-
...readyDelayOverride,
|
|
181
|
-
instructions: buildSimpleIterateInstructions(result),
|
|
182
|
-
};
|
|
183
|
-
}
|
|
178
|
+
export { projectIterateVerbose } from "./iterate-verbose.mjs";
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { renderMergeCommand } from "../commands/iterate/merge.mjs";
|
|
2
|
+
import { inlineCode, joinSections } from "../util/markdown.mjs";
|
|
3
|
+
import { buildSimpleIterateInstructions, numberInstructions } from "./iterate-instructions.mjs";
|
|
4
|
+
export function appendMergeQueueHeader(lines, result) {
|
|
5
|
+
const queue = result.mergeQueue;
|
|
6
|
+
if (!queue)
|
|
7
|
+
return;
|
|
8
|
+
const parts = [`enabled \`${queue.enabled}\``, `inQueue \`${queue.inQueue}\``];
|
|
9
|
+
if (queue.entry) {
|
|
10
|
+
parts.push(`state \`${queue.entry.state}\``, `position \`${queue.entry.position}\``);
|
|
11
|
+
if (queue.entry.estimatedTimeToMerge !== null) {
|
|
12
|
+
parts.push(`estimatedTimeToMerge \`${queue.entry.estimatedTimeToMerge}\``);
|
|
13
|
+
}
|
|
14
|
+
if (queue.entry.enqueuedAtUnix !== undefined) {
|
|
15
|
+
parts.push(`enqueuedAtUnix \`${queue.entry.enqueuedAtUnix}\``);
|
|
16
|
+
}
|
|
17
|
+
if (queue.entry.enqueuer)
|
|
18
|
+
parts.push(`enqueuer \`@${queue.entry.enqueuer}\``);
|
|
19
|
+
if (queue.entry.headCommitOid)
|
|
20
|
+
parts.push(`headCommit \`${queue.entry.headCommitOid}\``);
|
|
21
|
+
}
|
|
22
|
+
if (queue.checkCommitOid)
|
|
23
|
+
parts.push(`checkCommit \`${queue.checkCommitOid}\``);
|
|
24
|
+
if (queue.checksIncomplete)
|
|
25
|
+
parts.push("checks incomplete (first 100 shown)");
|
|
26
|
+
if (queue.headUpdatedAfterRemoval)
|
|
27
|
+
parts.push("head updated after removal");
|
|
28
|
+
lines.push(`**merge queue** ${parts.join(" · ")}`);
|
|
29
|
+
if (queue.autoMergeRequest) {
|
|
30
|
+
lines.push(`**auto-merge** method \`${queue.autoMergeRequest.mergeMethod}\` · enabledAtUnix \`${queue.autoMergeRequest.enabledAtUnix}\`${queue.autoMergeRequest.enabledBy ? ` · by \`@${queue.autoMergeRequest.enabledBy}\`` : ""}`);
|
|
31
|
+
}
|
|
32
|
+
if (queue.latestRemoval) {
|
|
33
|
+
const removal = queue.latestRemoval;
|
|
34
|
+
lines.push(`**queue removal** reason \`${removal.reason ?? "not provided"}\` · createdAtUnix \`${removal.createdAtUnix}\`${removal.actor ? ` · actor \`@${removal.actor}\`` : ""}${removal.beforeCommitOid ? ` · commit \`${removal.beforeCommitOid}\`` : ""}${removal.beforeCommitParentOids ? ` · parents \`${removal.beforeCommitParentOids.join(",")}\`` : ""}`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
export function formatMergeAction(header, result) {
|
|
38
|
+
const commandLines = [
|
|
39
|
+
`- ${result.merge.mode === "queue" ? "merge queue" : "auto-merge"}: ${inlineCode(renderMergeCommand(result.merge.command))}`,
|
|
40
|
+
];
|
|
41
|
+
if (result.merge.fallbackCommand) {
|
|
42
|
+
commandLines.push(`- plain merge fallback: ${inlineCode(renderMergeCommand(result.merge.fallbackCommand))}`);
|
|
43
|
+
}
|
|
44
|
+
if (result.merge.queueApiFallbackCommand) {
|
|
45
|
+
commandLines.push(`- queue API fallback: ${inlineCode(renderMergeCommand(result.merge.queueApiFallbackCommand))}`);
|
|
46
|
+
}
|
|
47
|
+
return joinSections([
|
|
48
|
+
header,
|
|
49
|
+
`## Merge command\n\n${commandLines.join("\n")}`,
|
|
50
|
+
`## Instructions\n\n${numberInstructions(buildSimpleIterateInstructions(result))}`,
|
|
51
|
+
]);
|
|
52
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { adaptIterateLog, buildSimpleIterateInstructions } from "./iterate-instructions.mjs";
|
|
2
|
+
export function projectIterateVerbose(result, opts) {
|
|
3
|
+
const readyDelaySuffix = opts?.readyDelaySuffix;
|
|
4
|
+
const readyDelayOverride = readyDelaySuffix ? { readyDelayOverride: readyDelaySuffix } : {};
|
|
5
|
+
if (result.action === "fix_code")
|
|
6
|
+
return { ...result, ...readyDelayOverride };
|
|
7
|
+
const log = "log" in result && typeof result.log === "string" ? { log: adaptIterateLog(result.log) } : {};
|
|
8
|
+
return {
|
|
9
|
+
...result,
|
|
10
|
+
...log,
|
|
11
|
+
...readyDelayOverride,
|
|
12
|
+
instructions: buildSimpleIterateInstructions(result),
|
|
13
|
+
};
|
|
14
|
+
}
|
package/bin/cli/poll-handler.mjs
CHANGED
|
@@ -36,6 +36,7 @@ export async function handlePoll(args) {
|
|
|
36
36
|
stallTimeoutSeconds: flags.stallTimeoutSeconds,
|
|
37
37
|
noAutoMarkReady: flags.noAutoMarkReady,
|
|
38
38
|
noAutoCancelActionable: flags.noAutoCancelActionable,
|
|
39
|
+
merge: flags.merge,
|
|
39
40
|
intervalSeconds,
|
|
40
41
|
timeoutSeconds,
|
|
41
42
|
debounceSeconds,
|
package/bin/cli/runner.mjs
CHANGED
|
@@ -8,11 +8,12 @@ export function renderShellCommand(argv) {
|
|
|
8
8
|
function renderShellArg(arg) {
|
|
9
9
|
if (/^\$[A-Z_][A-Z0-9_]*$/.test(arg))
|
|
10
10
|
return `"${arg}"`;
|
|
11
|
+
const assignment = /^([A-Za-z_][A-Za-z0-9_]*)=(\$[A-Z_][A-Z0-9_]*)$/.exec(arg);
|
|
12
|
+
if (assignment)
|
|
13
|
+
return `${assignment[1]}="${assignment[2]}"`;
|
|
11
14
|
if (/^[A-Za-z0-9_./:@%+=,-]+$/.test(arg))
|
|
12
15
|
return arg;
|
|
13
16
|
if (!/["$`\\]/.test(arg))
|
|
14
17
|
return `"${arg}"`;
|
|
15
|
-
|
|
16
|
-
return `'${arg}'`;
|
|
17
|
-
throw new Error(`Unexpected character in shell arg: ${JSON.stringify(arg)}`);
|
|
18
|
+
return `'${arg.replaceAll("'", `'"'"'`)}'`;
|
|
18
19
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { SuggestionPatchRequest } from "../commands/suggestion-patch-item.mts";
|
|
2
|
+
type ParseFailure = {
|
|
3
|
+
ok: false;
|
|
4
|
+
error: string;
|
|
5
|
+
};
|
|
6
|
+
type ParseResult = {
|
|
7
|
+
ok: true;
|
|
8
|
+
suggestions: SuggestionPatchRequest[];
|
|
9
|
+
} | ParseFailure;
|
|
10
|
+
export declare function parseSuggestionPatchGroups(args: readonly string[]): ParseResult;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
export function parseSuggestionPatchGroups(args) {
|
|
2
|
+
const parsed = parseFlags(args);
|
|
3
|
+
if (!parsed.ok)
|
|
4
|
+
return parsed;
|
|
5
|
+
return groupFlags(parsed.flags);
|
|
6
|
+
}
|
|
7
|
+
function parseFlags(args) {
|
|
8
|
+
const flags = [];
|
|
9
|
+
for (let index = 0; index < args.length;) {
|
|
10
|
+
const parsed = parseFlag(args, index);
|
|
11
|
+
if (!parsed)
|
|
12
|
+
return { ok: false, error: `Unknown argument: ${args[index]}` };
|
|
13
|
+
flags.push(parsed);
|
|
14
|
+
index += parsed.consumed;
|
|
15
|
+
}
|
|
16
|
+
return { ok: true, flags };
|
|
17
|
+
}
|
|
18
|
+
function groupFlags(flags) {
|
|
19
|
+
const suggestions = [];
|
|
20
|
+
let current = null;
|
|
21
|
+
for (const flag of flags) {
|
|
22
|
+
if (flag.name === "--thread-id") {
|
|
23
|
+
const finalized = finalize(current);
|
|
24
|
+
if (!finalized.ok)
|
|
25
|
+
return finalized;
|
|
26
|
+
if (finalized.suggestion)
|
|
27
|
+
suggestions.push(finalized.suggestion);
|
|
28
|
+
current = { threadId: flag.value };
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
const updated = setMetadata(current, flag);
|
|
32
|
+
if (!updated.ok)
|
|
33
|
+
return updated;
|
|
34
|
+
current = updated.current;
|
|
35
|
+
}
|
|
36
|
+
const finalized = finalize(current);
|
|
37
|
+
if (!finalized.ok)
|
|
38
|
+
return finalized;
|
|
39
|
+
if (finalized.suggestion)
|
|
40
|
+
suggestions.push(finalized.suggestion);
|
|
41
|
+
if (suggestions.length === 0)
|
|
42
|
+
return { ok: false, error: "At least one --thread-id is required." };
|
|
43
|
+
return { ok: true, suggestions };
|
|
44
|
+
}
|
|
45
|
+
function setMetadata(current, flag) {
|
|
46
|
+
if (!current)
|
|
47
|
+
return { ok: false, error: `${flag.name} must follow --thread-id.` };
|
|
48
|
+
const property = flag.name === "--message" ? "message" : "description";
|
|
49
|
+
if (current[property] !== undefined) {
|
|
50
|
+
return { ok: false, error: `${flag.name} may appear only once per suggestion.` };
|
|
51
|
+
}
|
|
52
|
+
return { ok: true, current: { ...current, [property]: flag.value } };
|
|
53
|
+
}
|
|
54
|
+
function parseFlag(args, index) {
|
|
55
|
+
const arg = args[index];
|
|
56
|
+
for (const name of ["--thread-id", "--message", "--description"]) {
|
|
57
|
+
if (arg.startsWith(`${name}=`)) {
|
|
58
|
+
return { name, value: arg.slice(name.length + 1), consumed: 1 };
|
|
59
|
+
}
|
|
60
|
+
if (arg === name && index + 1 < args.length) {
|
|
61
|
+
return { name, value: args[index + 1], consumed: 2 };
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
function finalize(current) {
|
|
67
|
+
if (!current)
|
|
68
|
+
return { ok: true, suggestion: null };
|
|
69
|
+
if (!current.threadId || current.threadId.trim() === "") {
|
|
70
|
+
return { ok: false, error: "--thread-id must be non-empty." };
|
|
71
|
+
}
|
|
72
|
+
if (!current.message || current.message.trim() === "") {
|
|
73
|
+
return { ok: false, error: `--message is required for thread ${current.threadId}.` };
|
|
74
|
+
}
|
|
75
|
+
return {
|
|
76
|
+
ok: true,
|
|
77
|
+
suggestion: {
|
|
78
|
+
threadId: current.threadId,
|
|
79
|
+
message: current.message,
|
|
80
|
+
...(current.description !== undefined && { description: current.description }),
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
}
|
package/bin/cli-parser.mjs
CHANGED
|
@@ -8,7 +8,7 @@ import { parseCommonArgs, getFlag, hasFlag, parseList } from "./cli/args.mjs";
|
|
|
8
8
|
import { isDefaultPollInvocation, validateDefaultPollArgs } from "./cli/default-poll.mjs";
|
|
9
9
|
import { USAGE, helpKeyForArgs, maybePrintHelp } from "./cli/help.mjs";
|
|
10
10
|
import { formatMutateResult } from "./cli/formatters.mjs";
|
|
11
|
-
import { handleClean, handleCommitSuggestion, handleIterate, handleMarkFilesAsViewed, } from "./cli/handlers.mjs";
|
|
11
|
+
import { handleClean, handleCommitSuggestion, handleSuggestionPatches, handleIterate, handleMarkFilesAsViewed, } from "./cli/handlers.mjs";
|
|
12
12
|
import { handleJournal } from "./cli/journal-handler.mjs";
|
|
13
13
|
import { handlePoll } from "./cli/poll-handler.mjs";
|
|
14
14
|
import { warnPrrcThreadIds, validateRequireSha, rejectPrrcMinimizeIds, } from "./cli/resolve-validators.mjs";
|
|
@@ -54,7 +54,8 @@ export async function main(argv) {
|
|
|
54
54
|
resolve: "apply review",
|
|
55
55
|
"mark-files-as-viewed": "apply files",
|
|
56
56
|
journal: "apply journal",
|
|
57
|
-
"
|
|
57
|
+
"build-suggestion-patch": "build-suggestion-patches",
|
|
58
|
+
"commit-suggestion": "build-suggestion-patches",
|
|
58
59
|
};
|
|
59
60
|
if (subcommand !== undefined && legacyReplacement[subcommand] !== undefined) {
|
|
60
61
|
warnLegacyAlias(subcommand, legacyReplacement[subcommand]);
|
|
@@ -71,6 +72,9 @@ export async function main(argv) {
|
|
|
71
72
|
case "apply":
|
|
72
73
|
await handleApply(args.slice(1));
|
|
73
74
|
break;
|
|
75
|
+
case "build-suggestion-patches":
|
|
76
|
+
await handleSuggestionPatches(args.slice(1));
|
|
77
|
+
break;
|
|
74
78
|
case "build-suggestion-patch":
|
|
75
79
|
await handleCommitSuggestion(args.slice(1));
|
|
76
80
|
break;
|
package/bin/commands/check.mjs
CHANGED
|
@@ -42,7 +42,22 @@ export async function runCheck(opts) {
|
|
|
42
42
|
? []
|
|
43
43
|
: await fetchStartupFailureChecks(repo, batchData.headRefOid, prNumber);
|
|
44
44
|
const allChecks = mergeStartupFailureChecks(batchData.checks, startupFailureChecks);
|
|
45
|
-
const
|
|
45
|
+
const classifiedPrChecks = classifyChecks(allChecks);
|
|
46
|
+
const latestRemoval = batchData.latestMergeQueueRemoval;
|
|
47
|
+
const headUpdatedAfterRemoval = Boolean(latestRemoval &&
|
|
48
|
+
latestRemoval.beforeCommitParentOids &&
|
|
49
|
+
!latestRemoval.beforeCommitParentOids.includes(batchData.headRefOid));
|
|
50
|
+
const queueRawChecks = batchData.isInMergeQueue
|
|
51
|
+
? (batchData.mergeQueueChecks ?? [])
|
|
52
|
+
: latestRemoval && !headUpdatedAfterRemoval
|
|
53
|
+
? (batchData.removedMergeQueueChecks ?? [])
|
|
54
|
+
: [];
|
|
55
|
+
// Keep supersession grouping commit-local, but accept merge_group only for the
|
|
56
|
+
// synthetic queue-commit source.
|
|
57
|
+
const classifiedQueueChecks = classifyChecks(queueRawChecks, {
|
|
58
|
+
additionalRelevantEvents: ["merge_group"],
|
|
59
|
+
});
|
|
60
|
+
const classifiedChecks = [...classifiedPrChecks, ...classifiedQueueChecks];
|
|
46
61
|
const verdict = getCiVerdict(classifiedChecks);
|
|
47
62
|
const passing = classifiedChecks.filter((c) => c.category === "passed");
|
|
48
63
|
const failing = classifiedChecks.filter((c) => c.category === "failing");
|
|
@@ -131,9 +146,17 @@ export async function runCheck(opts) {
|
|
|
131
146
|
}
|
|
132
147
|
}
|
|
133
148
|
const blockedByFilteredCheck = isBlockedByFilteredCheck(mergeStatus, verdict);
|
|
149
|
+
const queueCommit = batchData.isInMergeQueue
|
|
150
|
+
? batchData.mergeQueueEntry?.headCommitOid
|
|
151
|
+
: batchData.latestMergeQueueRemoval?.beforeCommitOid;
|
|
152
|
+
const hasQueueState = Boolean(batchData.isMergeQueueEnabled ||
|
|
153
|
+
batchData.isInMergeQueue ||
|
|
154
|
+
batchData.autoMergeRequest ||
|
|
155
|
+
batchData.latestMergeQueueRemoval);
|
|
134
156
|
return {
|
|
135
157
|
pr: prNumber,
|
|
136
158
|
nodeId: batchData.nodeId,
|
|
159
|
+
headSha: batchData.headRefOid,
|
|
137
160
|
repo: `${repo.owner}/${repo.name}`,
|
|
138
161
|
status,
|
|
139
162
|
baseBranch: batchData.baseRefName,
|
|
@@ -175,6 +198,24 @@ export async function runCheck(opts) {
|
|
|
175
198
|
: undefined),
|
|
176
199
|
branchProtection: batchData.branchProtection,
|
|
177
200
|
activity: batchData.activity,
|
|
201
|
+
...(hasQueueState && {
|
|
202
|
+
mergeQueue: {
|
|
203
|
+
enabled: Boolean(batchData.isMergeQueueEnabled),
|
|
204
|
+
inQueue: Boolean(batchData.isInMergeQueue),
|
|
205
|
+
...(batchData.autoMergeRequest && { autoMergeRequest: batchData.autoMergeRequest }),
|
|
206
|
+
...(batchData.mergeQueueEntry && { entry: batchData.mergeQueueEntry }),
|
|
207
|
+
...(batchData.latestMergeQueueRemoval && {
|
|
208
|
+
latestRemoval: batchData.latestMergeQueueRemoval,
|
|
209
|
+
}),
|
|
210
|
+
...(queueCommit && { checkCommitOid: queueCommit }),
|
|
211
|
+
...((batchData.isInMergeQueue
|
|
212
|
+
? batchData.mergeQueueChecksIncomplete
|
|
213
|
+
: batchData.removedMergeQueueChecksIncomplete) && {
|
|
214
|
+
checksIncomplete: true,
|
|
215
|
+
}),
|
|
216
|
+
...(headUpdatedAfterRemoval && { headUpdatedAfterRemoval: true }),
|
|
217
|
+
},
|
|
218
|
+
}),
|
|
178
219
|
};
|
|
179
220
|
}
|
|
180
221
|
async function remainingRuleAutoResolveIds(partition, autoMinimizeSuppressed = false) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Build the `build-suggestion-
|
|
2
|
+
* Build the `build-suggestion-patches` instruction step for agent consumers.
|
|
3
3
|
* Currently emitted by iterate `fix_code` for suggestion review threads. The CLI keeps
|
|
4
4
|
* only the trigger and the concrete command; refusal/drift handling is invariant across
|
|
5
5
|
* every invocation, so it lives in the pr-shepherd skill's "Suggestion patches" playbook
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { buildPrShepherdCommand } from "../cli/runner.mjs";
|
|
2
2
|
/**
|
|
3
|
-
* Build the `build-suggestion-
|
|
3
|
+
* Build the `build-suggestion-patches` instruction step for agent consumers.
|
|
4
4
|
* Currently emitted by iterate `fix_code` for suggestion review threads. The CLI keeps
|
|
5
5
|
* only the trigger and the concrete command; refusal/drift handling is invariant across
|
|
6
6
|
* every invocation, so it lives in the pr-shepherd skill's "Suggestion patches" playbook
|
|
@@ -11,7 +11,7 @@ import { buildPrShepherdCommand } from "../cli/runner.mjs";
|
|
|
11
11
|
*/
|
|
12
12
|
export function buildCommitSuggestionInstruction(prNumber, sectionName) {
|
|
13
13
|
const command = buildPrShepherdCommand([
|
|
14
|
-
"build-suggestion-
|
|
14
|
+
"build-suggestion-patches",
|
|
15
15
|
String(prNumber),
|
|
16
16
|
"--thread-id",
|
|
17
17
|
"<id>",
|
|
@@ -19,5 +19,5 @@ export function buildCommitSuggestionInstruction(prNumber, sectionName) {
|
|
|
19
19
|
"<one-sentence headline>",
|
|
20
20
|
"--format=json",
|
|
21
21
|
]).text;
|
|
22
|
-
return `For
|
|
22
|
+
return `For all threads marked \`[suggestion]\` under \`${sectionName}\`, run one \`${command}\` command, repeating the \`--thread-id <id> --message <one-sentence headline>\` group in displayed order, then apply the returned patches in order. See "Suggestion patches" in the pr-shepherd skill for refusals and drift.`;
|
|
23
23
|
}
|
|
@@ -4,5 +4,5 @@ export interface CommitSuggestionOptions extends GlobalOptions {
|
|
|
4
4
|
message: string;
|
|
5
5
|
description?: string;
|
|
6
6
|
}
|
|
7
|
-
/** @deprecated
|
|
7
|
+
/** @deprecated Use runSuggestionPatches. */
|
|
8
8
|
export declare function runCommitSuggestion(opts: CommitSuggestionOptions): Promise<CommitSuggestionResult>;
|