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.
Files changed (109) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/README.md +14 -9
  3. package/bin/api.d.mts +12 -1
  4. package/bin/api.mjs +34 -1
  5. package/bin/checks/classify.d.mts +3 -1
  6. package/bin/checks/classify.mjs +5 -2
  7. package/bin/cli/args.mjs +1 -0
  8. package/bin/cli/default-poll.mjs +1 -0
  9. package/bin/cli/fix-formatter.mjs +12 -2
  10. package/bin/cli/formatters.d.mts +2 -1
  11. package/bin/cli/formatters.mjs +33 -0
  12. package/bin/cli/handlers.d.mts +1 -0
  13. package/bin/cli/handlers.mjs +21 -1
  14. package/bin/cli/help-command-pages.d.mts +22 -6
  15. package/bin/cli/help-command-pages.mjs +20 -4
  16. package/bin/cli/help-iterate-poll-pages.d.mts +2 -2
  17. package/bin/cli/help-iterate-poll-pages.mjs +7 -2
  18. package/bin/cli/help-top-page.d.mts +1 -1
  19. package/bin/cli/help-top-page.mjs +3 -3
  20. package/bin/cli/help.d.mts +23 -7
  21. package/bin/cli/iterate-flags.d.mts +1 -0
  22. package/bin/cli/iterate-flags.mjs +2 -0
  23. package/bin/cli/iterate-formatter.mjs +4 -1
  24. package/bin/cli/iterate-instructions.mjs +15 -0
  25. package/bin/cli/iterate-lean.d.mts +1 -2
  26. package/bin/cli/iterate-lean.mjs +12 -17
  27. package/bin/cli/iterate-merge-formatter.d.mts +3 -0
  28. package/bin/cli/iterate-merge-formatter.mjs +52 -0
  29. package/bin/cli/iterate-verbose.d.mts +6 -0
  30. package/bin/cli/iterate-verbose.mjs +14 -0
  31. package/bin/cli/poll-handler.mjs +1 -0
  32. package/bin/cli/runner.mjs +4 -3
  33. package/bin/cli/suggestion-patch-flags.d.mts +11 -0
  34. package/bin/cli/suggestion-patch-flags.mjs +83 -0
  35. package/bin/cli-parser.mjs +6 -2
  36. package/bin/commands/check-terminal-report.mjs +1 -0
  37. package/bin/commands/check.mjs +42 -1
  38. package/bin/commands/commit-suggestion-instruction.d.mts +1 -1
  39. package/bin/commands/commit-suggestion-instruction.mjs +3 -3
  40. package/bin/commands/commit-suggestion.d.mts +1 -1
  41. package/bin/commands/commit-suggestion.mjs +19 -138
  42. package/bin/commands/iterate/base.d.mts +5 -0
  43. package/bin/commands/iterate/base.mjs +25 -0
  44. package/bin/commands/iterate/escalate.d.mts +3 -1
  45. package/bin/commands/iterate/escalate.mjs +18 -2
  46. package/bin/commands/iterate/fix-code.mjs +16 -0
  47. package/bin/commands/iterate/helpers.mjs +6 -2
  48. package/bin/commands/iterate/index.mjs +29 -35
  49. package/bin/commands/iterate/merge-state.d.mts +15 -0
  50. package/bin/commands/iterate/merge-state.mjs +53 -0
  51. package/bin/commands/iterate/merge.d.mts +13 -0
  52. package/bin/commands/iterate/merge.mjs +46 -0
  53. package/bin/commands/poll.mjs +3 -1
  54. package/bin/commands/suggestion-patch-git.d.mts +6 -0
  55. package/bin/commands/suggestion-patch-git.mjs +54 -0
  56. package/bin/commands/suggestion-patch-item.d.mts +15 -0
  57. package/bin/commands/suggestion-patch-item.mjs +106 -0
  58. package/bin/commands/suggestion-patches.d.mts +6 -0
  59. package/bin/commands/suggestion-patches.mjs +108 -0
  60. package/bin/config/load.d.mts +4 -0
  61. package/bin/config/load.mjs +34 -0
  62. package/bin/config/merge-command-args.d.mts +2 -0
  63. package/bin/config/merge-command-args.mjs +44 -0
  64. package/bin/config.json +3 -0
  65. package/bin/exit-codes.d.mts +2 -0
  66. package/bin/exit-codes.mjs +4 -0
  67. package/bin/github/batch-parse-checks.d.mts +3 -0
  68. package/bin/github/batch-parse-checks.mjs +29 -0
  69. package/bin/github/batch-parsers-rules.d.mts +3 -1
  70. package/bin/github/batch-parsers-rules.mjs +33 -0
  71. package/bin/github/batch-parsers.mjs +23 -26
  72. package/bin/github/batch-raw-rules.d.mts +48 -0
  73. package/bin/github/batch-raw-types.mjs +0 -1
  74. package/bin/github/batch.mjs +2 -0
  75. package/bin/github/gql/batch-pr.gql +92 -0
  76. package/bin/github/gql/commit-check-contexts.gql +58 -0
  77. package/bin/github/gql/{commit-suggestion-thread.gql → suggestion-threads.gql} +2 -2
  78. package/bin/github/merge-queue-checks.d.mts +4 -0
  79. package/bin/github/merge-queue-checks.mjs +48 -0
  80. package/bin/github/queries.d.mts +3 -1
  81. package/bin/github/queries.mjs +3 -1
  82. package/bin/github/suggestion-thread.d.mts +3 -3
  83. package/bin/github/suggestion-thread.mjs +8 -5
  84. package/bin/mcp/server.d.mts +1 -1
  85. package/bin/mcp/server.mjs +24 -3
  86. package/bin/reporters/agent.mjs +6 -3
  87. package/bin/types/activity.d.mts +2 -0
  88. package/bin/types/escalate.d.mts +30 -0
  89. package/bin/types/escalate.mjs +1 -0
  90. package/bin/types/github.d.mts +8 -0
  91. package/bin/types/github.mjs +0 -3
  92. package/bin/types/iterate.d.mts +14 -31
  93. package/bin/types/merge-action.d.mts +12 -0
  94. package/bin/types/merge-action.mjs +1 -0
  95. package/bin/types/merge-queue.d.mts +13 -0
  96. package/bin/types/merge-queue.mjs +1 -0
  97. package/bin/types/merge-requirements.d.mts +17 -0
  98. package/bin/types/report.d.mts +8 -19
  99. package/bin/types/suggestion-patch.d.mts +30 -0
  100. package/bin/types/suggestion-patch.mjs +1 -0
  101. package/bin/types.d.mts +4 -0
  102. package/bin/types.mjs +4 -0
  103. package/bin/util/markdown.d.mts +2 -0
  104. package/bin/util/markdown.mjs +7 -0
  105. package/package.json +1 -1
  106. package/plugins/pr-shepherd/.codex-plugin/plugin.json +1 -1
  107. package/plugins/pr-shepherd/.codex.mcp.json +1 -1
  108. package/plugins/pr-shepherd/.mcp.json +1 -1
  109. package/plugins/pr-shepherd/skills/pr-shepherd/SKILL.md +11 -10
