pr-shepherd 0.60.1 → 1.0.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 +7 -5
- package/bin/api.d.mts +35 -24
- package/bin/api.mjs +68 -48
- package/bin/checks/classify.d.mts +1 -1
- package/bin/checks/classify.mjs +4 -4
- package/bin/checks/log-excerpt.mjs +1 -1
- package/bin/cli/arg-flags.mjs +0 -3
- package/bin/cli/clean-handler.d.mts +1 -1
- package/bin/cli/clean-handler.mjs +5 -15
- package/bin/cli/default-poll.d.mts +2 -0
- package/bin/cli/default-poll.mjs +9 -6
- package/bin/cli/formatters.d.mts +2 -3
- package/bin/cli/formatters.mjs +0 -26
- package/bin/cli/handlers.d.mts +3 -3
- package/bin/cli/handlers.mjs +45 -35
- package/bin/cli/help-command-pages.d.mts +13 -158
- package/bin/cli/help-command-pages.mjs +12 -157
- package/bin/cli/help-iterate-poll-pages.d.mts +4 -3
- package/bin/cli/help-iterate-poll-pages.mjs +76 -36
- package/bin/cli/help-log-file-page.d.mts +1 -1
- package/bin/cli/help-log-file-page.mjs +3 -5
- package/bin/cli/help-top-page.d.mts +1 -1
- package/bin/cli/help-top-page.mjs +19 -20
- package/bin/cli/help.d.mts +14 -159
- package/bin/cli/iterate-checks-formatter.mjs +1 -1
- package/bin/cli/iterate-flags.d.mts +2 -4
- package/bin/cli/iterate-flags.mjs +4 -20
- package/bin/cli/iterate-formatter.d.mts +1 -1
- package/bin/cli/iterate-formatter.mjs +6 -6
- package/bin/cli/iterate-instructions.d.mts +1 -1
- package/bin/cli/iterate-instructions.mjs +5 -6
- package/bin/cli/iterate-lean.mjs +32 -40
- package/bin/cli/iterate-verbose.mjs +1 -1
- package/bin/cli/journal-formatter.mjs +0 -3
- package/bin/cli/journal-handler.d.mts +1 -1
- package/bin/cli/journal-handler.mjs +2 -1
- package/bin/cli/mutate-formatter.mjs +0 -9
- package/bin/cli/next-check-format.d.mts +0 -4
- package/bin/cli/next-check-format.mjs +0 -4
- package/bin/cli/poll-handler.d.mts +3 -0
- package/bin/cli/poll-handler.mjs +88 -47
- package/bin/cli/poll-summary-emitter.mjs +2 -2
- package/bin/cli/poll-summary-formatter.mjs +2 -2
- package/bin/cli/poll-targets.d.mts +2 -2
- package/bin/cli/poll-targets.mjs +15 -35
- package/bin/cli/removed-flags.d.mts +3 -0
- package/bin/cli/removed-flags.mjs +24 -0
- package/bin/cli/runner.d.mts +1 -1
- package/bin/cli/runner.mjs +2 -2
- package/bin/cli/stack-overview.d.mts +0 -1
- package/bin/cli/stack-overview.mjs +1 -2
- package/bin/cli/{fix-formatter-extra.d.mts → triage-formatter-extra.d.mts} +1 -2
- package/bin/cli/{fix-formatter-extra.mjs → triage-formatter-extra.mjs} +0 -6
- package/bin/cli/triage-formatter.d.mts +4 -0
- package/bin/cli/{fix-formatter.mjs → triage-formatter.mjs} +31 -42
- package/bin/cli/unknown-flags.d.mts +6 -0
- package/bin/cli/unknown-flags.mjs +29 -0
- package/bin/cli-parser.mjs +41 -62
- package/bin/commands/check-annotations.d.mts +1 -1
- package/bin/commands/check-annotations.mjs +1 -1
- package/bin/commands/check-review-budget.d.mts +1 -1
- package/bin/commands/check-review-budget.mjs +1 -1
- package/bin/commands/check-wait-detectors.d.mts +1 -1
- package/bin/commands/check-wait-detectors.mjs +1 -1
- package/bin/commands/check.d.mts +1 -1
- package/bin/commands/check.mjs +7 -7
- package/bin/commands/commit-suggestion-instruction.d.mts +2 -2
- package/bin/commands/commit-suggestion-instruction.mjs +3 -3
- package/bin/commands/iterate/api-usage.mjs +8 -8
- package/bin/commands/iterate/check-instructions.d.mts +4 -4
- package/bin/commands/iterate/check-instructions.mjs +8 -8
- package/bin/commands/iterate/classify.mjs +2 -2
- package/bin/commands/iterate/escalate.mjs +6 -6
- package/bin/commands/iterate/index.mjs +20 -23
- package/bin/commands/iterate/merge-plan.mjs +3 -3
- package/bin/commands/iterate/merge-state.mjs +4 -7
- package/bin/commands/iterate/native-stack-rebase.mjs +1 -1
- package/bin/commands/iterate/render.d.mts +1 -1
- package/bin/commands/iterate/render.mjs +2 -2
- package/bin/commands/iterate/stall.mjs +11 -9
- package/bin/commands/iterate/{fix-loop-instruction.mjs → triage-loop-instruction.mjs} +7 -3
- package/bin/commands/iterate/{fix-code.d.mts → triage.d.mts} +2 -2
- package/bin/commands/iterate/{fix-code.mjs → triage.mjs} +14 -23
- package/bin/commands/iterate/unreported-required.mjs +2 -5
- package/bin/commands/journal/index.d.mts +1 -3
- package/bin/commands/journal/index.mjs +1 -1
- package/bin/commands/mark-files-as-viewed.d.mts +1 -3
- package/bin/commands/mark-files-as-viewed.mjs +1 -1
- package/bin/commands/next-check.d.mts +2 -2
- package/bin/commands/next-check.mjs +4 -2
- package/bin/commands/poll-progress.mjs +1 -1
- package/bin/commands/poll-summary-explicit-instructions.mjs +1 -1
- package/bin/commands/poll-summary-instructions.mjs +7 -7
- package/bin/commands/poll-summary.mjs +4 -4
- package/bin/commands/poll.d.mts +1 -1
- package/bin/commands/poll.mjs +4 -4
- package/bin/commands/resolve-mutate.d.mts +1 -1
- package/bin/commands/resolve-mutate.mjs +1 -1
- package/bin/commands/rest-stack-merge-readiness.mjs +1 -1
- package/bin/commands/single-tick.d.mts +5 -0
- package/bin/commands/single-tick.mjs +7 -0
- package/bin/commands/stack-drain.mjs +1 -1
- package/bin/commands/stack-merge-flag.mjs +1 -1
- package/bin/commands/stack-stall.d.mts +2 -2
- package/bin/commands/stack-stall.mjs +2 -2
- package/bin/commands/stack-work.d.mts +2 -2
- package/bin/commands/stack-work.mjs +2 -2
- package/bin/commands/suggestion-patch-item.d.mts +0 -1
- package/bin/commands/suggestion-patch-item.mjs +0 -12
- package/bin/commands/suggestion-patches.d.mts +2 -2
- package/bin/commands/suggestion-patches.mjs +1 -1
- package/bin/commands/tick-instructions.d.mts +9 -0
- package/bin/commands/tick-instructions.mjs +23 -0
- package/bin/commands/tick.d.mts +15 -0
- package/bin/commands/{event-mode.mjs → tick.mjs} +39 -55
- package/bin/comments/minimize-policy.mjs +1 -3
- package/bin/comments/resolve.d.mts +0 -23
- package/bin/comments/resolve.mjs +0 -4
- package/bin/comments/review-output-budget.d.mts +1 -1
- package/bin/comments/review-output-budget.mjs +1 -1
- package/bin/comments/sha-poll.mjs +3 -1
- package/bin/config/default-bot-usernames.d.mts +2 -0
- package/bin/config/default-bot-usernames.mjs +15 -0
- package/bin/config/load.d.mts +4 -138
- package/bin/config/load.mjs +88 -443
- package/bin/config/merge-command-args.mjs +2 -2
- package/bin/config/merge-method.d.mts +1 -2
- package/bin/config/merge-method.mjs +1 -8
- package/bin/config/renames.d.mts +8 -0
- package/bin/config/renames.mjs +87 -0
- package/bin/config/resolve.d.mts +31 -0
- package/bin/config/resolve.mjs +89 -0
- package/bin/config/schema.d.mts +161 -0
- package/bin/config/schema.mjs +168 -0
- package/bin/exit-codes.d.mts +1 -1
- package/bin/exit-codes.mjs +3 -3
- package/bin/github/poll-summary-check-blockers.mjs +1 -1
- package/bin/github/poll-summary-command.mjs +8 -6
- package/bin/github/poll-summary-projector.mjs +2 -2
- package/bin/github/poll-summary-review.mjs +1 -1
- package/bin/github/poll-summary-route.mjs +9 -9
- package/bin/github/poll-summary-unreported.mjs +1 -1
- package/bin/github/poll-summary.mjs +1 -1
- package/bin/github/queries.d.mts +1 -1
- package/bin/github/queries.mjs +1 -1
- package/bin/mcp/server.mjs +48 -54
- package/bin/merge-status/derive.mjs +1 -1
- package/bin/state/durable-state.d.mts +1 -3
- package/bin/state/durable-state.mjs +2 -8
- package/bin/state/fix-attempts.d.mts +2 -2
- package/bin/state/fix-attempts.mjs +1 -1
- package/bin/state/merge-request.mjs +1 -1
- package/bin/state/pr-fingerprint.mjs +4 -11
- package/bin/state/seen-comments.d.mts +4 -5
- package/bin/state/seen-comments.mjs +8 -14
- package/bin/state/stack-stall.d.mts +1 -1
- package/bin/state/stack-stall.mjs +1 -1
- package/bin/state/stall-state-store.d.mts +1 -1
- package/bin/state/stall-state-store.mjs +1 -1
- package/bin/types/escalate.d.mts +2 -2
- package/bin/types/iterate.d.mts +12 -26
- package/bin/types/merge-queue.d.mts +2 -2
- package/bin/types/next-check.d.mts +1 -1
- package/bin/types/poll-summary.d.mts +3 -6
- package/bin/types/report.d.mts +2 -2
- package/bin/types/suggestion-patch.d.mts +1 -8
- package/package.json +2 -1
- package/plugins/pr-shepherd/.claude-plugin/plugin.json +1 -1
- package/plugins/pr-shepherd/.codex-plugin/plugin.json +1 -1
- package/plugins/pr-shepherd/.codex.mcp.json +1 -1
- package/plugins/pr-shepherd/.mcp.json +1 -1
- package/plugins/pr-shepherd/skills/pr-shepherd/SKILL.md +6 -6
- package/plugins/pr-shepherd/skills/pr-shepherd/references/ci-failure-triage.md +1 -1
- package/plugins/pr-shepherd/skills/pr-shepherd/references/{cloud-event-loop.md → event-loop.md} +5 -5
- package/plugins/pr-shepherd/skills/pr-shepherd/references/mcp-fallback.md +3 -3
- package/plugins/pr-shepherd/skills/pr-shepherd/references/merge-queue-ejection.md +1 -1
- package/plugins/pr-shepherd/skills/pr-shepherd/references/suggestion-patches.md +1 -1
- package/plugins/pr-shepherd/skills/pr-shepherd/references/{fix-code-loop.md → triage-loop.md} +3 -3
- package/plugins/pr-shepherd/skills/reduce-pr-noise/SKILL.md +1 -1
- package/plugins/pr-shepherd/skills/reduce-pr-noise/references/classifiers.md +2 -2
- package/plugins/pr-shepherd/skills/reduce-pr-noise/references/settings.md +11 -11
- package/pr-shepherd.schema.json +361 -0
- package/bin/cli/event-state-scope.d.mts +0 -19
- package/bin/cli/event-state-scope.mjs +0 -60
- package/bin/cli/fix-formatter.d.mts +0 -4
- package/bin/commands/commit-suggestion.d.mts +0 -8
- package/bin/commands/commit-suggestion.mjs +0 -26
- package/bin/commands/event-instructions.d.mts +0 -11
- package/bin/commands/event-instructions.mjs +0 -27
- package/bin/commands/event-mode.d.mts +0 -14
- package/bin/commands/poll-mode.d.mts +0 -8
- package/bin/commands/poll-mode.mjs +0 -14
- package/bin/config.json +0 -68
- package/bin/types/protected-run.d.mts +0 -6
- package/bin/types/protected-run.mjs +0 -1
- /package/bin/commands/iterate/{fix-loop-instruction.d.mts → triage-loop-instruction.d.mts} +0 -0
|
@@ -1,16 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { loadConfig } from "../config/load.mts";
|
|
2
|
+
import { type InstructionStyle } from "../config/resolve.mts";
|
|
2
3
|
interface IterateFlags {
|
|
3
4
|
readyDelaySuffix: string | undefined | null;
|
|
4
5
|
readyDelaySeconds: number;
|
|
5
6
|
stallTimeoutSuffix: string | undefined | null;
|
|
6
7
|
stallTimeoutSeconds: number;
|
|
7
8
|
noAutoMarkReady: boolean;
|
|
8
|
-
noAutoCancelActionable: boolean;
|
|
9
9
|
merge: boolean;
|
|
10
10
|
/** `null` when `--instructions` was invalid (an error was already printed). */
|
|
11
11
|
instructions: InstructionStyle | null | undefined;
|
|
12
|
-
/** `null` when `--poll-mode` was invalid (an error was already printed). */
|
|
13
|
-
pollMode: PollMode | null | undefined;
|
|
14
12
|
}
|
|
15
13
|
/** True when any flag failed validation; the usage error is already printed. */
|
|
16
14
|
export declare function hasInvalidIterateFlags(flags: IterateFlags): boolean;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { INSTRUCTION_STYLES,
|
|
1
|
+
import { INSTRUCTION_STYLES, isInstructionStyle, } from "../config/resolve.mjs";
|
|
2
2
|
import { EXIT } from "../exit-codes.mjs";
|
|
3
3
|
import { getFlag, hasFlag } from "./args.mjs";
|
|
4
4
|
import { parseDurationToSeconds } from "./duration.mjs";
|
|
@@ -10,29 +10,25 @@ const MINUTE_FLAG_OPTS = { defaultUnit: "m", allowZero: true };
|
|
|
10
10
|
export function hasInvalidIterateFlags(flags) {
|
|
11
11
|
return (flags.readyDelaySuffix === null ||
|
|
12
12
|
flags.stallTimeoutSuffix === null ||
|
|
13
|
-
flags.instructions === null
|
|
14
|
-
flags.pollMode === null);
|
|
13
|
+
flags.instructions === null);
|
|
15
14
|
}
|
|
16
15
|
export function parseIterateFlags(extra, cfg) {
|
|
17
16
|
const readyDelayStr = getFlag(extra, "--ready-delay");
|
|
18
17
|
const readyDelaySuffix = validateSecondsDurationFlag("pr-shepherd", "--ready-delay", readyDelayStr, hasFlag(extra, "--ready-delay"), MINUTE_FLAG_OPTS);
|
|
19
|
-
const readyDelaySeconds = parseDurationToSeconds(readyDelaySuffix ?? "", cfg.
|
|
18
|
+
const readyDelaySeconds = parseDurationToSeconds(readyDelaySuffix ?? "", cfg.iterate["ready-delay-minutes"] * 60, MINUTE_FLAG_OPTS);
|
|
20
19
|
const noAutoMarkReady = hasFlag(extra, "--no-auto-mark-ready");
|
|
21
|
-
const noAutoCancelActionable = hasFlag(extra, "--no-auto-cancel-actionable");
|
|
22
20
|
const merge = hasFlag(extra, "--merge");
|
|
23
21
|
const stallTimeoutStr = getFlag(extra, "--stall-timeout");
|
|
24
22
|
const stallTimeoutSuffix = validateSecondsDurationFlag("pr-shepherd", "--stall-timeout", stallTimeoutStr, hasFlag(extra, "--stall-timeout"), MINUTE_FLAG_OPTS);
|
|
25
|
-
const stallTimeoutSeconds = parseDurationToSeconds(stallTimeoutSuffix ?? "", cfg.iterate
|
|
23
|
+
const stallTimeoutSeconds = parseDurationToSeconds(stallTimeoutSuffix ?? "", cfg.iterate["stall-timeout-minutes"] * 60, MINUTE_FLAG_OPTS);
|
|
26
24
|
const instructions = parseInstructionsFlag(extra);
|
|
27
25
|
return {
|
|
28
26
|
instructions,
|
|
29
|
-
pollMode: parsePollModeFlag(extra),
|
|
30
27
|
readyDelaySuffix,
|
|
31
28
|
readyDelaySeconds,
|
|
32
29
|
stallTimeoutSuffix,
|
|
33
30
|
stallTimeoutSeconds,
|
|
34
31
|
noAutoMarkReady,
|
|
35
|
-
noAutoCancelActionable,
|
|
36
32
|
merge,
|
|
37
33
|
};
|
|
38
34
|
}
|
|
@@ -50,15 +46,3 @@ function parseInstructionsFlag(extra) {
|
|
|
50
46
|
function hasInstructionsFlag(extra) {
|
|
51
47
|
return extra.some((arg) => arg === "--instructions" || arg.startsWith("--instructions="));
|
|
52
48
|
}
|
|
53
|
-
/** Validate `--poll-mode`. Returns `undefined` when absent, `null` after printing a usage error. */
|
|
54
|
-
function parsePollModeFlag(extra) {
|
|
55
|
-
const value = getFlag(extra, "--poll-mode");
|
|
56
|
-
if (!extra.some((arg) => arg === "--poll-mode" || arg.startsWith("--poll-mode="))) {
|
|
57
|
-
return undefined;
|
|
58
|
-
}
|
|
59
|
-
if (isPollMode(value))
|
|
60
|
-
return value;
|
|
61
|
-
process.stderr.write(`pr-shepherd: --poll-mode must be one of ${POLL_MODES.join(", ")}, got ${JSON.stringify(value ?? "")}\n`);
|
|
62
|
-
process.exitCode = EXIT.USAGE;
|
|
63
|
-
return null;
|
|
64
|
-
}
|
|
@@ -6,7 +6,7 @@ import type { IterateResult } from "../types.mts";
|
|
|
6
6
|
* 1. The H1 heading on line 1 contains `[<ACTION>]` — the action tag identifies
|
|
7
7
|
* the output for logging and validation. Behavior is driven by `## Instructions`,
|
|
8
8
|
* not by dispatching on the tag.
|
|
9
|
-
* 2. `[
|
|
9
|
+
* 2. `[TRIAGE]` prints the `apply review` command inline, in backticks, in its
|
|
10
10
|
* `## Instructions` step; the agent runs that backticked command as printed.
|
|
11
11
|
* 3. Every action except `cancel` ends with a `## Instructions` section — numbered
|
|
12
12
|
* `1.`, `2.`, … — that tells the agent exactly what to do with this output, with at
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* eslint-disable max-lines */
|
|
2
2
|
import { insertEditedCommentsSection } from "./edited-comments-format.mjs";
|
|
3
|
-
import {
|
|
3
|
+
import { formatTriageResult } from "./triage-formatter.mjs";
|
|
4
4
|
import { formatRelevantChecks } from "./iterate-checks-formatter.mjs";
|
|
5
5
|
import { joinSections } from "../util/markdown.mjs";
|
|
6
6
|
import { adaptIterateLog, buildSimpleIterateInstructions, numberInstructions, } from "./iterate-instructions.mjs";
|
|
@@ -12,7 +12,7 @@ import { formatSuppressedNameLines } from "./iterate-check-names.mjs";
|
|
|
12
12
|
import { branchStateSegment } from "./iterate-branch-segment.mjs";
|
|
13
13
|
import { insertRuleAutoResolveSection } from "../commands/rule-auto-resolve-format.mjs";
|
|
14
14
|
import { formatTransportEvidence } from "./transport-formatter.mjs";
|
|
15
|
-
import { formatNextCheckLines
|
|
15
|
+
import { formatNextCheckLines } from "./next-check-format.mjs";
|
|
16
16
|
import { formatPrUrl } from "../pr-reference.mjs";
|
|
17
17
|
/**
|
|
18
18
|
* Format an IterateResult as human-readable Markdown.
|
|
@@ -21,7 +21,7 @@ import { formatPrUrl } from "../pr-reference.mjs";
|
|
|
21
21
|
* 1. The H1 heading on line 1 contains `[<ACTION>]` — the action tag identifies
|
|
22
22
|
* the output for logging and validation. Behavior is driven by `## Instructions`,
|
|
23
23
|
* not by dispatching on the tag.
|
|
24
|
-
* 2. `[
|
|
24
|
+
* 2. `[TRIAGE]` prints the `apply review` command inline, in backticks, in its
|
|
25
25
|
* `## Instructions` step; the agent runs that backticked command as printed.
|
|
26
26
|
* 3. Every action except `cancel` ends with a `## Instructions` section — numbered
|
|
27
27
|
* `1.`, `2.`, … — that tells the agent exactly what to do with this output, with at
|
|
@@ -55,7 +55,7 @@ export function formatIterateResult(result, opts) {
|
|
|
55
55
|
? ` · **merge** \`${result.mergeStateStatus}\``
|
|
56
56
|
: "";
|
|
57
57
|
const stateSeg = verbose || result.state !== "OPEN" ? ` · **state** \`${result.state}\`` : "";
|
|
58
|
-
const baseLine = `**status** \`${result.status}\`${mergeSeg}${reviewDecisionSeg}${stateSeg}${repoSeg}${baseBranchSeg}
|
|
58
|
+
const baseLine = `**status** \`${result.status}\`${mergeSeg}${reviewDecisionSeg}${stateSeg}${repoSeg}${baseBranchSeg}`;
|
|
59
59
|
const branchSeg = branchStateSegment(result);
|
|
60
60
|
let summaryLine;
|
|
61
61
|
if (verbose) {
|
|
@@ -199,8 +199,8 @@ export function formatIterateResult(result, opts) {
|
|
|
199
199
|
result.escalate.humanMessage,
|
|
200
200
|
`## Instructions\n\n${numberInstructions(buildSimpleIterateInstructions(result))}`,
|
|
201
201
|
]));
|
|
202
|
-
case "
|
|
203
|
-
return finish(
|
|
202
|
+
case "triage":
|
|
203
|
+
return finish(formatTriageResult(joinSections([header, ...telemetrySections]), result, { verbose }));
|
|
204
204
|
}
|
|
205
205
|
}
|
|
206
206
|
function appendUnreportedLines(lines, result) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { IterateResult } from "../types.mts";
|
|
2
2
|
export declare function buildSimpleIterateInstructions(result: Exclude<IterateResult, {
|
|
3
|
-
action: "
|
|
3
|
+
action: "triage";
|
|
4
4
|
}>): string[];
|
|
5
5
|
export declare function adaptIterateLog(log: string): string;
|
|
6
6
|
export declare function numberInstructions(instructions: string[]): string;
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { inlineCode } from "../util/markdown.mjs";
|
|
2
2
|
import { buildQuotaAwareContinuation } from "../quota-warning.mjs";
|
|
3
3
|
import { renderShellCommand } from "./runner.mjs";
|
|
4
|
-
import {
|
|
4
|
+
import { tickWaitSteps } from "../commands/tick-instructions.mjs";
|
|
5
5
|
export function buildSimpleIterateInstructions(result) {
|
|
6
6
|
switch (result.action) {
|
|
7
7
|
case "ready": {
|
|
8
8
|
if (result.nextCheck) {
|
|
9
9
|
return [
|
|
10
10
|
`PR #${result.pr} is ready. Ready-delay has ${result.remainingSeconds}s left. Do not invent unrelated work.`,
|
|
11
|
-
...
|
|
11
|
+
...tickWaitSteps(result.nextCheck),
|
|
12
12
|
];
|
|
13
13
|
}
|
|
14
14
|
const sentence = `PR #${result.pr} is ready. Ready-delay has ${result.remainingSeconds}s left. Rerun this command when the timer elapses. Do not invent unrelated work.`;
|
|
@@ -18,7 +18,7 @@ export function buildSimpleIterateInstructions(result) {
|
|
|
18
18
|
}
|
|
19
19
|
case "wait":
|
|
20
20
|
if (result.nextCheck) {
|
|
21
|
-
return ["Non-terminal — no action needed this tick.", ...
|
|
21
|
+
return ["Non-terminal — no action needed this tick.", ...tickWaitSteps(result.nextCheck)];
|
|
22
22
|
}
|
|
23
23
|
if (result.quotaWarning) {
|
|
24
24
|
return [
|
|
@@ -29,8 +29,7 @@ export function buildSimpleIterateInstructions(result) {
|
|
|
29
29
|
"Non-terminal — no action needed this tick. Iterate immediately with the same options to continue.",
|
|
30
30
|
];
|
|
31
31
|
case "mark_ready":
|
|
32
|
-
|
|
33
|
-
if (result.quotaWarning && result.pollMode !== "event") {
|
|
32
|
+
if (result.quotaWarning) {
|
|
34
33
|
return [
|
|
35
34
|
buildQuotaAwareContinuation(result.quotaWarning, "The CLI marked the PR ready for review."),
|
|
36
35
|
];
|
|
@@ -44,7 +43,7 @@ export function buildSimpleIterateInstructions(result) {
|
|
|
44
43
|
if (result.merge.mode === "rest" && result.nextCheck)
|
|
45
44
|
return [
|
|
46
45
|
`Run the REST merge command exactly as printed: ${command}. \`enqueued\` is not merged.`,
|
|
47
|
-
...
|
|
46
|
+
...tickWaitSteps(result.nextCheck),
|
|
48
47
|
];
|
|
49
48
|
if (result.merge.mode === "rest")
|
|
50
49
|
return [
|
package/bin/cli/iterate-lean.mjs
CHANGED
|
@@ -95,7 +95,6 @@ export function projectIterateLean(result, opts) {
|
|
|
95
95
|
...(result.baseBehindBy !== undefined &&
|
|
96
96
|
result.baseBehindBy > 0 && { baseBehindBy: result.baseBehindBy }),
|
|
97
97
|
...(result.quotaWarning && { quotaWarning: result.quotaWarning }),
|
|
98
|
-
...(result.pollMode && { pollMode: result.pollMode }),
|
|
99
98
|
...(result.nextCheck && { nextCheck: result.nextCheck }),
|
|
100
99
|
...(result.ruleAutoResolve && {
|
|
101
100
|
ruleAutoResolve: projectRuleAutoResolve(result.ruleAutoResolve),
|
|
@@ -140,58 +139,51 @@ export function projectIterateLean(result, opts) {
|
|
|
140
139
|
merge: result.merge,
|
|
141
140
|
instructions: simpleInstructions(result),
|
|
142
141
|
};
|
|
143
|
-
case "
|
|
142
|
+
case "triage":
|
|
144
143
|
return {
|
|
145
144
|
...base,
|
|
146
|
-
// Passing checks stay summary counts and failures stay in `
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
...(result.
|
|
150
|
-
|
|
151
|
-
resolutionOnlyThreads: result.fix.resolutionOnlyThreads,
|
|
145
|
+
// Passing checks stay summary counts and failures stay in `triage.checks`, as in lean text.
|
|
146
|
+
triage: {
|
|
147
|
+
...(result.triage.threads.length > 0 && { threads: result.triage.threads }),
|
|
148
|
+
...(result.triage.resolutionOnlyThreads.length > 0 && {
|
|
149
|
+
resolutionOnlyThreads: result.triage.resolutionOnlyThreads,
|
|
152
150
|
}),
|
|
153
|
-
...(result.
|
|
154
|
-
actionableComments: result.
|
|
151
|
+
...(result.triage.actionableComments.length > 0 && {
|
|
152
|
+
actionableComments: result.triage.actionableComments,
|
|
155
153
|
}),
|
|
156
|
-
...(result.
|
|
157
|
-
reviewSummaryIds: result.
|
|
154
|
+
...(result.triage.reviewSummaryIds.length > 0 && {
|
|
155
|
+
reviewSummaryIds: result.triage.reviewSummaryIds,
|
|
158
156
|
}),
|
|
159
|
-
...(result.
|
|
160
|
-
firstLookSummaries: result.
|
|
157
|
+
...(result.triage.firstLookSummaries.length > 0 && {
|
|
158
|
+
firstLookSummaries: result.triage.firstLookSummaries,
|
|
161
159
|
}),
|
|
162
|
-
...(result.
|
|
163
|
-
editedSummaries: result.
|
|
160
|
+
...(result.triage.editedSummaries.length > 0 && {
|
|
161
|
+
editedSummaries: result.triage.editedSummaries,
|
|
164
162
|
}),
|
|
165
|
-
...(result.
|
|
166
|
-
surfacedApprovals: result.
|
|
163
|
+
...(result.triage.surfacedApprovals.length > 0 && {
|
|
164
|
+
surfacedApprovals: result.triage.surfacedApprovals,
|
|
167
165
|
}),
|
|
168
|
-
...(result.
|
|
169
|
-
firstLookThreads: result.
|
|
166
|
+
...(result.triage.firstLookThreads.length > 0 && {
|
|
167
|
+
firstLookThreads: result.triage.firstLookThreads,
|
|
170
168
|
}),
|
|
171
|
-
...(result.
|
|
172
|
-
firstLookComments: result.
|
|
169
|
+
...(result.triage.firstLookComments.length > 0 && {
|
|
170
|
+
firstLookComments: result.triage.firstLookComments,
|
|
173
171
|
}),
|
|
174
|
-
...(result.
|
|
175
|
-
|
|
172
|
+
...(result.triage.requeue && { requeue: result.triage.requeue }),
|
|
173
|
+
...(result.triage.queueRemovalAcknowledgment && {
|
|
174
|
+
queueRemovalAcknowledgment: result.triage.queueRemovalAcknowledgment,
|
|
176
175
|
}),
|
|
177
|
-
...(result.
|
|
178
|
-
|
|
176
|
+
...(result.triage.checks.length > 0 && { checks: result.triage.checks }),
|
|
177
|
+
...(result.triage.changesRequestedReviews.length > 0 && {
|
|
178
|
+
changesRequestedReviews: result.triage.changesRequestedReviews,
|
|
179
179
|
}),
|
|
180
|
-
|
|
181
|
-
...(result.
|
|
182
|
-
|
|
180
|
+
resolveCommand: result.triage.resolveCommand,
|
|
181
|
+
...(result.triage.resolveOnlyCommand && {
|
|
182
|
+
resolveOnlyCommand: result.triage.resolveOnlyCommand,
|
|
183
183
|
}),
|
|
184
|
-
...(result.
|
|
185
|
-
...(result.
|
|
186
|
-
|
|
187
|
-
}),
|
|
188
|
-
resolveCommand: result.fix.resolveCommand,
|
|
189
|
-
...(result.fix.resolveOnlyCommand && {
|
|
190
|
-
resolveOnlyCommand: result.fix.resolveOnlyCommand,
|
|
191
|
-
}),
|
|
192
|
-
...(result.fix.reviewItems && { reviewItems: result.fix.reviewItems }),
|
|
193
|
-
...(result.fix.instructions.length > 0 && {
|
|
194
|
-
instructions: result.fix.instructions,
|
|
184
|
+
...(result.triage.reviewItems && { reviewItems: result.triage.reviewItems }),
|
|
185
|
+
...(result.triage.instructions.length > 0 && {
|
|
186
|
+
instructions: result.triage.instructions,
|
|
195
187
|
}),
|
|
196
188
|
},
|
|
197
189
|
};
|
|
@@ -7,7 +7,7 @@ export function projectIterateVerbose(result, opts) {
|
|
|
7
7
|
const edited = result.editedComments && {
|
|
8
8
|
editedComments: projectEditedComments(result.editedComments),
|
|
9
9
|
};
|
|
10
|
-
if (result.action === "
|
|
10
|
+
if (result.action === "triage")
|
|
11
11
|
return { ...result, ...readyDelayOverride, ...edited };
|
|
12
12
|
const log = "log" in result && typeof result.log === "string" ? { log: adaptIterateLog(result.log) } : {};
|
|
13
13
|
// `cancel` has no instructions, so verbose JSON omits the field as verbose Markdown omits the section.
|
|
@@ -1,7 +1,4 @@
|
|
|
1
1
|
export function formatJournalResult(result) {
|
|
2
|
-
if (result.authorizationSkipped) {
|
|
3
|
-
return `Authorization denied or unverifiable — Shepherd Journal in PR #${result.prNumber} was not updated.`;
|
|
4
|
-
}
|
|
5
2
|
if (result.dryRun) {
|
|
6
3
|
const lines = ["Dry run — no body change written."];
|
|
7
4
|
if (result.previewBody !== undefined) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare function handleJournal(args: string[]
|
|
1
|
+
export declare function handleJournal(args: string[]): Promise<void>;
|
|
@@ -5,7 +5,8 @@ import { getFlag } from "./args.mjs";
|
|
|
5
5
|
import { parseCliPrReference, resolveParsedPrTarget } from "../pr-reference.mjs";
|
|
6
6
|
import { USAGE } from "./help.mjs";
|
|
7
7
|
import { formatJournalResult } from "./journal-formatter.mjs";
|
|
8
|
-
export async function handleJournal(args
|
|
8
|
+
export async function handleJournal(args) {
|
|
9
|
+
const command = "apply journal";
|
|
9
10
|
for (const a of args) {
|
|
10
11
|
if (!a.startsWith("--"))
|
|
11
12
|
continue;
|
|
@@ -33,15 +33,6 @@ export function formatMutateResult(result) {
|
|
|
33
33
|
pushIds(lines, "Resolved threads", result.resolvedThreads);
|
|
34
34
|
pushIds(lines, "Minimized comments", result.minimizedComments);
|
|
35
35
|
pushIds(lines, "Dismissed reviews", result.dismissedReviews);
|
|
36
|
-
pushIds(lines, "Skipped dismissals", result.skippedDismissals);
|
|
37
|
-
pushIds(lines, "Skipped human thread resolves", result.skippedHumanResolves);
|
|
38
|
-
pushIds(lines, "Skipped human minimizes", result.skippedHumanMinimizes);
|
|
39
|
-
pushIds(lines, "Skipped human review dismissals", result.skippedHumanDismissals);
|
|
40
|
-
pushIds(lines, "Skipped non-human/unknown thread replies", result.skippedNonHumanReplies);
|
|
41
|
-
pushIds(lines, "Authorization denied/unverifiable for thread replies", result.skippedUnauthorizedReplies);
|
|
42
|
-
pushIds(lines, "Authorization denied/unverifiable for thread resolves", result.skippedUnauthorizedResolves);
|
|
43
|
-
pushIds(lines, "Authorization denied/unverifiable for minimizes", result.skippedUnauthorizedMinimizes);
|
|
44
|
-
pushIds(lines, "Authorization denied/unverifiable for review dismissals", result.skippedUnauthorizedDismissals);
|
|
45
36
|
const rateLimit = formatRateLimit(result);
|
|
46
37
|
if (rateLimit)
|
|
47
38
|
lines.push(rateLimit);
|
|
@@ -1,7 +1,3 @@
|
|
|
1
1
|
import type { NextCheck } from "../types/next-check.mts";
|
|
2
|
-
/** ` · **pollMode** \`event\``, or nothing in poll mode. */
|
|
3
|
-
export declare function formatPollModeSegment(result: {
|
|
4
|
-
pollMode?: "event";
|
|
5
|
-
}): string;
|
|
6
2
|
/** The header line naming the next wake-up, or nothing when none applies. */
|
|
7
3
|
export declare function formatNextCheckLines(next: NextCheck | undefined): string[];
|
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
/** ` · **pollMode** \`event\``, or nothing in poll mode. */
|
|
2
|
-
export function formatPollModeSegment(result) {
|
|
3
|
-
return result.pollMode ? ` · **pollMode** \`${result.pollMode}\`` : "";
|
|
4
|
-
}
|
|
5
1
|
/** The header line naming the next wake-up, or nothing when none applies. */
|
|
6
2
|
export function formatNextCheckLines(next) {
|
|
7
3
|
if (!next)
|
|
@@ -1 +1,4 @@
|
|
|
1
|
+
/** The default command: one PR, or several PRs from one repository. */
|
|
1
2
|
export declare function handlePoll(args: string[]): Promise<void>;
|
|
3
|
+
/** `pr-shepherd stack <PR>`: the native stack containing one PR. */
|
|
4
|
+
export declare function handleStack(args: string[]): Promise<void>;
|
package/bin/cli/poll-handler.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { runAggregatePollCommand, runPollCommand, runPollSummaryTick } from "../commands/tick.mjs";
|
|
2
2
|
import { loadConfig } from "../config/load.mjs";
|
|
3
3
|
import { parseCommonArgs, getFlag, hasFlag } from "./args.mjs";
|
|
4
4
|
import { parseDurationToSeconds } from "./duration.mjs";
|
|
@@ -8,41 +8,88 @@ import { emitIterateResult } from "./iterate-emitter.mjs";
|
|
|
8
8
|
import { EXIT } from "../exit-codes.mjs";
|
|
9
9
|
import { emitPollSummaryResult } from "./poll-summary-emitter.mjs";
|
|
10
10
|
import { parsePollTargets, resolvePollTargets } from "./poll-targets.mjs";
|
|
11
|
+
import { DEFAULT_POLL_BOOLEAN_FLAGS, DEFAULT_POLL_FLAGS_WITH_VALUES } from "./default-poll.mjs";
|
|
12
|
+
import { validateDefaultArgs } from "./validate-default-args.mjs";
|
|
13
|
+
import { rejectRemovedFlags } from "./removed-flags.mjs";
|
|
14
|
+
import { rejectUnknownFlags } from "./unknown-flags.mjs";
|
|
15
|
+
import { maybePrintHelp, USAGE } from "./help.mjs";
|
|
16
|
+
/** The default command: one PR, or several PRs from one repository. */
|
|
11
17
|
export async function handlePoll(args) {
|
|
12
18
|
const parsedTargets = parsePollTargets(args);
|
|
13
19
|
if (!parsedTargets)
|
|
14
20
|
return;
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
const resolvedTargets = parsedTargets.refs.length > 1 ? await resolvePollTargets(parsedTargets) : { prNumbers: [] };
|
|
22
|
+
// Duplicate references collapse to one PR, which takes the single-PR iterator.
|
|
23
|
+
if (resolvedTargets.prNumbers.length > 1) {
|
|
24
|
+
const shared = parseLoopOptions(parsedTargets.extra, parsedTargets.global, true);
|
|
25
|
+
if (!shared)
|
|
26
|
+
return;
|
|
27
|
+
const result = await runAggregatePollCommand({ ...shared.options, ...resolvedTargets });
|
|
28
|
+
emitPollSummaryResult(result, { format: parsedTargets.global.format });
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const { prNumber, global: globalOpts, extra } = parseCommonArgs(args);
|
|
32
|
+
const shared = parseLoopOptions(extra, globalOpts, false);
|
|
33
|
+
if (!shared)
|
|
34
|
+
return;
|
|
35
|
+
const result = await runPollCommand({ ...shared.options, prNumber });
|
|
36
|
+
emitIterateResult(result, {
|
|
37
|
+
format: globalOpts.format,
|
|
38
|
+
verbose: globalOpts.verbose ?? false,
|
|
39
|
+
readyDelaySuffix: shared.readyDelaySuffix,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
/** `pr-shepherd stack <PR>`: the native stack containing one PR. */
|
|
43
|
+
export async function handleStack(args) {
|
|
44
|
+
if (maybePrintHelp(args, "stack"))
|
|
45
|
+
return;
|
|
46
|
+
if (rejectRemovedFlags(args) || rejectUnknownFlags(args, "stack", STACK_FLAGS))
|
|
47
|
+
return;
|
|
48
|
+
if (!validateDefaultArgs(args, DEFAULT_POLL_FLAGS_WITH_VALUES, STACK_BOOLEAN_FLAGS, usageArg))
|
|
49
|
+
return;
|
|
50
|
+
const parsedTargets = parsePollTargets(args);
|
|
51
|
+
if (!parsedTargets)
|
|
52
|
+
return;
|
|
53
|
+
if (parsedTargets.refs.length !== 1) {
|
|
54
|
+
usage("stack requires exactly one PR reference.");
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const { prNumbers, targetRepository } = await resolvePollTargets(parsedTargets);
|
|
58
|
+
const shared = parseLoopOptions(parsedTargets.extra, parsedTargets.global, true);
|
|
59
|
+
if (!shared)
|
|
60
|
+
return;
|
|
61
|
+
const target = { stackPrNumber: prNumbers[0], targetRepository };
|
|
62
|
+
const result = hasFlag(parsedTargets.extra, "--once")
|
|
63
|
+
? await runPollSummaryTick({ ...shared.options, ...target })
|
|
64
|
+
: await runAggregatePollCommand({ ...shared.options, ...target });
|
|
65
|
+
emitPollSummaryResult(result, { format: parsedTargets.global.format });
|
|
66
|
+
}
|
|
67
|
+
const STACK_BOOLEAN_FLAGS = new Set([...DEFAULT_POLL_BOOLEAN_FLAGS, "--once"]);
|
|
68
|
+
const STACK_FLAGS = [...DEFAULT_POLL_FLAGS_WITH_VALUES, ...STACK_BOOLEAN_FLAGS];
|
|
69
|
+
function parseLoopOptions(extra, globalOpts, isAggregate) {
|
|
23
70
|
const cfg = loadConfig();
|
|
24
71
|
const flags = parseIterateFlags(extra, cfg);
|
|
25
72
|
if (hasInvalidIterateFlags(flags))
|
|
26
|
-
return;
|
|
73
|
+
return null;
|
|
27
74
|
const intervalStr = getFlag(extra, "--interval");
|
|
28
75
|
const intervalSuffix = validateSecondsDurationFlag("pr-shepherd", "--interval", intervalStr, hasFlag(extra, "--interval"));
|
|
29
76
|
if (intervalSuffix === null)
|
|
30
|
-
return;
|
|
31
|
-
let intervalSeconds = parseDurationToSeconds(intervalSuffix ?? "", cfg.poll
|
|
77
|
+
return null;
|
|
78
|
+
let intervalSeconds = parseDurationToSeconds(intervalSuffix ?? "", cfg.poll["interval-seconds"]);
|
|
32
79
|
// `--interval` is the invocation interval. Only an omitted flag is scaled, and only for aggregates.
|
|
33
80
|
if (isAggregate && intervalSuffix === undefined) {
|
|
34
|
-
intervalSeconds *= cfg.poll
|
|
81
|
+
intervalSeconds *= cfg.poll["stack-interval-factor"];
|
|
35
82
|
}
|
|
36
83
|
const timeoutStr = getFlag(extra, "--timeout");
|
|
37
84
|
const timeoutSuffix = validateSecondsDurationFlag("pr-shepherd", "--timeout", timeoutStr, hasFlag(extra, "--timeout"));
|
|
38
85
|
if (timeoutSuffix === null)
|
|
39
|
-
return;
|
|
40
|
-
const timeoutSeconds = parseDurationToSeconds(timeoutSuffix ?? "", cfg.poll
|
|
86
|
+
return null;
|
|
87
|
+
const timeoutSeconds = parseDurationToSeconds(timeoutSuffix ?? "", cfg.poll["timeout-seconds"]);
|
|
41
88
|
const debounceStr = getFlag(extra, "--debounce");
|
|
42
89
|
const debounceSuffix = validateSecondsDurationFlag("pr-shepherd", "--debounce", debounceStr, hasFlag(extra, "--debounce"), { allowZero: true });
|
|
43
90
|
if (debounceSuffix === null)
|
|
44
|
-
return;
|
|
45
|
-
const debounceSeconds = parseDurationToSeconds(debounceSuffix ?? "", cfg.poll
|
|
91
|
+
return null;
|
|
92
|
+
const debounceSeconds = parseDurationToSeconds(debounceSuffix ?? "", cfg.poll["debounce-seconds"], {
|
|
46
93
|
allowZero: true,
|
|
47
94
|
});
|
|
48
95
|
const quietStatusFlag = hasFlag(extra, "--quiet-status");
|
|
@@ -50,36 +97,30 @@ export async function handlePoll(args) {
|
|
|
50
97
|
if (quietStatusFlag && noQuietStatusFlag) {
|
|
51
98
|
process.stderr.write("pr-shepherd: --quiet-status and --no-quiet-status cannot be used together\n");
|
|
52
99
|
process.exitCode = EXIT.USAGE;
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
|
-
const quietStatus = quietStatusFlag || (!noQuietStatusFlag && cfg.poll.quietStatus);
|
|
56
|
-
const shared = {
|
|
57
|
-
...globalOpts,
|
|
58
|
-
readyDelaySeconds: flags.readyDelaySeconds,
|
|
59
|
-
stallTimeoutSeconds: flags.stallTimeoutSeconds,
|
|
60
|
-
noAutoMarkReady: flags.noAutoMarkReady,
|
|
61
|
-
noAutoCancelActionable: flags.noAutoCancelActionable,
|
|
62
|
-
merge: flags.merge,
|
|
63
|
-
instructions: flags.instructions ?? undefined,
|
|
64
|
-
pollMode: flags.pollMode ?? undefined,
|
|
65
|
-
intervalSeconds,
|
|
66
|
-
timeoutSeconds,
|
|
67
|
-
debounceSeconds,
|
|
68
|
-
quietStatus,
|
|
69
|
-
untilTerminal: hasFlag(extra, "--until-terminal"),
|
|
70
|
-
};
|
|
71
|
-
if (isAggregate) {
|
|
72
|
-
const result = await runAggregatePollForMode({
|
|
73
|
-
...shared,
|
|
74
|
-
...resolvedTargets,
|
|
75
|
-
});
|
|
76
|
-
emitPollSummaryResult(result, { format: globalOpts.format });
|
|
77
|
-
return;
|
|
100
|
+
return null;
|
|
78
101
|
}
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
format: globalOpts.format,
|
|
82
|
-
verbose: globalOpts.verbose ?? false,
|
|
102
|
+
const quietStatus = quietStatusFlag || (!noQuietStatusFlag && cfg.poll["quiet-status"]);
|
|
103
|
+
return {
|
|
83
104
|
readyDelaySuffix: flags.readyDelaySuffix ?? undefined,
|
|
84
|
-
|
|
105
|
+
options: {
|
|
106
|
+
...globalOpts,
|
|
107
|
+
readyDelaySeconds: flags.readyDelaySeconds,
|
|
108
|
+
stallTimeoutSeconds: flags.stallTimeoutSeconds,
|
|
109
|
+
noAutoMarkReady: flags.noAutoMarkReady,
|
|
110
|
+
merge: flags.merge,
|
|
111
|
+
instructions: flags.instructions ?? undefined,
|
|
112
|
+
intervalSeconds,
|
|
113
|
+
timeoutSeconds,
|
|
114
|
+
debounceSeconds,
|
|
115
|
+
quietStatus,
|
|
116
|
+
untilTerminal: hasFlag(extra, "--until-terminal"),
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
function usageArg(arg) {
|
|
121
|
+
usage(`unexpected argument: "${arg}"`);
|
|
122
|
+
}
|
|
123
|
+
function usage(message) {
|
|
124
|
+
process.stderr.write(`pr-shepherd: stack: ${message}\n${USAGE.stack}\n`);
|
|
125
|
+
process.exitCode = EXIT.USAGE;
|
|
85
126
|
}
|
|
@@ -25,8 +25,8 @@ function pollSummaryExitCode(result) {
|
|
|
25
25
|
const actions = new Set(result.prs.map((item) => item.action));
|
|
26
26
|
if (actions.has("escalate"))
|
|
27
27
|
return EXIT.ESCALATE;
|
|
28
|
-
if (actions.has("
|
|
29
|
-
return EXIT.
|
|
28
|
+
if (actions.has("triage"))
|
|
29
|
+
return EXIT.TRIAGE;
|
|
30
30
|
if (actions.has("merge"))
|
|
31
31
|
return EXIT.MERGE;
|
|
32
32
|
if (actions.has("mark_ready"))
|
|
@@ -2,7 +2,7 @@ import { formatApiUsage, formatQuotaWarning } from "./api-usage-formatter.mjs";
|
|
|
2
2
|
import { withPollSummaryInstructions } from "../commands/poll-summary-instructions.mjs";
|
|
3
3
|
import { formatStackOverview, projectStackOverview } from "./stack-overview.mjs";
|
|
4
4
|
import { formatTransportEvidence } from "./transport-formatter.mjs";
|
|
5
|
-
import { formatNextCheckLines
|
|
5
|
+
import { formatNextCheckLines } from "./next-check-format.mjs";
|
|
6
6
|
export function formatPollSummaryResult(result) {
|
|
7
7
|
if (result.selection.kind === "stack")
|
|
8
8
|
return formatStackOverview(projectStackOverview(result));
|
|
@@ -10,7 +10,7 @@ export function formatPollSummaryResult(result) {
|
|
|
10
10
|
const lines = [
|
|
11
11
|
`# Poll summary [${result.reason.toUpperCase()}]`,
|
|
12
12
|
"",
|
|
13
|
-
`**repo** \`${result.repo}\` · **selection** ${selection} · **mode** \`${result.mode}\`${
|
|
13
|
+
`**repo** \`${result.repo}\` · **selection** ${selection} · **mode** \`${result.mode}\`${result.stackMergeable !== undefined ? ` · **stack mergeable** \`${result.stackMergeable}\`` : ""}${result.nextAction ? ` · **next action** \`${result.nextAction}\`` : ""}`,
|
|
14
14
|
...formatNextCheckLines(result.nextCheck),
|
|
15
15
|
"",
|
|
16
16
|
"## Pull requests",
|
|
@@ -3,13 +3,13 @@ import { type ParsedPrReference } from "../pr-reference.mts";
|
|
|
3
3
|
import type { GlobalOptions } from "../types.mts";
|
|
4
4
|
export interface ParsedPollTargets {
|
|
5
5
|
refs: ParsedPrReference[];
|
|
6
|
-
stack: ParsedPrReference | undefined;
|
|
7
6
|
global: GlobalOptions;
|
|
8
7
|
extra: string[];
|
|
9
8
|
}
|
|
9
|
+
/** Splits PR references from flags. Returns null after printing a usage error. */
|
|
10
10
|
export declare function parsePollTargets(args: string[]): ParsedPollTargets | null;
|
|
11
|
+
/** Resolves PR references that must all name one repository. */
|
|
11
12
|
export declare function resolvePollTargets(parsed: ParsedPollTargets): Promise<{
|
|
12
13
|
prNumbers: number[];
|
|
13
|
-
stackPrNumber?: number;
|
|
14
14
|
targetRepository?: RepoInfo;
|
|
15
15
|
}>;
|