pr-shepherd 0.40.0 → 0.42.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 +25 -7
- package/bin/api.d.mts +13 -2
- package/bin/api.mjs +41 -24
- 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 +20 -1
- package/bin/cli/help-command-pages.d.mts +20 -4
- package/bin/cli/help-command-pages.mjs +20 -4
- 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 +21 -5
- 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/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/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/github/gql/{commit-suggestion-thread.gql → suggestion-threads.gql} +2 -2
- package/bin/github/queries.d.mts +1 -1
- package/bin/github/queries.mjs +1 -1
- package/bin/github/suggestion-thread.d.mts +3 -3
- package/bin/github/suggestion-thread.mjs +8 -5
- package/bin/journal/extract.d.mts +16 -0
- package/bin/journal/extract.mjs +71 -0
- package/bin/journal/index.d.mts +1 -0
- package/bin/journal/index.mjs +1 -0
- package/bin/journal/markdown-line.d.mts +2 -0
- package/bin/journal/markdown-line.mjs +4 -2
- package/bin/journal/reconcile.d.mts +1 -0
- package/bin/journal/reconcile.mjs +11 -8
- package/bin/mcp/server.d.mts +1 -1
- package/bin/mcp/server.mjs +38 -7
- package/bin/pr-reference.d.mts +7 -0
- package/bin/pr-reference.mjs +36 -0
- package/bin/types/report.d.mts +0 -19
- package/bin/types/suggestion-patch.d.mts +30 -0
- package/bin/types/suggestion-patch.mjs +1 -0
- package/bin/types.d.mts +1 -0
- package/bin/types.mjs +1 -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/mark-files-as-viewed/SKILL.md +2 -2
- package/plugins/pr-shepherd/skills/pr-shepherd/SKILL.md +10 -9
package/README.md
CHANGED
|
@@ -9,14 +9,14 @@ An agent finishing a PR should think about code, not reconstruct GitHub state or
|
|
|
9
9
|
## What it does
|
|
10
10
|
|
|
11
11
|
1. **Gather all context for a PR** in one invocation: review threads, comments, replies, summaries, CI, mergeability, merge requirements, first-look / outdated / edited items, and author provenance.
|
|
12
|
-
2. **Provide deterministic actions for the agent**: exactly one of `WAIT`, `MARK_READY`, `FIX_CODE`, `CANCEL`, or `ESCALATE`, plus numbered `## Instructions` and explicit `apply` / `
|
|
12
|
+
2. **Provide deterministic actions for the agent**: exactly one of `WAIT`, `MARK_READY`, `FIX_CODE`, `CANCEL`, or `ESCALATE`, plus numbered `## Instructions` and explicit `apply` / `build_suggestion_patches` operations. The agent still decides whether a comment or CI failure needs a code change. Shepherd does not classify signal vs noise and does not mutate git.
|
|
13
13
|
|
|
14
14
|
Highlights:
|
|
15
15
|
|
|
16
16
|
- Batched GraphQL reads and writes (plus REST where GraphQL cannot) so one poll replaces a tool-call fan-out. MCP `iterate` is one tick and the client owns recurrence; `--debounce` is a poll-dispatcher settle window, not an MCP tool.
|
|
17
17
|
- CI summaries include failed checks, and the failed job/step plus a log excerpt when triage can fetch them. Job and log details are omitted for `STARTUP_FAILURE` and `CANCELLED`; agents may still inspect logs.
|
|
18
18
|
- Handles GitHub comment types (comments, threads, replies) and their states, including first-look, outdated, resolved, minimized, and edited.
|
|
19
|
-
- `apply` batches resolve / reply / minimize / dismiss. `
|
|
19
|
+
- `apply` batches resolve / reply / minimize / dismiss. `build_suggestion_patches` validates and returns ordered diffs without mutating git.
|
|
20
20
|
- `BEHIND` is mergeability information, not a rebase or a guarantee that the next push is at the default-branch tip. The agent can update the branch before pushing.
|
|
21
21
|
|
|
22
22
|
Full reference: [docs/README.md](docs/README.md). Feature matrix: [docs/features.md](docs/features.md).
|
|
@@ -25,7 +25,7 @@ Full reference: [docs/README.md](docs/README.md). Feature matrix: [docs/features
|
|
|
25
25
|
|
|
26
26
|
`pr-shepherd` moves deterministic PR orchestration into a local MCP server, with a CLI for shells and CI. Both interfaces fetch the same GitHub state, emit raw-enough context, and return a numbered plan for the calling agent to follow.
|
|
27
27
|
|
|
28
|
-
The MCP server exposes
|
|
28
|
+
The MCP server exposes canonical `iterate`, `apply`, and `build_suggestion_patches` tools. `apply` accepts ordered review mutations, file-view mutations, and journal entries; the deprecated singular suggestion tool remains temporarily as an adapter. Direct MCP calls require a repository-qualified `pr`: a GitHub PR URL or `owner/repo#N`, matching the repository where the server started. The CLI and programmatic API also retain bare-number and current-branch PR discovery. The shipped skills are thin dispatchers for those tools.
|
|
29
29
|
|
|
30
30
|
Each tick returns exactly one action:
|
|
31
31
|
|
|
@@ -88,7 +88,7 @@ This system is opinionated and works best with PRs that use required status chec
|
|
|
88
88
|
- Every review thread/comment/review summary is surfaced at least once, even if already outdated, resolved, or minimized; edited items re-surface through seen markers.
|
|
89
89
|
- Draft PRs can be marked ready automatically when clean; disable with `actions.autoMarkReady: false` or `--no-auto-mark-ready`.
|
|
90
90
|
- The CLI never performs git mutations. It emits instructions; the caller commits, rebases, pushes, and handles repository hooks.
|
|
91
|
-
- `
|
|
91
|
+
- `build_suggestion_patches` turns one or more ordered GitHub suggestion threads into checked patches and commit metadata, but never edits the working tree or git history. Local HEAD may be ahead when the live PR head is its ancestor.
|
|
92
92
|
|
|
93
93
|
## Usage
|
|
94
94
|
|
|
@@ -115,7 +115,7 @@ Grok:
|
|
|
115
115
|
/pr-shepherd 42
|
|
116
116
|
```
|
|
117
117
|
|
|
118
|
-
MCP clients call `iterate` once per tick, then use `apply` for review/file/journal mutations and `
|
|
118
|
+
MCP clients call `iterate` once per tick, then use `apply` for review/file/journal mutations and `build_suggestion_patches` for anchored suggestions. Every direct MCP call supplies the same repository-qualified PR reference. `iterate` returns the same structured action data as the CLI, including its review mutation arguments. The client owns recurrence, so this works consistently in Codex, Claude Code, Grok, and any other stdio MCP client.
|
|
119
119
|
|
|
120
120
|
The CLI remains useful for shell workflows. Its canonical polling form is:
|
|
121
121
|
|
|
@@ -131,7 +131,25 @@ pr-shepherd iterate 42 # single tick
|
|
|
131
131
|
|
|
132
132
|
### Apply Review, File, And Journal Changes
|
|
133
133
|
|
|
134
|
-
Use `apply` with ordered operations to reply/resolve/minimize/dismiss review items, mark changed files viewed, or append an idempotent Shepherd Journal item. Use `
|
|
134
|
+
Use `apply` with ordered operations to reply/resolve/minimize/dismiss review items, mark changed files viewed, or append an idempotent Shepherd Journal item. Use `build_suggestion_patches` to turn ordered review suggestions into checked patches and commit metadata; it never changes the worktree or git history.
|
|
135
|
+
|
|
136
|
+
### Extract Shepherd Journal Entries
|
|
137
|
+
|
|
138
|
+
The pure `pr-shepherd/journal` entry point can extract one validated journal without GitHub access:
|
|
139
|
+
|
|
140
|
+
```ts
|
|
141
|
+
import { extractShepherdJournal } from "pr-shepherd/journal";
|
|
142
|
+
|
|
143
|
+
const result = extractShepherdJournal(prBody);
|
|
144
|
+
if (!result.ok) throw new Error(result.error);
|
|
145
|
+
|
|
146
|
+
for (const entry of result.journal?.entries ?? []) console.log(entry);
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
The result identifies canonical `details` versus historical `legacy` H2 journals and returns each
|
|
150
|
+
complete Markdown list item with LF line endings. It fails closed for malformed or ambiguous
|
|
151
|
+
containers and ignores journal-shaped examples hidden in Markdown constructs. The full journal API,
|
|
152
|
+
including append and reconciliation helpers, is documented in [docs/api.md](docs/api.md).
|
|
135
153
|
|
|
136
154
|
### Clean Local State
|
|
137
155
|
|
|
@@ -258,7 +276,7 @@ Ready-to-use examples for common patterns are in [`examples/classification/`](ex
|
|
|
258
276
|
|
|
259
277
|
## CLI aliases
|
|
260
278
|
|
|
261
|
-
`poll`, `resolve`, `commit-suggestion`, `mark-files-as-viewed`, `journal`, `clean`, and `log-file` are CLI aliases. Prefer default polling/`iterate` in a shell and the MCP `iterate`, `apply`, and `
|
|
279
|
+
`poll`, `resolve`, `build-suggestion-patch`, `commit-suggestion`, `mark-files-as-viewed`, `journal`, `clean`, and `log-file` are CLI aliases or deprecated adapters. Prefer default polling/`iterate` in a shell and the MCP `iterate`, `apply`, and `build_suggestion_patches` tools in an agent client.
|
|
262
280
|
|
|
263
281
|
## Requirements
|
|
264
282
|
|
package/bin/api.d.mts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { type JournalResult } from "./commands/journal/index.mts";
|
|
2
2
|
import { type MarkFilesAsViewedResult } from "./commands/mark-files-as-viewed.mts";
|
|
3
3
|
import type { ResolveResult } from "./comments/resolve.mts";
|
|
4
|
-
import type { CommitSuggestionResult, IterateCommandOptions, IterateResult } from "./types.mts";
|
|
4
|
+
import type { BuildSuggestionPatchesResult, CommitSuggestionResult, IterateCommandOptions, IterateResult } from "./types.mts";
|
|
5
5
|
export interface CreatePrShepherdOptions {
|
|
6
6
|
/** Working directory used for git, config, and classification-rule lookups. */
|
|
7
7
|
cwd?: string;
|
|
8
8
|
}
|
|
9
|
-
/** A positive PR number
|
|
9
|
+
/** A positive PR number, GitHub pull-request URL, or owner/repo#number reference. */
|
|
10
10
|
export type PrReference = number | string;
|
|
11
11
|
export type IterateInput = Omit<IterateCommandOptions, "format" | "prNumber"> & {
|
|
12
12
|
pr?: PrReference;
|
|
@@ -58,9 +58,20 @@ export interface BuildSuggestionPatchInput {
|
|
|
58
58
|
message: string;
|
|
59
59
|
description?: string;
|
|
60
60
|
}
|
|
61
|
+
export interface SuggestionPatchInput {
|
|
62
|
+
threadId: string;
|
|
63
|
+
message: string;
|
|
64
|
+
description?: string;
|
|
65
|
+
}
|
|
66
|
+
export interface BuildSuggestionPatchesInput {
|
|
67
|
+
pr?: PrReference;
|
|
68
|
+
suggestions: SuggestionPatchInput[];
|
|
69
|
+
}
|
|
61
70
|
export interface PrShepherd {
|
|
62
71
|
iterate(input?: IterateInput): Promise<IterateResult>;
|
|
63
72
|
apply(input: ApplyInput): Promise<ApplyResult>;
|
|
73
|
+
buildSuggestionPatches(input: BuildSuggestionPatchesInput): Promise<BuildSuggestionPatchesResult>;
|
|
74
|
+
/** Compatibility adapter; prefer buildSuggestionPatches. */
|
|
64
75
|
buildSuggestionPatch(input: BuildSuggestionPatchInput): Promise<CommitSuggestionResult>;
|
|
65
76
|
}
|
|
66
77
|
/** Raised before any API mutation when an input cannot be validated. */
|
package/bin/api.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/* eslint-disable max-lines */
|
|
2
2
|
import { resolve } from "node:path";
|
|
3
3
|
import { runCommitSuggestion } from "./commands/commit-suggestion.mjs";
|
|
4
|
+
import { runSuggestionPatches } from "./commands/suggestion-patches.mjs";
|
|
4
5
|
import { runIterate } from "./commands/iterate/index.mjs";
|
|
5
6
|
import { runJournal } from "./commands/journal/index.mjs";
|
|
6
7
|
import { validateJournalItem } from "./commands/journal/transform.mjs";
|
|
@@ -8,6 +9,7 @@ import { runMarkFilesAsViewed, } from "./commands/mark-files-as-viewed.mjs";
|
|
|
8
9
|
import { runResolveMutate } from "./commands/resolve-mutate.mjs";
|
|
9
10
|
import { runWithExecutionCwd } from "./execution-context.mjs";
|
|
10
11
|
import { getRepoInfo } from "./github/client.mjs";
|
|
12
|
+
import { parsePrReference } from "./pr-reference.mjs";
|
|
11
13
|
/** Raised before any API mutation when an input cannot be validated. */
|
|
12
14
|
export class PrShepherdValidationError extends Error {
|
|
13
15
|
constructor(message) {
|
|
@@ -100,6 +102,14 @@ export function createPrShepherd(options = {}) {
|
|
|
100
102
|
return runCommitSuggestion({ ...options, prNumber, format: "json" });
|
|
101
103
|
});
|
|
102
104
|
},
|
|
105
|
+
buildSuggestionPatches(input) {
|
|
106
|
+
validateSuggestionPatchesInput(input);
|
|
107
|
+
const { pr: _pr, ...options } = input;
|
|
108
|
+
return runWithExecutionCwd(cwd, async () => {
|
|
109
|
+
const prNumber = await resolvePrReference(input.pr);
|
|
110
|
+
return runSuggestionPatches({ ...options, prNumber, format: "json" });
|
|
111
|
+
});
|
|
112
|
+
},
|
|
103
113
|
});
|
|
104
114
|
}
|
|
105
115
|
function validateApplyInput(input) {
|
|
@@ -108,7 +118,7 @@ function validateApplyInput(input) {
|
|
|
108
118
|
}
|
|
109
119
|
for (const operation of input.operations)
|
|
110
120
|
validateOperation(operation);
|
|
111
|
-
|
|
121
|
+
validatePrReference(input.pr);
|
|
112
122
|
}
|
|
113
123
|
function validateOperation(operation) {
|
|
114
124
|
if (!operation || typeof operation !== "object") {
|
|
@@ -183,7 +193,7 @@ function validateMarkFilesViewed(operation) {
|
|
|
183
193
|
}
|
|
184
194
|
}
|
|
185
195
|
function validateSuggestionPatchInput(input) {
|
|
186
|
-
if (!input || typeof input.threadId !== "string" || input.threadId === "") {
|
|
196
|
+
if (!input || typeof input.threadId !== "string" || input.threadId.trim() === "") {
|
|
187
197
|
throw new PrShepherdValidationError("buildSuggestionPatch.threadId is required");
|
|
188
198
|
}
|
|
189
199
|
if (typeof input.message !== "string" || input.message.trim() === "") {
|
|
@@ -192,38 +202,45 @@ function validateSuggestionPatchInput(input) {
|
|
|
192
202
|
if (input.description !== undefined && typeof input.description !== "string") {
|
|
193
203
|
throw new PrShepherdValidationError("buildSuggestionPatch.description must be a string");
|
|
194
204
|
}
|
|
195
|
-
|
|
205
|
+
validatePrReference(input.pr);
|
|
196
206
|
}
|
|
197
|
-
function
|
|
198
|
-
if (
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
207
|
+
function validateSuggestionPatchesInput(input) {
|
|
208
|
+
if (!input || !Array.isArray(input.suggestions) || input.suggestions.length === 0) {
|
|
209
|
+
throw new PrShepherdValidationError("buildSuggestionPatches.suggestions must be a non-empty array");
|
|
210
|
+
}
|
|
211
|
+
const seen = new Set();
|
|
212
|
+
for (const suggestion of input.suggestions) {
|
|
213
|
+
if (!suggestion ||
|
|
214
|
+
typeof suggestion.threadId !== "string" ||
|
|
215
|
+
suggestion.threadId.trim() === "") {
|
|
216
|
+
throw new PrShepherdValidationError("each suggestion.threadId is required");
|
|
217
|
+
}
|
|
218
|
+
if (typeof suggestion.message !== "string" || suggestion.message.trim() === "") {
|
|
219
|
+
throw new PrShepherdValidationError("each suggestion.message must be non-empty");
|
|
220
|
+
}
|
|
221
|
+
if (suggestion.description !== undefined && typeof suggestion.description !== "string") {
|
|
222
|
+
throw new PrShepherdValidationError("each suggestion.description must be a string");
|
|
213
223
|
}
|
|
214
|
-
|
|
215
|
-
|
|
224
|
+
if (seen.has(suggestion.threadId)) {
|
|
225
|
+
throw new PrShepherdValidationError(`duplicate suggestion thread ID: ${suggestion.threadId}`);
|
|
216
226
|
}
|
|
227
|
+
seen.add(suggestion.threadId);
|
|
217
228
|
}
|
|
218
|
-
|
|
229
|
+
validatePrReference(input.pr);
|
|
219
230
|
}
|
|
220
|
-
|
|
231
|
+
function validatePrReference(pr) {
|
|
221
232
|
const parsed = parsePrReference(pr);
|
|
233
|
+
if (parsed !== null)
|
|
234
|
+
return parsed;
|
|
235
|
+
throw new PrShepherdValidationError("pr must be a positive number, a GitHub pull-request URL, or owner/repo#number");
|
|
236
|
+
}
|
|
237
|
+
async function resolvePrReference(pr) {
|
|
238
|
+
const parsed = validatePrReference(pr);
|
|
222
239
|
if (parsed.repository !== undefined) {
|
|
223
240
|
const repo = await getRepoInfo();
|
|
224
241
|
const currentRepository = `${repo.owner}/${repo.name}`;
|
|
225
242
|
if (parsed.repository.toLowerCase() !== currentRepository.toLowerCase()) {
|
|
226
|
-
throw new PrShepherdValidationError(`PR
|
|
243
|
+
throw new PrShepherdValidationError(`PR reference repository ${parsed.repository} does not match the configured repository ${currentRepository}`);
|
|
227
244
|
}
|
|
228
245
|
}
|
|
229
246
|
return parsed.number;
|
package/bin/cli/formatters.d.mts
CHANGED
|
@@ -3,5 +3,6 @@ export { projectIterateLean, projectIterateVerbose } from "./iterate-lean.mts";
|
|
|
3
3
|
export { formatCleanResult } from "./clean-formatter.mts";
|
|
4
4
|
export { formatMarkFilesAsViewedResult } from "./mark-files-as-viewed-formatter.mts";
|
|
5
5
|
export { formatMutateResult } from "./mutate-formatter.mts";
|
|
6
|
-
import type { CommitSuggestionResult } from "../types.mts";
|
|
6
|
+
import type { BuildSuggestionPatchesResult, CommitSuggestionResult } from "../types.mts";
|
|
7
|
+
export declare function formatSuggestionPatchesResult(result: BuildSuggestionPatchesResult): string;
|
|
7
8
|
export declare function formatCommitSuggestionResult(result: CommitSuggestionResult): string;
|
package/bin/cli/formatters.mjs
CHANGED
|
@@ -4,6 +4,14 @@ export { formatCleanResult } from "./clean-formatter.mjs";
|
|
|
4
4
|
export { formatMarkFilesAsViewedResult } from "./mark-files-as-viewed-formatter.mjs";
|
|
5
5
|
export { formatMutateResult } from "./mutate-formatter.mjs";
|
|
6
6
|
import { safeFence } from "./fence.mjs";
|
|
7
|
+
export function formatSuggestionPatchesResult(result) {
|
|
8
|
+
const lines = [`Suggestion patches for PR #${result.pr}:`, ` repo: ${result.repo}`];
|
|
9
|
+
result.patches.forEach((patch, index) => {
|
|
10
|
+
lines.push("", ...formatPatch(patch, `## Patch ${index + 1}`).split("\n"));
|
|
11
|
+
});
|
|
12
|
+
appendInstructions(lines, result.postActionInstructions);
|
|
13
|
+
return lines.join("\n");
|
|
14
|
+
}
|
|
7
15
|
export function formatCommitSuggestionResult(result) {
|
|
8
16
|
const lines = [];
|
|
9
17
|
const range = result.startLine === result.endLine
|
|
@@ -30,3 +38,28 @@ export function formatCommitSuggestionResult(result) {
|
|
|
30
38
|
}
|
|
31
39
|
return lines.join("\n");
|
|
32
40
|
}
|
|
41
|
+
function formatPatch(patch, heading) {
|
|
42
|
+
const range = patch.startLine === patch.endLine
|
|
43
|
+
? `line ${patch.startLine}`
|
|
44
|
+
: `lines ${patch.startLine}–${patch.endLine}`;
|
|
45
|
+
const lines = [
|
|
46
|
+
heading,
|
|
47
|
+
"",
|
|
48
|
+
`Suggestion from @${patch.author} — thread ${patch.threadId}:`,
|
|
49
|
+
` ${patch.path} (${range})`,
|
|
50
|
+
];
|
|
51
|
+
if (patch.patch) {
|
|
52
|
+
const fence = safeFence(patch.patch);
|
|
53
|
+
lines.push("", `${fence}diff`, patch.patch.trimEnd(), fence);
|
|
54
|
+
}
|
|
55
|
+
lines.push("", "### Suggested commit message", "", patch.commitMessage, "", patch.commitBody);
|
|
56
|
+
return lines.join("\n");
|
|
57
|
+
}
|
|
58
|
+
function appendInstructions(lines, instructions) {
|
|
59
|
+
if (instructions.length === 0)
|
|
60
|
+
return;
|
|
61
|
+
lines.push("", "## Instructions", "");
|
|
62
|
+
instructions.forEach((instruction, index) => {
|
|
63
|
+
lines.push(`${index + 1}. ${instruction}`);
|
|
64
|
+
});
|
|
65
|
+
}
|
package/bin/cli/handlers.d.mts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export declare function handleClean(args: string[], command?: "admin clean" | "clean"): Promise<void>;
|
|
2
2
|
export declare function handleCommitSuggestion(args: string[], command?: "build-suggestion-patch" | "commit-suggestion"): Promise<void>;
|
|
3
|
+
export declare function handleSuggestionPatches(args: string[]): Promise<void>;
|
|
3
4
|
export declare function handleIterate(args: string[]): Promise<void>;
|
|
4
5
|
export declare function handleMarkFilesAsViewed(args: string[], command?: "apply files" | "mark-files-as-viewed"): Promise<void>;
|
package/bin/cli/handlers.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { runCommitSuggestion } from "../commands/commit-suggestion.mjs";
|
|
2
|
+
import { runSuggestionPatches } from "../commands/suggestion-patches.mjs";
|
|
2
3
|
import { runMarkFilesAsViewed } from "../commands/mark-files-as-viewed.mjs";
|
|
3
4
|
import { runIterate } from "../commands/iterate/index.mjs";
|
|
4
5
|
import { runClean } from "../commands/clean.mjs";
|
|
@@ -6,7 +7,8 @@ import { loadConfig } from "../config/load.mjs";
|
|
|
6
7
|
import { EXIT } from "../exit-codes.mjs";
|
|
7
8
|
import { parseCommonArgs, getFlag } from "./args.mjs";
|
|
8
9
|
import { USAGE } from "./help.mjs";
|
|
9
|
-
import { formatCommitSuggestionResult, formatCleanResult, formatMarkFilesAsViewedResult, } from "./formatters.mjs";
|
|
10
|
+
import { formatCommitSuggestionResult, formatSuggestionPatchesResult, formatCleanResult, formatMarkFilesAsViewedResult, } from "./formatters.mjs";
|
|
11
|
+
import { parseSuggestionPatchGroups } from "./suggestion-patch-flags.mjs";
|
|
10
12
|
import { parseIterateFlags } from "./iterate-flags.mjs";
|
|
11
13
|
import { emitIterateResult } from "./iterate-emitter.mjs";
|
|
12
14
|
import { parseMarkFilesAsViewedArgs } from "./mark-files-as-viewed-flags.mjs";
|
|
@@ -92,6 +94,23 @@ export async function handleCommitSuggestion(args, command = "build-suggestion-p
|
|
|
92
94
|
? `${JSON.stringify(result, null, 2)}\n`
|
|
93
95
|
: `${formatCommitSuggestionResult(result)}\n`);
|
|
94
96
|
}
|
|
97
|
+
export async function handleSuggestionPatches(args) {
|
|
98
|
+
const { prNumber, global: globalOpts, extra } = parseCommonArgs(args);
|
|
99
|
+
const parsed = parseSuggestionPatchGroups(extra);
|
|
100
|
+
if (!parsed.ok) {
|
|
101
|
+
process.stderr.write(`${parsed.error}\n${USAGE["build-suggestion-patches"]}\n`);
|
|
102
|
+
process.exitCode = EXIT.USAGE;
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
const result = await runSuggestionPatches({
|
|
106
|
+
...globalOpts,
|
|
107
|
+
prNumber,
|
|
108
|
+
suggestions: parsed.suggestions,
|
|
109
|
+
});
|
|
110
|
+
process.stdout.write(globalOpts.format === "json"
|
|
111
|
+
? `${JSON.stringify(result, null, 2)}\n`
|
|
112
|
+
: `${formatSuggestionPatchesResult(result)}\n`);
|
|
113
|
+
}
|
|
95
114
|
export async function handleIterate(args) {
|
|
96
115
|
const { prNumber, global: globalOpts, extra } = parseCommonArgs(args);
|
|
97
116
|
const cfg = loadConfig();
|
|
@@ -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
|
|
@@ -64,11 +64,27 @@ PR may be a number or GitHub pull request URL. An item must start with '- ' foll
|
|
|
64
64
|
Use --file to read an item from a file, or --file - to read it from stdin. Exactly one item source
|
|
65
65
|
is required. --dry-run previews the resulting body without writing it.
|
|
66
66
|
--help, -h Print this help and exit before GitHub I/O.`,
|
|
67
|
-
"build-suggestion-
|
|
67
|
+
"build-suggestion-patches": `pr-shepherd build-suggestion-patches
|
|
68
68
|
|
|
69
|
-
Build
|
|
69
|
+
Build an ordered list of patches and commit instructions from GitHub review suggestions.
|
|
70
70
|
The command does not edit files or mutate git history.
|
|
71
71
|
|
|
72
|
+
Usage:
|
|
73
|
+
pr-shepherd build-suggestion-patches [PR]
|
|
74
|
+
--thread-id ID --message MSG [--description DESC]
|
|
75
|
+
[--thread-id ID --message MSG [--description DESC] ...]
|
|
76
|
+
[--format text|json]
|
|
77
|
+
|
|
78
|
+
Each --thread-id starts a suggestion group. Its following --message and optional --description
|
|
79
|
+
belong to that suggestion. Groups are validated and returned in command-line order.
|
|
80
|
+
|
|
81
|
+
The current branch must match the PR head ref. Local HEAD may equal or descend from the PR head;
|
|
82
|
+
every generated patch is dry-run in order with git apply --check before output.
|
|
83
|
+
--help, -h Print this help and exit before GitHub, git, config, or log I/O.`,
|
|
84
|
+
"build-suggestion-patch": `pr-shepherd build-suggestion-patch
|
|
85
|
+
|
|
86
|
+
Deprecated one-suggestion adapter. Use build-suggestion-patches.
|
|
87
|
+
|
|
72
88
|
Usage:
|
|
73
89
|
pr-shepherd build-suggestion-patch [PR] --thread-id ID --message MSG
|
|
74
90
|
[--description DESC] [--format text|json]
|
|
@@ -79,7 +95,7 @@ Flags:
|
|
|
79
95
|
--description <text> Optional longer commit body.
|
|
80
96
|
--format text|json Output format. Default: text.
|
|
81
97
|
|
|
82
|
-
The current branch must match the PR head ref
|
|
98
|
+
The current branch must match the PR head ref. Local HEAD may equal or descend from the PR head.
|
|
83
99
|
--help, -h Print this help and exit before GitHub, git, config, or log I/O.`,
|
|
84
100
|
admin: `pr-shepherd admin
|
|
85
101
|
|
|
@@ -152,7 +168,7 @@ Flags:
|
|
|
152
168
|
--help, -h Print this help and exit before GitHub, git, config, or log I/O.
|
|
153
169
|
|
|
154
170
|
Preconditions:
|
|
155
|
-
The current branch must match the PR head ref
|
|
171
|
+
The current branch must match the PR head ref. Local HEAD may equal or descend from the PR head.
|
|
156
172
|
|
|
157
173
|
Exit codes:
|
|
158
174
|
0 suggestion patch and instructions produced
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const TOP_USAGE = "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-
|
|
1
|
+
export declare const TOP_USAGE = "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.";
|
|
@@ -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
|
|
@@ -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;
|
|
@@ -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 {};
|