pr-shepherd 0.33.0 → 0.35.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 +3 -2
- package/.grok-plugin/marketplace.json +17 -0
- package/README.md +63 -41
- package/bin/api.d.mts +80 -0
- package/bin/api.mjs +236 -0
- package/bin/checks/classify.d.mts +41 -0
- package/bin/checks/startup-failures.d.mts +2 -0
- package/bin/checks/superseded.d.mts +21 -0
- package/bin/checks/triage.d.mts +4 -0
- package/bin/classify/apply.d.mts +18 -0
- package/bin/classify/apply.mjs +4 -0
- package/bin/classify/loader.d.mts +10 -0
- package/bin/classify/types.d.mts +35 -0
- package/bin/cli/args.d.mts +18 -0
- package/bin/cli/clean-formatter.d.mts +2 -0
- package/bin/cli/default-poll.d.mts +2 -0
- package/bin/cli/default-poll.mjs +2 -1
- package/bin/cli/duration-flag.d.mts +2 -0
- package/bin/cli/duration-flag.mjs +5 -4
- package/bin/cli/duration.d.mts +13 -0
- package/bin/cli/{exit-codes.mjs → duration.mjs} +0 -26
- package/bin/cli/fence.d.mts +1 -0
- package/bin/cli/fix-formatter-extra.d.mts +3 -0
- package/bin/cli/fix-formatter.d.mts +2 -0
- package/bin/cli/fix-formatter.mjs +6 -6
- package/bin/cli/formatters.d.mts +7 -0
- package/bin/cli/handlers.d.mts +4 -0
- package/bin/cli/handlers.mjs +20 -18
- package/bin/cli/help-command-pages.d.mts +231 -0
- package/bin/cli/help-command-pages.mjs +116 -72
- package/bin/cli/help-iterate-poll-pages.d.mts +4 -0
- package/bin/cli/help-iterate-poll-pages.mjs +74 -0
- package/bin/cli/help-log-file-page.d.mts +1 -0
- package/bin/cli/help-top-page.d.mts +1 -0
- package/bin/cli/help-top-page.mjs +22 -20
- package/bin/cli/help.d.mts +236 -0
- package/bin/cli/help.mjs +17 -0
- package/bin/cli/iterate-emitter.d.mts +8 -0
- package/bin/cli/iterate-emitter.mjs +2 -2
- package/bin/cli/iterate-flags.d.mts +11 -0
- package/bin/cli/iterate-flags.mjs +1 -1
- package/bin/cli/iterate-formatter.d.mts +19 -0
- package/bin/cli/iterate-instructions.d.mts +6 -0
- package/bin/cli/iterate-lean.d.mts +12 -0
- package/bin/cli/journal-formatter.d.mts +2 -0
- package/bin/cli/journal-formatter.mjs +15 -0
- package/bin/cli/journal-handler.d.mts +1 -0
- package/bin/cli/journal-handler.mjs +13 -25
- package/bin/cli/list-formatters.d.mts +76 -0
- package/bin/cli/list-formatters.mjs +9 -9
- package/bin/cli/mark-files-as-viewed-flags.d.mts +11 -0
- package/bin/cli/mark-files-as-viewed-formatter.d.mts +2 -0
- package/bin/cli/mutate-formatter.d.mts +2 -0
- package/bin/cli/poll-handler.d.mts +1 -0
- package/bin/cli/poll-handler.mjs +3 -3
- package/bin/cli/resolve-validators.d.mts +3 -0
- package/bin/cli/resolve-validators.mjs +6 -5
- package/bin/cli/runner.d.mts +7 -0
- package/bin/cli/suggestion-renderer.d.mts +3 -0
- package/bin/cli/validate-default-args.d.mts +6 -0
- package/bin/cli-parser.d.mts +2 -0
- package/bin/cli-parser.mjs +77 -20
- package/bin/commands/check-annotations.d.mts +5 -0
- package/bin/commands/check-status.d.mts +3 -0
- package/bin/commands/check-terminal-report.d.mts +5 -0
- package/bin/commands/check.d.mts +6 -0
- package/bin/commands/check.mjs +4 -2
- package/bin/commands/clean.d.mts +21 -0
- package/bin/commands/commit-suggestion-instruction.d.mts +8 -0
- package/bin/commands/commit-suggestion-instruction.mjs +3 -3
- package/bin/commands/commit-suggestion.d.mts +8 -0
- package/bin/commands/commit-suggestion.mjs +28 -26
- package/bin/commands/iterate/check-instructions.d.mts +16 -0
- package/bin/commands/iterate/check-instructions.mjs +3 -3
- package/bin/commands/iterate/classify.d.mts +18 -0
- package/bin/commands/iterate/classify.mjs +4 -4
- package/bin/commands/iterate/escalate.d.mts +31 -0
- package/bin/commands/iterate/escalate.mjs +7 -4
- package/bin/commands/iterate/fix-code.d.mts +25 -0
- package/bin/commands/iterate/helpers.d.mts +13 -0
- package/bin/commands/iterate/helpers.mjs +4 -1
- package/bin/commands/iterate/index.d.mts +2 -0
- package/bin/commands/iterate/index.mjs +10 -5
- package/bin/commands/iterate/render.d.mts +5 -0
- package/bin/commands/iterate/render.mjs +8 -6
- package/bin/commands/iterate/reruns.d.mts +20 -0
- package/bin/commands/iterate/stall.d.mts +6 -0
- package/bin/commands/journal/index.d.mts +14 -0
- package/bin/commands/journal/index.mjs +1 -0
- package/bin/commands/journal/transform.d.mts +22 -0
- package/bin/commands/log-file.d.mts +5 -0
- package/bin/commands/mark-files-as-viewed.d.mts +26 -0
- package/bin/commands/mark-files-as-viewed.mjs +8 -5
- package/bin/commands/poll.d.mts +10 -0
- package/bin/commands/poll.mjs +1 -0
- package/bin/commands/ready-delay.d.mts +29 -0
- package/bin/commands/ready-mergeability.d.mts +15 -0
- package/bin/commands/resolve-mutate.d.mts +4 -0
- package/bin/commands/resolve-mutate.mjs +3 -1
- package/bin/commands/resolve.d.mts +4 -0
- package/bin/commands/shepherd-journal.d.mts +7 -0
- package/bin/commands/shepherd-journal.mjs +2 -2
- package/bin/comments/authors.d.mts +14 -0
- package/bin/comments/marker.d.mts +2 -0
- package/bin/comments/minimize-policy.d.mts +4 -0
- package/bin/comments/pending-ops.d.mts +15 -0
- package/bin/comments/rate-limit.d.mts +18 -0
- package/bin/comments/resolve.d.mts +34 -0
- package/bin/comments/resolve.mjs +1 -0
- package/bin/comments/review-thread-markers.d.mts +8 -0
- package/bin/comments/review-visibility.d.mts +28 -0
- package/bin/comments/sha-poll.d.mts +2 -0
- package/bin/comments/thread-visibility.d.mts +11 -0
- package/bin/comments/visible-comments.d.mts +11 -0
- package/bin/config/load.d.mts +60 -0
- package/bin/config/load.mjs +72 -1
- package/bin/config.json +0 -2
- package/bin/execution-context.d.mts +9 -0
- package/bin/execution-context.mjs +19 -0
- package/bin/exit-codes.d.mts +51 -0
- package/bin/exit-codes.mjs +74 -0
- package/bin/github/activity.d.mts +3 -0
- package/bin/github/activity.mjs +7 -0
- package/bin/github/batch-parser-helpers.d.mts +22 -0
- package/bin/github/batch-parsers.d.mts +3 -0
- package/bin/github/batch-parsers.mjs +6 -0
- package/bin/github/batch-raw-types.d.mts +207 -0
- package/bin/github/batch-response.d.mts +4 -0
- package/bin/github/batch-response.mjs +8 -3
- package/bin/github/batch.d.mts +22 -0
- package/bin/github/branch-protection.d.mts +3 -0
- package/bin/github/check-annotations.d.mts +2 -0
- package/bin/github/client.d.mts +46 -0
- package/bin/github/client.mjs +7 -2
- package/bin/github/errors.d.mts +25 -0
- package/bin/github/errors.mjs +26 -2
- package/bin/github/gql/batch-pr.gql +5 -0
- package/bin/github/gql/review-thread-comments.gql +1 -0
- package/bin/github/graphql-http.d.mts +19 -0
- package/bin/github/graphql-response.d.mts +7 -0
- package/bin/github/graphql-response.mjs +5 -0
- package/bin/github/http-auth.d.mts +4 -0
- package/bin/github/http-auth.mjs +2 -1
- package/bin/github/http-request.d.mts +7 -0
- package/bin/github/http-utils.d.mts +11 -0
- package/bin/github/http.d.mts +5 -0
- package/bin/github/pagination.d.mts +45 -0
- package/bin/github/queries.d.mts +24 -0
- package/bin/github/rest-http.d.mts +2 -0
- package/bin/github/rest-http.mjs +19 -5
- package/bin/github/thread-comments.d.mts +2 -0
- package/bin/index.d.mts +10 -0
- package/bin/index.mjs +3 -2
- package/bin/log/log-file.d.mts +28 -0
- package/bin/log/session.d.mts +31 -0
- package/bin/log/setup.d.mts +6 -0
- package/bin/mcp/index.d.mts +5 -0
- package/bin/mcp/index.mjs +8 -0
- package/bin/mcp/server.d.mts +8 -0
- package/bin/mcp/server.mjs +157 -0
- package/bin/mcp-stdio.d.mts +2 -0
- package/bin/mcp-stdio.mjs +7 -0
- package/bin/merge-status/derive.d.mts +19 -0
- package/bin/reporters/agent.d.mts +23 -0
- package/bin/reporters/agent.mjs +3 -0
- package/bin/state/base.d.mts +1 -0
- package/bin/state/bot-cr-seen.d.mts +51 -0
- package/bin/state/bot-cr-seen.mjs +1 -1
- package/bin/state/fix-attempts.d.mts +27 -0
- package/bin/state/iterate-stall.d.mts +27 -0
- package/bin/state/seen-comments.d.mts +62 -0
- package/bin/suggestions/extract.d.mts +8 -0
- package/bin/suggestions/parse.d.mts +48 -0
- package/bin/suggestions/patch.d.mts +14 -0
- package/bin/threads/transcript.d.mts +14 -0
- package/bin/threads/transcript.mjs +4 -0
- package/bin/types/activity.d.mts +30 -0
- package/bin/types/agent-thread.d.mts +9 -0
- package/bin/types/check-annotations.d.mts +14 -0
- package/bin/types/check-classification.d.mts +19 -0
- package/bin/types/github.d.mts +139 -0
- package/bin/types/iterate.d.mts +157 -0
- package/bin/types/protected-run.d.mts +6 -0
- package/bin/types/report.d.mts +176 -0
- package/bin/types/review-thread.d.mts +12 -0
- package/bin/types.d.mts +9 -0
- package/bin/util/markdown.d.mts +1 -0
- package/bin/util/path-segment.d.mts +2 -0
- package/bin/util/sleep.d.mts +1 -0
- package/bin/util/worktree.d.mts +9 -0
- package/bin/util/worktree.mjs +4 -1
- package/package.json +51 -37
- package/plugins/pr-shepherd/.codex-plugin/plugin.json +3 -2
- package/plugins/pr-shepherd/.codex.mcp.json +8 -0
- package/plugins/pr-shepherd/.mcp.json +6 -0
- package/plugins/pr-shepherd/skills/mark-files-as-viewed/SKILL.md +5 -19
- package/plugins/pr-shepherd/skills/pr-shepherd/SKILL.md +6 -15
- package/src/classify/types.mts +12 -0
package/bin/cli/help.mjs
CHANGED
|
@@ -5,6 +5,23 @@ export const USAGE = {
|
|
|
5
5
|
top: TOP_USAGE,
|
|
6
6
|
...COMMAND_USAGE,
|
|
7
7
|
};
|
|
8
|
+
/** Resolve help keys for nested public commands before any command I/O. */
|
|
9
|
+
export function helpKeyForArgs(args) {
|
|
10
|
+
if (args[0] === "apply" && args[1] === "review")
|
|
11
|
+
return "apply review";
|
|
12
|
+
if (args[0] === "apply" && args[1] === "files")
|
|
13
|
+
return "apply files";
|
|
14
|
+
if (args[0] === "apply" && args[1] === "journal")
|
|
15
|
+
return "apply journal";
|
|
16
|
+
if (args[0] === "admin" && args[1] === "clean")
|
|
17
|
+
return "admin clean";
|
|
18
|
+
if (args[0] === "admin" && args[1] === "log-file")
|
|
19
|
+
return "admin log-file";
|
|
20
|
+
if (args[0] != null && args[0] in USAGE) {
|
|
21
|
+
return args[0];
|
|
22
|
+
}
|
|
23
|
+
return "top";
|
|
24
|
+
}
|
|
8
25
|
/** Prints usage for `key` to stdout and returns true if `--help` or `-h` is in args. */
|
|
9
26
|
export function maybePrintHelp(args, key) {
|
|
10
27
|
if (!hasFlag(args, "--help") && !hasFlag(args, "-h"))
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { IterateResult } from "../types.mts";
|
|
2
|
+
interface EmitIterateResultOpts {
|
|
3
|
+
format: "text" | "json";
|
|
4
|
+
verbose: boolean;
|
|
5
|
+
readyDelaySuffix?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function emitIterateResult(result: IterateResult, opts: EmitIterateResultOpts): void;
|
|
8
|
+
export {};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { iterateResultToExitCode } from "../exit-codes.mjs";
|
|
2
2
|
import { formatIterateResult, projectIterateLean, projectIterateVerbose } from "./formatters.mjs";
|
|
3
3
|
export function emitIterateResult(result, opts) {
|
|
4
4
|
const projectionOpts = {
|
|
@@ -14,5 +14,5 @@ export function emitIterateResult(result, opts) {
|
|
|
14
14
|
const text = formatIterateResult(result, { verbose: opts.verbose, ...projectionOpts });
|
|
15
15
|
process.stdout.write(`${text}\n`);
|
|
16
16
|
}
|
|
17
|
-
process.exitCode =
|
|
17
|
+
process.exitCode = iterateResultToExitCode(result);
|
|
18
18
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { loadConfig } from "../config/load.mts";
|
|
2
|
+
interface IterateFlags {
|
|
3
|
+
readyDelaySuffix: string | undefined | null;
|
|
4
|
+
readyDelaySeconds: number;
|
|
5
|
+
stallTimeoutSuffix: string | undefined | null;
|
|
6
|
+
stallTimeoutSeconds: number;
|
|
7
|
+
noAutoMarkReady: boolean;
|
|
8
|
+
noAutoCancelActionable: boolean;
|
|
9
|
+
}
|
|
10
|
+
export declare function parseIterateFlags(extra: string[], cfg: ReturnType<typeof loadConfig>): IterateFlags;
|
|
11
|
+
export {};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { getFlag, hasFlag } from "./args.mjs";
|
|
2
|
-
import { parseDurationToSeconds } from "./
|
|
2
|
+
import { parseDurationToSeconds } from "./duration.mjs";
|
|
3
3
|
import { validateSecondsDurationFlag } from "./duration-flag.mjs";
|
|
4
4
|
// --ready-delay and --stall-timeout are minute-family flags: a bare number means minutes, and 0 is a
|
|
5
5
|
// valid value (it disables the ready-delay settle window / stall-timeout escalation, respectively).
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { IterateResult } from "../types.mts";
|
|
2
|
+
/**
|
|
3
|
+
* Format an IterateResult as human-readable Markdown.
|
|
4
|
+
*
|
|
5
|
+
* Load-bearing conventions the iterate skill relies on:
|
|
6
|
+
* 1. The H1 heading on line 1 contains `[<ACTION>]` — the action tag identifies
|
|
7
|
+
* the output for logging and validation. Behavior is driven by `## Instructions`,
|
|
8
|
+
* not by dispatching on the tag.
|
|
9
|
+
* 2. `[FIX_CODE]` wraps the `resolve` command under `## Post-fix push` in
|
|
10
|
+
* backticks — the skill extracts the backticked content for execution.
|
|
11
|
+
* 3. Every action ends with a `## Instructions` section — numbered `1.`, `2.`, … —
|
|
12
|
+
* that tells the agent exactly what to do with this output. The section is
|
|
13
|
+
* unconditional: every action, every variant, always emits at least one step.
|
|
14
|
+
* The skill simply follows those steps; it does not need its own dispatch table.
|
|
15
|
+
*/
|
|
16
|
+
export declare function formatIterateResult(result: IterateResult, opts?: {
|
|
17
|
+
verbose?: boolean;
|
|
18
|
+
readyDelaySuffix?: string;
|
|
19
|
+
}): string;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { IterateResult } from "../types.mts";
|
|
2
|
+
export declare function buildSimpleIterateInstructions(result: Exclude<IterateResult, {
|
|
3
|
+
action: "fix_code";
|
|
4
|
+
}>): string[];
|
|
5
|
+
export declare function adaptIterateLog(log: string): string;
|
|
6
|
+
export declare function numberInstructions(instructions: string[]): string;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { IterateResult } from "../types.mts";
|
|
2
|
+
interface IterateProjectionOptions {
|
|
3
|
+
readyDelaySuffix?: string;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Project an IterateResult to a lean JSON shape for the default (non-verbose) output.
|
|
7
|
+
* Omits fields that are the trivial default (false, 0, empty) or state-gated fields
|
|
8
|
+
* outside the state where they are meaningful.
|
|
9
|
+
*/
|
|
10
|
+
export declare function projectIterateLean(result: IterateResult, opts?: IterateProjectionOptions): unknown;
|
|
11
|
+
export declare function projectIterateVerbose(result: IterateResult, opts?: IterateProjectionOptions): unknown;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export function formatJournalResult(result) {
|
|
2
|
+
if (result.dryRun) {
|
|
3
|
+
const lines = ["Dry run — no body change written."];
|
|
4
|
+
if (result.previewBody !== undefined) {
|
|
5
|
+
lines.push("", result.previewBody);
|
|
6
|
+
}
|
|
7
|
+
return lines.join("\n");
|
|
8
|
+
}
|
|
9
|
+
if (!result.mutated)
|
|
10
|
+
return "No change — entry already present.";
|
|
11
|
+
if (!result.sectionExisted) {
|
|
12
|
+
return `Created ## Shepherd Journal section in PR #${result.prNumber}.`;
|
|
13
|
+
}
|
|
14
|
+
return `Appended to ## Shepherd Journal in PR #${result.prNumber}.`;
|
|
15
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function handleJournal(args: string[], command?: "apply journal" | "journal"): Promise<void>;
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { EXIT, errorToExitCode } from "../exit-codes.mjs";
|
|
2
3
|
import { runJournal } from "../commands/journal/index.mjs";
|
|
3
4
|
import { getFlag, parsePrNumber } from "./args.mjs";
|
|
4
5
|
import { USAGE } from "./help.mjs";
|
|
5
|
-
|
|
6
|
+
import { formatJournalResult } from "./journal-formatter.mjs";
|
|
7
|
+
export async function handleJournal(args, command = "apply journal") {
|
|
6
8
|
for (const a of args) {
|
|
7
9
|
if (!a.startsWith("--"))
|
|
8
10
|
continue;
|
|
@@ -10,15 +12,15 @@ export async function handleJournal(args) {
|
|
|
10
12
|
continue;
|
|
11
13
|
if (a === "--file" || a.startsWith("--file="))
|
|
12
14
|
continue;
|
|
13
|
-
process.stderr.write(`pr-shepherd:
|
|
14
|
-
process.exitCode =
|
|
15
|
+
process.stderr.write(`pr-shepherd: ${command}: unknown flag: "${a}"\n`);
|
|
16
|
+
process.exitCode = EXIT.USAGE;
|
|
15
17
|
return;
|
|
16
18
|
}
|
|
17
19
|
const { prNumber, extra } = parseJournalArgs(args);
|
|
18
20
|
const filePath = getFlag(args, "--file");
|
|
19
21
|
if (filePath !== null && extra[0]) {
|
|
20
|
-
process.stderr.write(`pr-shepherd:
|
|
21
|
-
process.exitCode =
|
|
22
|
+
process.stderr.write(`pr-shepherd: ${command}: provide the entry as a positional argument or via --file, not both\n`);
|
|
23
|
+
process.exitCode = EXIT.USAGE;
|
|
22
24
|
return;
|
|
23
25
|
}
|
|
24
26
|
let rawItem;
|
|
@@ -26,13 +28,13 @@ export async function handleJournal(args) {
|
|
|
26
28
|
rawItem = filePath !== null ? await readItemSource(filePath) : extra[0];
|
|
27
29
|
}
|
|
28
30
|
catch (e) {
|
|
29
|
-
process.stderr.write(`pr-shepherd:
|
|
30
|
-
process.exitCode =
|
|
31
|
+
process.stderr.write(`pr-shepherd: ${command}: ${String(e)}\n`);
|
|
32
|
+
process.exitCode = EXIT.NOINPUT;
|
|
31
33
|
return;
|
|
32
34
|
}
|
|
33
35
|
if (rawItem === undefined) {
|
|
34
|
-
process.stderr.write(`${USAGE
|
|
35
|
-
process.exitCode =
|
|
36
|
+
process.stderr.write(`${USAGE[command]}\n`);
|
|
37
|
+
process.exitCode = EXIT.USAGE;
|
|
36
38
|
return;
|
|
37
39
|
}
|
|
38
40
|
const dryRun = args.includes("--dry-run");
|
|
@@ -48,8 +50,8 @@ export async function handleJournal(args) {
|
|
|
48
50
|
}
|
|
49
51
|
}
|
|
50
52
|
catch (e) {
|
|
51
|
-
process.stderr.write(`pr-shepherd:
|
|
52
|
-
process.exitCode =
|
|
53
|
+
process.stderr.write(`pr-shepherd: ${command}: ${String(e)}\n`);
|
|
54
|
+
process.exitCode = errorToExitCode(e);
|
|
53
55
|
}
|
|
54
56
|
}
|
|
55
57
|
/** Reads the journal entry from a file, or from stdin when `filePath` is `-`. */
|
|
@@ -95,17 +97,3 @@ function parseJournalArgs(args) {
|
|
|
95
97
|
}
|
|
96
98
|
return { prNumber, extra };
|
|
97
99
|
}
|
|
98
|
-
function formatJournalResult(result) {
|
|
99
|
-
if (result.dryRun) {
|
|
100
|
-
const lines = ["Dry run — no body change written."];
|
|
101
|
-
if (result.previewBody !== undefined) {
|
|
102
|
-
lines.push("", result.previewBody);
|
|
103
|
-
}
|
|
104
|
-
return lines.join("\n");
|
|
105
|
-
}
|
|
106
|
-
if (!result.mutated)
|
|
107
|
-
return "No change — entry already present.";
|
|
108
|
-
if (!result.sectionExisted)
|
|
109
|
-
return `Created ## Shepherd Journal section in PR #${result.prNumber}.`;
|
|
110
|
-
return `Appended to ## Shepherd Journal in PR #${result.prNumber}.`;
|
|
111
|
-
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import type { AuthorType, CommentAuthorAssociation, SuggestionBlock } from "../types.mts";
|
|
2
|
+
import type { FirstLookThread, FirstLookComment } from "../types/report.mts";
|
|
3
|
+
export declare function renderAuthor(author: string, authorType?: AuthorType, authorAssociation?: CommentAuthorAssociation): string;
|
|
4
|
+
export declare function renderBodyPreview(body: string): string;
|
|
5
|
+
export declare function renderThreadResolutionStatusTag(t: {
|
|
6
|
+
isOutdated?: boolean;
|
|
7
|
+
isMinimized?: boolean;
|
|
8
|
+
}): string;
|
|
9
|
+
interface ThreadBulletInput {
|
|
10
|
+
id: string;
|
|
11
|
+
reviewId?: string;
|
|
12
|
+
url?: string;
|
|
13
|
+
path?: string | null;
|
|
14
|
+
startLine?: number | null;
|
|
15
|
+
line?: number | null;
|
|
16
|
+
author: string;
|
|
17
|
+
authorType?: AuthorType;
|
|
18
|
+
authorAssociation?: CommentAuthorAssociation;
|
|
19
|
+
body: string;
|
|
20
|
+
comments?: Array<{
|
|
21
|
+
id: string;
|
|
22
|
+
author: string;
|
|
23
|
+
authorType?: AuthorType;
|
|
24
|
+
authorAssociation?: CommentAuthorAssociation;
|
|
25
|
+
body: string;
|
|
26
|
+
url: string;
|
|
27
|
+
}>;
|
|
28
|
+
suggestion?: SuggestionBlock;
|
|
29
|
+
edited?: boolean;
|
|
30
|
+
}
|
|
31
|
+
export declare function renderThreadBullet(t: ThreadBulletInput, opts?: {
|
|
32
|
+
statusTag?: string;
|
|
33
|
+
renderSuggestion?: boolean;
|
|
34
|
+
noBody?: boolean;
|
|
35
|
+
suppressEditedMarker?: boolean;
|
|
36
|
+
}): string;
|
|
37
|
+
export declare function renderThreadConversation(t: ThreadBulletInput): string;
|
|
38
|
+
export declare function blockquote(body: string): string;
|
|
39
|
+
export declare function renderCommentBullet(c: {
|
|
40
|
+
id: string;
|
|
41
|
+
url?: string;
|
|
42
|
+
author: string;
|
|
43
|
+
authorType?: AuthorType;
|
|
44
|
+
authorAssociation?: CommentAuthorAssociation;
|
|
45
|
+
body: string;
|
|
46
|
+
}, opts?: {
|
|
47
|
+
statusTag?: string;
|
|
48
|
+
}): string;
|
|
49
|
+
export declare function renderEditedCommentTag(c: {
|
|
50
|
+
edited?: boolean;
|
|
51
|
+
}): string | undefined;
|
|
52
|
+
export declare function renderReviewBullet(r: {
|
|
53
|
+
id: string;
|
|
54
|
+
author: string;
|
|
55
|
+
authorType?: AuthorType;
|
|
56
|
+
authorAssociation?: CommentAuthorAssociation;
|
|
57
|
+
body?: string;
|
|
58
|
+
staleBotCr?: boolean;
|
|
59
|
+
staleReview?: boolean;
|
|
60
|
+
}, opts?: {
|
|
61
|
+
includeBody?: boolean;
|
|
62
|
+
}): string;
|
|
63
|
+
export declare function renderReviewListSection(heading: string, items: {
|
|
64
|
+
id: string;
|
|
65
|
+
author: string;
|
|
66
|
+
authorType?: AuthorType;
|
|
67
|
+
authorAssociation?: CommentAuthorAssociation;
|
|
68
|
+
body?: string;
|
|
69
|
+
}[]): string | null;
|
|
70
|
+
/**
|
|
71
|
+
* Build bullet strings for the `## First-look items` section.
|
|
72
|
+
* Threads that also appear in resolutionOnlyIds have their body suppressed
|
|
73
|
+
* (already shown in `## Review threads to resolve`).
|
|
74
|
+
*/
|
|
75
|
+
export declare function buildFirstLookBullets(firstLookThreads: FirstLookThread[], resolutionOnlyIds: Set<string>, firstLookComments: FirstLookComment[]): string[];
|
|
76
|
+
export {};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { renderLineRange, renderSuggestionBlock } from "./suggestion-renderer.mjs";
|
|
2
2
|
import { threadComments } from "../threads/transcript.mjs";
|
|
3
3
|
const BODY_PREVIEW_MAX = 100;
|
|
4
|
-
export function renderAuthor(author, authorType) {
|
|
5
|
-
return
|
|
4
|
+
export function renderAuthor(author, authorType, authorAssociation) {
|
|
5
|
+
return [`@${author}`, authorType, authorAssociation].filter(Boolean).join(" · ");
|
|
6
6
|
}
|
|
7
7
|
export function renderBodyPreview(body) {
|
|
8
8
|
const normalizedBody = body.replace(/\r\n?/g, "\n");
|
|
@@ -30,7 +30,7 @@ export function renderThreadBullet(t, opts = {}) {
|
|
|
30
30
|
const editedMarker = t.edited && !opts.suppressEditedMarker ? " [edited since first look]" : "";
|
|
31
31
|
const reviewMarker = t.reviewId ? ` [reviewId=${t.reviewId}]` : "";
|
|
32
32
|
const statusSuffix = opts.statusTag ? ` ${opts.statusTag}` : "";
|
|
33
|
-
const bulletLine = `- \`threadId=${t.id}\`${link} ${loc} (${renderAuthor(t.author, t.authorType)})${reviewMarker}${suggestionMarker}${editedMarker}${statusSuffix}`;
|
|
33
|
+
const bulletLine = `- \`threadId=${t.id}\`${link} ${loc} (${renderAuthor(t.author, t.authorType, t.authorAssociation)})${reviewMarker}${suggestionMarker}${editedMarker}${statusSuffix}`;
|
|
34
34
|
if (!opts.noBody && (!t.comments || t.comments.length === 0)) {
|
|
35
35
|
const legacyLine = `${bulletLine}: ${renderBodyPreview(t.body)}`;
|
|
36
36
|
return t.suggestion && opts.renderSuggestion
|
|
@@ -53,9 +53,9 @@ export function renderThreadConversation(t) {
|
|
|
53
53
|
.map((c) => {
|
|
54
54
|
const heading = c.id
|
|
55
55
|
? c.url
|
|
56
|
-
? `#### [commentId=${c.id}](${c.url}) (${renderAuthor(c.author, c.authorType)})`
|
|
57
|
-
: `#### \`commentId=${c.id}\` (${renderAuthor(c.author, c.authorType)})`
|
|
58
|
-
: `#### (${renderAuthor(c.author, c.authorType)})`;
|
|
56
|
+
? `#### [commentId=${c.id}](${c.url}) (${renderAuthor(c.author, c.authorType, c.authorAssociation)})`
|
|
57
|
+
: `#### \`commentId=${c.id}\` (${renderAuthor(c.author, c.authorType, c.authorAssociation)})`
|
|
58
|
+
: `#### (${renderAuthor(c.author, c.authorType, c.authorAssociation)})`;
|
|
59
59
|
return `${heading}\n\n${blockquote(c.body)}`;
|
|
60
60
|
})
|
|
61
61
|
.join("\n\n");
|
|
@@ -73,7 +73,7 @@ function renderThreadCommentBullets(t) {
|
|
|
73
73
|
const link = c.url ? ` [↗](${c.url})` : "";
|
|
74
74
|
const id = c.id ? `\`commentId=${c.id}\`` : "comment";
|
|
75
75
|
return [
|
|
76
|
-
` - ${id}${link} (${renderAuthor(c.author, c.authorType)})`,
|
|
76
|
+
` - ${id}${link} (${renderAuthor(c.author, c.authorType, c.authorAssociation)})`,
|
|
77
77
|
indentBlockquote(c.body, " "),
|
|
78
78
|
].join("\n");
|
|
79
79
|
})
|
|
@@ -88,13 +88,13 @@ function indentBlockquote(body, indent) {
|
|
|
88
88
|
export function renderCommentBullet(c, opts = {}) {
|
|
89
89
|
const link = c.url ? ` [↗](${c.url})` : "";
|
|
90
90
|
const statusSuffix = opts.statusTag ? ` ${opts.statusTag}` : "";
|
|
91
|
-
return `- \`commentId=${c.id}\`${link} (${renderAuthor(c.author, c.authorType)})${statusSuffix}: ${renderBodyPreview(c.body)}`;
|
|
91
|
+
return `- \`commentId=${c.id}\`${link} (${renderAuthor(c.author, c.authorType, c.authorAssociation)})${statusSuffix}: ${renderBodyPreview(c.body)}`;
|
|
92
92
|
}
|
|
93
93
|
export function renderEditedCommentTag(c) {
|
|
94
94
|
return c.edited ? "[edited since first look]" : undefined;
|
|
95
95
|
}
|
|
96
96
|
export function renderReviewBullet(r, opts = {}) {
|
|
97
|
-
const base = `- \`reviewId=${r.id}\` (${renderAuthor(r.author, r.authorType)})`;
|
|
97
|
+
const base = `- \`reviewId=${r.id}\` (${renderAuthor(r.author, r.authorType, r.authorAssociation)})`;
|
|
98
98
|
const staleTag = r.staleReview
|
|
99
99
|
? " [stale — review is on an old commit, all threads resolved]"
|
|
100
100
|
: "";
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
type ParseMarkFilesAsViewedResult = {
|
|
2
|
+
ok: true;
|
|
3
|
+
files: string[];
|
|
4
|
+
tests: boolean;
|
|
5
|
+
matchPatterns: string[];
|
|
6
|
+
} | {
|
|
7
|
+
ok: false;
|
|
8
|
+
error: string;
|
|
9
|
+
};
|
|
10
|
+
export declare function parseMarkFilesAsViewedArgs(args: string[]): ParseMarkFilesAsViewedResult;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function handlePoll(args: string[]): Promise<void>;
|
package/bin/cli/poll-handler.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { runPoll } from "../commands/poll.mjs";
|
|
2
2
|
import { loadConfig } from "../config/load.mjs";
|
|
3
3
|
import { parseCommonArgs, getFlag, hasFlag } from "./args.mjs";
|
|
4
|
-
import { parseDurationToSeconds } from "./
|
|
4
|
+
import { parseDurationToSeconds } from "./duration.mjs";
|
|
5
5
|
import { validateSecondsDurationFlag } from "./duration-flag.mjs";
|
|
6
6
|
import { parseIterateFlags } from "./iterate-flags.mjs";
|
|
7
7
|
import { emitIterateResult } from "./iterate-emitter.mjs";
|
|
@@ -14,12 +14,12 @@ export async function handlePoll(args) {
|
|
|
14
14
|
if (flags.readyDelaySuffix === null || flags.stallTimeoutSuffix === null)
|
|
15
15
|
return;
|
|
16
16
|
const intervalStr = getFlag(extra, "--interval");
|
|
17
|
-
const intervalSuffix = validateSecondsDurationFlag("pr-shepherd
|
|
17
|
+
const intervalSuffix = validateSecondsDurationFlag("pr-shepherd", "--interval", intervalStr, hasFlag(extra, "--interval"));
|
|
18
18
|
if (intervalSuffix === null)
|
|
19
19
|
return;
|
|
20
20
|
const intervalSeconds = parseDurationToSeconds(intervalSuffix ?? "", DEFAULT_POLL_INTERVAL_SECONDS);
|
|
21
21
|
const timeoutStr = getFlag(extra, "--timeout");
|
|
22
|
-
const timeoutSuffix = validateSecondsDurationFlag("pr-shepherd
|
|
22
|
+
const timeoutSuffix = validateSecondsDurationFlag("pr-shepherd", "--timeout", timeoutStr, hasFlag(extra, "--timeout"));
|
|
23
23
|
if (timeoutSuffix === null)
|
|
24
24
|
return;
|
|
25
25
|
const timeoutSeconds = parseDurationToSeconds(timeoutSuffix ?? "", DEFAULT_POLL_TIMEOUT_SECONDS);
|
|
@@ -1,15 +1,16 @@
|
|
|
1
|
+
import { EXIT } from "../exit-codes.mjs";
|
|
1
2
|
export function rejectPrrcMinimizeIds(ids) {
|
|
2
3
|
const prrcIds = ids.filter((id) => id.startsWith("PRRC_"));
|
|
3
4
|
if (prrcIds.length > 0) {
|
|
4
|
-
process.stderr.write(`pr-shepherd:
|
|
5
|
-
process.exitCode =
|
|
5
|
+
process.stderr.write(`pr-shepherd: apply review: --minimize-comment-ids contains thread comment IDs (PRRC_*): ${prrcIds.join(", ")}. Thread comments cannot be minimized individually — resolve the parent thread using --resolve-thread-ids with the PRRT_* thread ID instead.\n`);
|
|
6
|
+
process.exitCode = EXIT.DATAERR;
|
|
6
7
|
}
|
|
7
8
|
return prrcIds;
|
|
8
9
|
}
|
|
9
10
|
export function warnPrrcThreadIds(ids) {
|
|
10
11
|
const prrcIds = ids.filter((id) => id.startsWith("PRRC_"));
|
|
11
12
|
if (prrcIds.length > 0) {
|
|
12
|
-
process.stderr.write(`pr-shepherd:
|
|
13
|
+
process.stderr.write(`pr-shepherd: apply review: warning: --resolve-thread-ids contains comment IDs (PRRC_*) instead of thread IDs (PRRT_*): ${prrcIds.join(", ")}. The resolveReviewThread mutation requires PRRT_* thread IDs. Run a GraphQL query for pullRequest.reviewThreads to get the correct IDs.\n`);
|
|
13
14
|
}
|
|
14
15
|
return prrcIds;
|
|
15
16
|
}
|
|
@@ -18,7 +19,7 @@ export function validateRequireSha(sha) {
|
|
|
18
19
|
return true;
|
|
19
20
|
if (/^[0-9a-f]{40}$/.test(sha))
|
|
20
21
|
return true;
|
|
21
|
-
process.stderr.write(`pr-shepherd:
|
|
22
|
-
process.exitCode =
|
|
22
|
+
process.stderr.write(`pr-shepherd: apply review: --require-sha must be a full 40-character lowercase hex SHA, got "${sha}". Short SHAs will never match GitHub's headRefOid. Use $(git rev-parse HEAD) to get the full SHA.\n`);
|
|
23
|
+
process.exitCode = EXIT.DATAERR;
|
|
23
24
|
return false;
|
|
24
25
|
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validate args for default-dispatch paths (e.g. `pr-shepherd [PR] [flags]`).
|
|
3
|
+
* Returns false when an unexpected token is found; calls onError with the
|
|
4
|
+
* offending arg so callers can print their own usage message.
|
|
5
|
+
*/
|
|
6
|
+
export declare function validateDefaultArgs(args: string[], flagsWithValues: ReadonlySet<string>, booleanFlags: ReadonlySet<string>, onError: (arg: string) => void): boolean;
|
package/bin/cli-parser.mjs
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
/* eslint-disable max-lines */
|
|
1
2
|
/** CLI argument parsing and subcommand dispatch for pr-shepherd. See --help for usage. */
|
|
2
3
|
import { readFileSync } from "node:fs";
|
|
4
|
+
import { EXIT, errorToExitCode } from "./exit-codes.mjs";
|
|
3
5
|
import { runResolveMutate } from "./commands/resolve.mjs";
|
|
4
6
|
import { runLogFile } from "./commands/log-file.mjs";
|
|
5
7
|
import { parseCommonArgs, getFlag, hasFlag, parseList } from "./cli/args.mjs";
|
|
6
8
|
import { isDefaultPollInvocation, validateDefaultPollArgs } from "./cli/default-poll.mjs";
|
|
7
|
-
import { USAGE, maybePrintHelp } from "./cli/help.mjs";
|
|
9
|
+
import { USAGE, helpKeyForArgs, maybePrintHelp } from "./cli/help.mjs";
|
|
8
10
|
import { formatMutateResult } from "./cli/formatters.mjs";
|
|
9
11
|
import { handleClean, handleCommitSuggestion, handleIterate, handleMarkFilesAsViewed, } from "./cli/handlers.mjs";
|
|
10
12
|
import { handleJournal } from "./cli/journal-handler.mjs";
|
|
@@ -30,19 +32,33 @@ export async function main(argv) {
|
|
|
30
32
|
await handleLogFile(args.slice(1));
|
|
31
33
|
return;
|
|
32
34
|
}
|
|
35
|
+
// The public command groups keep admin diagnostics out of the normal
|
|
36
|
+
// command namespace. Keep this before setupLog because log-file reads the
|
|
37
|
+
// log path and must not initialize/tee the log it is reporting.
|
|
38
|
+
if (subcommand === "admin" && args[1] === "log-file") {
|
|
39
|
+
await handleLogFile(args.slice(2), "admin log-file");
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
33
42
|
// Short-circuit all --help/-h before any I/O or logging.
|
|
34
43
|
if (hasFlag(args, "--help") || hasFlag(args, "-h")) {
|
|
35
44
|
if (isDefaultPollInvocation(subcommand)) {
|
|
36
|
-
process.stdout.write(`${USAGE.
|
|
45
|
+
process.stdout.write(`${USAGE.default}\n`);
|
|
37
46
|
}
|
|
38
47
|
else {
|
|
39
|
-
|
|
40
|
-
? subcommand
|
|
41
|
-
: "top";
|
|
42
|
-
process.stdout.write(`${USAGE[key]}\n`);
|
|
48
|
+
process.stdout.write(`${USAGE[helpKeyForArgs(args)]}\n`);
|
|
43
49
|
}
|
|
44
50
|
return;
|
|
45
51
|
}
|
|
52
|
+
const legacyReplacement = {
|
|
53
|
+
poll: "pr-shepherd [PR] (the default PR polling command)",
|
|
54
|
+
resolve: "apply review",
|
|
55
|
+
"mark-files-as-viewed": "apply files",
|
|
56
|
+
journal: "apply journal",
|
|
57
|
+
"commit-suggestion": "build-suggestion-patch",
|
|
58
|
+
};
|
|
59
|
+
if (subcommand !== undefined && legacyReplacement[subcommand] !== undefined) {
|
|
60
|
+
warnLegacyAlias(subcommand, legacyReplacement[subcommand]);
|
|
61
|
+
}
|
|
46
62
|
// Initialize the per-worktree log and install a stdout tee.
|
|
47
63
|
await setupLog(argv);
|
|
48
64
|
if (isDefaultPollInvocation(subcommand)) {
|
|
@@ -52,14 +68,23 @@ export async function main(argv) {
|
|
|
52
68
|
return;
|
|
53
69
|
}
|
|
54
70
|
switch (subcommand) {
|
|
71
|
+
case "apply":
|
|
72
|
+
await handleApply(args.slice(1));
|
|
73
|
+
break;
|
|
74
|
+
case "build-suggestion-patch":
|
|
75
|
+
await handleCommitSuggestion(args.slice(1));
|
|
76
|
+
break;
|
|
77
|
+
case "admin":
|
|
78
|
+
await handleAdmin(args.slice(1));
|
|
79
|
+
break;
|
|
55
80
|
case "resolve":
|
|
56
|
-
await handleResolve(args.slice(1));
|
|
81
|
+
await handleResolve(args.slice(1), "resolve");
|
|
57
82
|
break;
|
|
58
83
|
case "commit-suggestion":
|
|
59
|
-
await handleCommitSuggestion(args.slice(1));
|
|
84
|
+
await handleCommitSuggestion(args.slice(1), "commit-suggestion");
|
|
60
85
|
break;
|
|
61
86
|
case "mark-files-as-viewed":
|
|
62
|
-
await handleMarkFilesAsViewed(args.slice(1));
|
|
87
|
+
await handleMarkFilesAsViewed(args.slice(1), "mark-files-as-viewed");
|
|
63
88
|
break;
|
|
64
89
|
case "iterate":
|
|
65
90
|
await handleIterate(args.slice(1));
|
|
@@ -68,18 +93,50 @@ export async function main(argv) {
|
|
|
68
93
|
await handlePoll(args.slice(1));
|
|
69
94
|
break;
|
|
70
95
|
case "clean":
|
|
71
|
-
await handleClean(args.slice(1));
|
|
96
|
+
await handleClean(args.slice(1), "clean");
|
|
72
97
|
break;
|
|
73
98
|
case "journal":
|
|
74
|
-
await handleJournal(args.slice(1));
|
|
99
|
+
await handleJournal(args.slice(1), "journal");
|
|
75
100
|
break;
|
|
76
101
|
default:
|
|
77
102
|
process.stderr.write(`Unknown subcommand: ${subcommand ?? "(none)"}\n`);
|
|
78
103
|
process.stderr.write(`${USAGE.top}\n`);
|
|
79
|
-
process.exitCode =
|
|
104
|
+
process.exitCode = EXIT.USAGE;
|
|
80
105
|
return;
|
|
81
106
|
}
|
|
82
107
|
}
|
|
108
|
+
function warnLegacyAlias(alias, replacement) {
|
|
109
|
+
process.stderr.write(`pr-shepherd: ${alias} is deprecated; use ${replacement.startsWith("pr-shepherd") ? replacement : `pr-shepherd ${replacement}`} instead.\n`);
|
|
110
|
+
}
|
|
111
|
+
async function handleApply(args) {
|
|
112
|
+
const action = args[0];
|
|
113
|
+
switch (action) {
|
|
114
|
+
case "review":
|
|
115
|
+
await handleResolve(args.slice(1));
|
|
116
|
+
return;
|
|
117
|
+
case "files":
|
|
118
|
+
await handleMarkFilesAsViewed(args.slice(1));
|
|
119
|
+
return;
|
|
120
|
+
case "journal":
|
|
121
|
+
await handleJournal(args.slice(1));
|
|
122
|
+
return;
|
|
123
|
+
default:
|
|
124
|
+
process.stderr.write(`Unknown apply action: ${action ?? "(none)"}\n`);
|
|
125
|
+
process.stderr.write(`${USAGE.apply}\n`);
|
|
126
|
+
process.exitCode = EXIT.USAGE;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
async function handleAdmin(args) {
|
|
130
|
+
switch (args[0]) {
|
|
131
|
+
case "clean":
|
|
132
|
+
await handleClean(args.slice(1));
|
|
133
|
+
return;
|
|
134
|
+
default:
|
|
135
|
+
process.stderr.write(`Unknown admin command: ${args[0] ?? "(none)"}\n`);
|
|
136
|
+
process.stderr.write(`${USAGE.admin}\n`);
|
|
137
|
+
process.exitCode = EXIT.USAGE;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
83
140
|
function readVersion() {
|
|
84
141
|
const pkgUrl = new URL("../package.json", import.meta.url);
|
|
85
142
|
const pkg = JSON.parse(readFileSync(pkgUrl, "utf8"));
|
|
@@ -88,8 +145,8 @@ function readVersion() {
|
|
|
88
145
|
// ---------------------------------------------------------------------------
|
|
89
146
|
// Subcommand handlers
|
|
90
147
|
// ---------------------------------------------------------------------------
|
|
91
|
-
async function handleLogFile(args) {
|
|
92
|
-
if (maybePrintHelp(args,
|
|
148
|
+
async function handleLogFile(args, usageKey = "log-file") {
|
|
149
|
+
if (maybePrintHelp(args, usageKey))
|
|
93
150
|
return;
|
|
94
151
|
const jsonOut = args.some((a) => a === "--format=json") ||
|
|
95
152
|
(() => {
|
|
@@ -102,10 +159,10 @@ async function handleLogFile(args) {
|
|
|
102
159
|
}
|
|
103
160
|
catch (e) {
|
|
104
161
|
process.stderr.write(`pr-shepherd: log-file: ${String(e)}\n`);
|
|
105
|
-
process.exitCode =
|
|
162
|
+
process.exitCode = errorToExitCode(e);
|
|
106
163
|
}
|
|
107
164
|
}
|
|
108
|
-
async function handleResolve(args) {
|
|
165
|
+
async function handleResolve(args, command = "apply review") {
|
|
109
166
|
const { prNumber, global: globalOpts, extra } = parseCommonArgs(args);
|
|
110
167
|
const resolveThreadIds = parseList(getFlag(extra, "--resolve-thread-ids"));
|
|
111
168
|
const replyThreadIds = parseList(getFlag(extra, "--reply-thread-ids"));
|
|
@@ -119,8 +176,8 @@ async function handleResolve(args) {
|
|
|
119
176
|
if (rejectPrrcMinimizeIds(minimizeCommentIds).length > 0)
|
|
120
177
|
return;
|
|
121
178
|
if (hasFlag(extra, "--fetch")) {
|
|
122
|
-
process.stderr.write(
|
|
123
|
-
process.exitCode =
|
|
179
|
+
process.stderr.write(`pr-shepherd: ${command}: --fetch has been removed; run pr-shepherd iterate to fetch the next action.\n`);
|
|
180
|
+
process.exitCode = EXIT.USAGE;
|
|
124
181
|
return;
|
|
125
182
|
}
|
|
126
183
|
const hasAction = resolveThreadIds.length > 0 ||
|
|
@@ -128,8 +185,8 @@ async function handleResolve(args) {
|
|
|
128
185
|
minimizeCommentIds.length > 0 ||
|
|
129
186
|
dismissReviewIds.length > 0;
|
|
130
187
|
if (!hasAction) {
|
|
131
|
-
process.stderr.write(
|
|
132
|
-
process.exitCode =
|
|
188
|
+
process.stderr.write(`pr-shepherd: ${command}: an action flag is required (--reply-thread-ids, --resolve-thread-ids, --minimize-comment-ids, or --dismiss-review-ids).\n`);
|
|
189
|
+
process.exitCode = EXIT.USAGE;
|
|
133
190
|
return;
|
|
134
191
|
}
|
|
135
192
|
const result = await runResolveMutate({
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { CheckAnnotation, TriagedCheck } from "../types.mts";
|
|
2
|
+
export declare function attachUnseenCheckAnnotations(checks: TriagedCheck[], seenMap: Map<string, {
|
|
3
|
+
seenAt: number;
|
|
4
|
+
}>, prNumber: number): Promise<TriagedCheck[]>;
|
|
5
|
+
export declare function annotationMarkerBody(a: CheckAnnotation): string;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { MergeStatusResult, ShepherdStatus } from "../types.mts";
|
|
2
|
+
import type { CiVerdict } from "../checks/classify.mts";
|
|
3
|
+
export declare function computeStatus(verdict: CiVerdict, unresolvedThreads: number, unresolvedComments: number, mergeStatus: MergeStatusResult, changesRequestedReviews: number): ShepherdStatus;
|