@@ -3,6 +3,7 @@ import type { ClassifiedCheck, TriagedCheck } from "./check-classification.mts";
3
3
  import type { AgentThreadComment } from "./agent-thread.mts";
4
4
  import type { CheckAnnotation } from "./check-annotations.mts";
5
5
  import type { PrActivitySummary } from "./activity.mts";
6
+ import type { MergeQueueReport } from "./merge-queue.mts";
6
7
  export interface FirstLookThread extends ReviewThread {
7
8
  firstLookStatus: "outdated" | "resolved" | "minimized";
8
9
  autoResolved?: boolean;
@@ -20,6 +21,8 @@ export interface ShepherdReport {
20
21
  pr: number;
21
22
  /** GitHub node ID of the PR — used for mutations (e.g. markPullRequestReadyForReview). */
22
23
  nodeId: string;
24
+ /** GitHub PR head OID from the same batch used to decide the action. */
25
+ headSha?: string;
23
26
  repo: string;
24
27
  status: ShepherdStatus;
25
28
  /** PR base branch from the GraphQL batch. */
@@ -71,6 +74,7 @@ export interface ShepherdReport {
71
74
  /** Branch protection rule for the PR's base branch. Null when no rule exists or the base ref is unavailable. */
72
75
  branchProtection: import("./github.mts").BranchProtection | null;
73
76
  activity?: PrActivitySummary;
77
+ mergeQueue?: MergeQueueReport;
74
78
  }
75
79
  export interface ResolveOptions {
76
80
  resolveThreadIds?: string[];
@@ -125,6 +129,8 @@ export interface AgentCheck {
125
129
  logExcerpt?: string;
126
130
  annotations?: CheckAnnotation[];
127
131
  annotationOnly?: true;
132
+ scope?: "merge_group";
133
+ commitOid?: string;
128
134
  }
129
135
  /**
130
136
  * A single CI check that is relevant to PR readiness — triggered by a PR event
@@ -149,25 +155,8 @@ export interface RelevantCheck {
149
155
  logExcerpt?: string;
150
156
  /** Marker-gated inline annotations from this check. */
151
157
  annotations?: CheckAnnotation[];
152
- }
153
- export interface CommitSuggestionResult {
154
- pr: number;
155
- repo: string;
156
- threadId: string;
157
- path: string;
158
- startLine: number;
159
- endLine: number;
160
- author: string;
161
- /** The unified diff generated for this suggestion. */
162
- patch: string;
163
- /** The commit subject line (user-supplied --message). */
164
- commitMessage: string;
165
- /** The commit body (optional description + Co-authored-by trailer). */
166
- commitBody: string;
167
- /** Files the agent should stage before committing. */
168
- filesToStage: string[];
169
- /** Numbered steps the agent must execute to apply, commit, resolve, and push. */
170
- postActionInstructions: string[];
158
+ scope?: "merge_group";
159
+ commitOid?: string;
171
160
  }
172
161
  export interface GlobalOptions {
173
162
  prNumber?: number;
@@ -0,0 +1,30 @@
1
+ export interface SuggestionPatchResult {
2
+ threadId: string;
3
+ path: string;
4
+ startLine: number;
5
+ endLine: number;
6
+ author: string;
7
+ /** The unified diff generated for this suggestion. */
8
+ patch: string;
9
+ /** The commit subject line supplied by the caller. */
10
+ commitMessage: string;
11
+ /** The optional description plus Co-authored-by trailer. */
12
+ commitBody: string;
13
+ /** Files the agent should stage before committing. */
14
+ filesToStage: string[];
15
+ }
16
+ export interface BuildSuggestionPatchesResult {
17
+ pr: number;
18
+ repo: string;
19
+ /** Suggestion patches in caller-supplied application order. */
20
+ patches: SuggestionPatchResult[];
21
+ /** Steps for applying and committing every patch, then pushing once. */
22
+ postActionInstructions: string[];
23
+ }
24
+ /** Compatibility result for the singular suggestion-patch adapter. */
25
+ export interface CommitSuggestionResult extends SuggestionPatchResult {
26
+ pr: number;
27
+ repo: string;
28
+ /** Numbered steps for the deprecated singular workflow. */
29
+ postActionInstructions: string[];
30
+ }
@@ -0,0 +1 @@
1
+ export {};
package/bin/types.d.mts CHANGED
@@ -6,5 +6,9 @@ export * from "./types/review-thread.mts";
6
6
  export * from "./types/agent-thread.mts";
7
7
  export * from "./types/check-annotations.mts";
8
8
  export * from "./types/report.mts";
9
+ export * from "./types/suggestion-patch.mts";
9
10
  export * from "./types/iterate.mts";
10
11
  export * from "./types/merge-requirements.mts";
12
+ export * from "./types/merge-action.mts";
13
+ export * from "./types/escalate.mts";
14
+ export * from "./types/merge-queue.mts";
package/bin/types.mjs CHANGED
@@ -6,5 +6,9 @@ export * from "./types/review-thread.mjs";
6
6
  export * from "./types/agent-thread.mjs";
7
7
  export * from "./types/check-annotations.mjs";
8
8
  export * from "./types/report.mjs";
9
+ export * from "./types/suggestion-patch.mjs";
9
10
  export * from "./types/iterate.mjs";
10
11
  export * from "./types/merge-requirements.mjs";
12
+ export * from "./types/merge-action.mjs";
13
+ export * from "./types/escalate.mjs";
14
+ export * from "./types/merge-queue.mjs";
@@ -1 +1,3 @@
1
1
  export declare function joinSections(sections: (string | null | undefined)[]): string;
2
+ /** Wrap arbitrary text in a CommonMark code span without colliding with embedded backticks. */
3
+ export declare function inlineCode(value: string): string;
@@ -5,3 +5,10 @@ export function joinSections(sections) {
5
5
  .filter((s) => s !== "")
6
6
  .join("\n\n");
7
7
  }
8
+ /** Wrap arbitrary text in a CommonMark code span without colliding with embedded backticks. */
9
+ export function inlineCode(value) {
10
+ const longestRun = Math.max(0, ...Array.from(value.matchAll(/`+/g), (match) => match[0].length));
11
+ const delimiter = "`".repeat(longestRun + 1);
12
+ const padding = value.startsWith("`") || value.endsWith("`") ? " " : "";
13
+ return `${delimiter}${padding}${value}${padding}${delimiter}`;
14
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pr-shepherd",
3
- "version": "0.41.0",
3
+ "version": "0.43.0",
4
4
  "description": "Autonomous PR CI monitor and review-comment resolver for agentic coding tools",
5
5
  "keywords": [
6
6
  "automation",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pr-shepherd",
3
- "version": "0.41.0",
3
+ "version": "0.43.0",
4
4
  "description": "Autonomous PR CI monitor and review-comment resolver for Codex.",
5
5
  "author": {
6
6
  "name": "Jonathan Ong",
@@ -2,7 +2,7 @@
2
2
  "mcpServers": {
3
3
  "pr-shepherd": {
4
4
  "command": "npx",
5
- "args": ["--yes", "--package", "pr-shepherd@0.41.0", "pr-shepherd-mcp"]
5
+ "args": ["--yes", "--package", "pr-shepherd@0.43.0", "pr-shepherd-mcp"]
6
6
  }
7
7
  }
8
8
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "pr-shepherd": {
3
3
  "command": "npx",
4
- "args": ["--yes", "--package", "pr-shepherd@0.41.0", "pr-shepherd-mcp"]
4
+ "args": ["--yes", "--package", "pr-shepherd@0.43.0", "pr-shepherd-mcp"]
5
5
  }
6
6
  }
@@ -2,7 +2,7 @@
2
2
  name: pr-shepherd
3
3
  description: 'Iterate a GitHub pull request with pr-shepherd (MCP or CLI). Use for requests like "use pr-shepherd", "iterate PR #123", or "run pr-shepherd until this PR is ready".'
4
4
  user-invocable: true
5
- argument-hint: "[PR number or URL]"
5
+ argument-hint: "[PR number or URL] [--merge]"
6
6
  allowed-tools: ["MCP", "Bash", "Read", "Grep", "Glob", "Edit", "Write"]
7
7
  ---
8
8
 
@@ -12,11 +12,11 @@ Thin dispatcher for iterating a PR. Poll with the CLI; use MCP `iterate` only wh
12
12
 
13
13
  ## Arguments: $ARGUMENTS
14
14
 
15
- 1. Parse an optional PR number, repository-qualified `owner/repo#N`, or GitHub PR URL from `$ARGUMENTS`; otherwise let pr-shepherd infer the current branch PR.
15
+ 1. Parse an optional PR number, repository-qualified `owner/repo#N`, or GitHub PR URL and an optional `--merge` flag from `$ARGUMENTS`; otherwise let pr-shepherd infer the current branch PR. Reject any remaining argument. Follow the target repository's local `AGENTS.md` and `CLAUDE.md` standards while making changes.
16
16
 
17
- 2. Before passing a supplied GitHub PR URL or `owner/repo#N` to the CLI, run `gh repo view --json nameWithOwner --jq .nameWithOwner` and verify that repository matches the reference case-insensitively. Stop on a mismatch or failed lookup; the CLI does not validate the URL repository. Convert a verified `owner/repo#N` to `https://github.com/owner/repo/pull/N`, then run the poll command `pr-shepherd` with the optional PR argument and print its full result. Do not run `pr-shepherd iterate`. If the CLI is unavailable and the `iterate` MCP tool is available, first obtain a repository-qualified reference: use a supplied GitHub PR URL or `owner/repo#N` unchanged; for a bare number, run `gh pr view <number> --json url --jq .url`; when omitted, run `gh pr view --json url --jq .url`. If that does not produce one qualified PR reference, stop and report that MCP cannot safely determine the PR. Otherwise call `iterate` with that qualified reference and print its full result.
17
+ 2. Before passing a supplied GitHub PR URL or `owner/repo#N` to the CLI, run `gh repo view --json nameWithOwner --jq .nameWithOwner` and verify that repository matches the reference case-insensitively. Stop on a mismatch or failed lookup; the CLI does not validate the URL repository. Convert a verified `owner/repo#N` to `https://github.com/owner/repo/pull/N`, then run the poll command `pr-shepherd` with the optional PR argument and forward `--merge` when supplied; print its full result. Do not run `pr-shepherd iterate`. If the CLI is unavailable and the `iterate` MCP tool is available, first obtain a repository-qualified reference: use a supplied GitHub PR URL or `owner/repo#N` unchanged; for a bare number, run `gh pr view <number> --json url --jq .url`; when omitted, run `gh pr view --json url --jq .url`. If that does not produce one qualified PR reference, stop and report that MCP cannot safely determine the PR. Otherwise call `iterate` with that qualified reference, plus `merge: true` when `--merge` was supplied, and print its full result.
18
18
 
19
- 3. Print the full result and follow every returned `## Instructions` step exactly. For CLI output, run each printed mutation command when instructed. For MCP output, use MCP `apply` and `build_suggestion_patch` with the same qualified PR reference; do not run a shell `pr-shepherd apply` command.
19
+ 3. Print the full result and follow every returned `## Instructions` step exactly. For CLI output, run each printed mutation command when instructed. For MCP output, use MCP `apply` and `build_suggestion_patches` with the same qualified PR reference; do not run a shell `pr-shepherd apply` command.
20
20
 
21
21
  4. After completing the returned instructions, repeat step 2 unless the action is `[CANCEL]` or `[ESCALATE]`, the instructions require a human handoff, or the human directs you to stop.
22
22
 
@@ -27,11 +27,11 @@ mechanics every tick. Apply the referenced playbook in full whenever a step poin
27
27
 
28
28
  ### Suggestion patches
29
29
 
30
- - The CLI only builds the patch. Apply it, stage the listed file, and follow the returned commit instructions.
31
- - If the command refuses because the suggestion is unsafe (an unsafe anchored range or nested/unbalanced suggestion fences), skip patch application and edit the file manually. Do not retry the command.
32
- - For any other refusal, follow the CLI error's stated recovery action; do not manually edit the suggestion.
33
- - If the patch does not apply for any other reason, edit the file manually instead. Do not retry the command.
34
- - After source drift prevents a generated suggestion patch from applying, replace the heading's exact `path:startLine-endLine` range with the `Replaces lines …` block verbatim. An empty replacement deletes the range. One blank line replaces it with one blank line.
30
+ - Run one plural `build-suggestion-patches` command with a repeated `--thread-id --message [--description …]` group for every marked thread in displayed order.
31
+ - The CLI only builds patches. Apply, stage, and commit the returned patches in order, then push once.
32
+ - The command builds from the fetched PR head and accepts a clean local descendant only when the complete ordered patch stream passes `git apply --check`.
33
+ - If the command refuses because a suggestion is unsafe or no longer applies, inspect the current source, the displayed replacement block, and reviewer intent before editing manually. Do not apply a stale numeric range blindly or retry unchanged input.
34
+ - A returned patch was checked against the then-current worktree. If it later fails, re-inspect the worktree because it changed after validation.
35
35
  - Keep human-authored thread IDs in `apply review:` so Shepherd replies instead of resolving them.
36
36
 
37
37
  ### CI failure triage
@@ -53,12 +53,13 @@ More specific rows win over the general "GitHub Actions failure" row — check c
53
53
 
54
54
  Applies to every `apply review:` / `resolve-only:` command the CLI prints. Covers only what stays safe if you run the printed command **unmodified** — `$HEAD_SHA`/`$DISMISS_MESSAGE` substitution and the self-reply exclusion rule are separate CLI-printed steps, not covered here, because the printed command is unsafe by default without them.
55
55
 
56
+ - Run every generated `apply review:` / `resolve-only:` command even when no code change is warranted. The command records the agent's disposition of the included review items; skipping it leaves bot threads active and can eventually trigger `fix-thrash`.
56
57
  - Never add first-look-only or check-annotation IDs to `--reply-thread-ids`, `--resolve-thread-ids`, `--dismiss-review-ids`, or `--minimize-comment-ids` — those flags are pre-populated by the CLI.
57
58
  - Keep every existing `--dismiss-review-ids` ID the CLI already included. Each is a bot or non-human review that must be dismissed; omitting one leaves the PR in `CHANGES_REQUESTED`.
58
59
 
59
60
  ### Review-mutation routing
60
61
 
61
- For threads under `## Review threads to resolve`: human-authored IDs use `--reply-thread-ids` (Shepherd replies instead of resolving them); bot and non-human IDs use `--resolve-thread-ids`. Use the commands as generated — do not move an ID between flags.
62
+ For threads under both `## Review threads` and `## Review threads to resolve`, evaluate every thread before running mutations. Keep bot and non-human IDs in `--resolve-thread-ids`, including when the feedback is advisory, already satisfied, or otherwise warrants no code change. Human-authored IDs use `--reply-thread-ids`; Shepherd replies instead of resolving them. Never move a human-authored ID to `--resolve-thread-ids`. Use the commands as generated — do not move an ID between flags.
62
63
 
63
64
  ### Shepherd Journal
64
65