pr-shepherd 0.42.0 → 0.43.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +8 -3
- package/bin/checks/classify.d.mts +3 -1
- package/bin/checks/classify.mjs +5 -2
- package/bin/cli/args.mjs +1 -0
- package/bin/cli/default-poll.mjs +1 -0
- package/bin/cli/fix-formatter.mjs +12 -2
- package/bin/cli/handlers.mjs +1 -0
- package/bin/cli/help-command-pages.d.mts +2 -2
- package/bin/cli/help-iterate-poll-pages.d.mts +2 -2
- package/bin/cli/help-iterate-poll-pages.mjs +7 -2
- package/bin/cli/help.d.mts +2 -2
- package/bin/cli/iterate-flags.d.mts +1 -0
- package/bin/cli/iterate-flags.mjs +2 -0
- package/bin/cli/iterate-formatter.mjs +4 -1
- package/bin/cli/iterate-instructions.mjs +15 -0
- package/bin/cli/iterate-lean.d.mts +1 -2
- package/bin/cli/iterate-lean.mjs +12 -17
- package/bin/cli/iterate-merge-formatter.d.mts +3 -0
- package/bin/cli/iterate-merge-formatter.mjs +52 -0
- package/bin/cli/iterate-verbose.d.mts +6 -0
- package/bin/cli/iterate-verbose.mjs +14 -0
- package/bin/cli/poll-handler.mjs +1 -0
- package/bin/cli/runner.mjs +4 -3
- package/bin/commands/check-terminal-report.mjs +1 -0
- package/bin/commands/check.mjs +42 -1
- package/bin/commands/iterate/base.d.mts +5 -0
- package/bin/commands/iterate/base.mjs +25 -0
- package/bin/commands/iterate/escalate.d.mts +3 -1
- package/bin/commands/iterate/escalate.mjs +18 -2
- package/bin/commands/iterate/fix-code.mjs +16 -0
- package/bin/commands/iterate/helpers.mjs +6 -2
- package/bin/commands/iterate/index.mjs +29 -35
- package/bin/commands/iterate/merge-state.d.mts +15 -0
- package/bin/commands/iterate/merge-state.mjs +53 -0
- package/bin/commands/iterate/merge.d.mts +13 -0
- package/bin/commands/iterate/merge.mjs +46 -0
- package/bin/commands/poll.mjs +3 -1
- package/bin/config/load.d.mts +4 -0
- package/bin/config/load.mjs +34 -0
- package/bin/config/merge-command-args.d.mts +2 -0
- package/bin/config/merge-command-args.mjs +44 -0
- package/bin/config.json +3 -0
- package/bin/exit-codes.d.mts +2 -0
- package/bin/exit-codes.mjs +4 -0
- package/bin/github/batch-parse-checks.d.mts +3 -0
- package/bin/github/batch-parse-checks.mjs +29 -0
- package/bin/github/batch-parsers-rules.d.mts +3 -1
- package/bin/github/batch-parsers-rules.mjs +33 -0
- package/bin/github/batch-parsers.mjs +23 -26
- package/bin/github/batch-raw-rules.d.mts +48 -0
- package/bin/github/batch-raw-types.mjs +0 -1
- package/bin/github/batch.mjs +2 -0
- package/bin/github/gql/batch-pr.gql +92 -0
- package/bin/github/gql/commit-check-contexts.gql +58 -0
- package/bin/github/merge-queue-checks.d.mts +4 -0
- package/bin/github/merge-queue-checks.mjs +48 -0
- package/bin/github/queries.d.mts +2 -0
- package/bin/github/queries.mjs +2 -0
- package/bin/mcp/server.mjs +1 -0
- package/bin/reporters/agent.mjs +6 -3
- package/bin/types/activity.d.mts +2 -0
- package/bin/types/escalate.d.mts +30 -0
- package/bin/types/escalate.mjs +1 -0
- package/bin/types/github.d.mts +8 -0
- package/bin/types/github.mjs +0 -3
- package/bin/types/iterate.d.mts +14 -31
- package/bin/types/merge-action.d.mts +12 -0
- package/bin/types/merge-action.mjs +1 -0
- package/bin/types/merge-queue.d.mts +13 -0
- package/bin/types/merge-queue.mjs +1 -0
- package/bin/types/merge-requirements.d.mts +17 -0
- package/bin/types/report.d.mts +8 -0
- package/bin/types.d.mts +3 -0
- package/bin/types.mjs +3 -0
- package/bin/util/markdown.d.mts +2 -0
- package/bin/util/markdown.mjs +7 -0
- package/package.json +1 -1
- package/plugins/pr-shepherd/.codex-plugin/plugin.json +1 -1
- package/plugins/pr-shepherd/.codex.mcp.json +1 -1
- package/plugins/pr-shepherd/.mcp.json +1 -1
- package/plugins/pr-shepherd/skills/pr-shepherd/SKILL.md +3 -3
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@ 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
|
|
12
|
+
2. **Provide deterministic actions for the agent**: exactly one of `WAIT`, `MARK_READY`, `FIX_CODE`, `MERGE`, `CANCEL`, or `ESCALATE`, plus numbered `## Instructions` and explicit commands. 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
|
|
|
@@ -32,6 +32,7 @@ Each tick returns exactly one action:
|
|
|
32
32
|
- `WAIT` — no immediate action; continue with the next poll.
|
|
33
33
|
- `MARK_READY` — the CLI converted an eligible draft PR to ready; continue polling.
|
|
34
34
|
- `FIX_CODE` — agent work is required; complete it, then continue polling.
|
|
35
|
+
- `MERGE` — run the emitted auto-merge or merge-queue command, then continue polling.
|
|
35
36
|
- `CANCEL` — stop polling because the PR merged, closed, or completed its ready-delay.
|
|
36
37
|
- `ESCALATE` — stop polling until a human provides direction.
|
|
37
38
|
|
|
@@ -76,7 +77,7 @@ Conversations Resolved: No [Not Required]
|
|
|
76
77
|
9. `[FIX_CODE]` is non-terminal. After completing these steps, iterate again with the same options to continue.
|
|
77
78
|
```
|
|
78
79
|
|
|
79
|
-
See [docs/actions.md](docs/actions.md) for the complete output contract. Iterate/poll PR outcomes use exit codes `0` and `10`–`
|
|
80
|
+
See [docs/actions.md](docs/actions.md) for the complete output contract. Iterate/poll PR outcomes use exit codes `0` and `10`–`15`; command and GitHub failures use `sysexits.h` codes — [docs/exit-codes.md](docs/exit-codes.md).
|
|
80
81
|
|
|
81
82
|
## Workflow Assumptions
|
|
82
83
|
|
|
@@ -126,6 +127,7 @@ pr-shepherd 42 --quiet-status # print only changed WAIT status snapshot
|
|
|
126
127
|
pr-shepherd 42 --until-terminal # continue through WAIT/MARK_READY until work or terminal state
|
|
127
128
|
pr-shepherd 42 --debounce 5m # wait 5m after first FIX_CODE, then return one batched tick
|
|
128
129
|
pr-shepherd 42 --ready-delay 15m
|
|
130
|
+
pr-shepherd 42 --merge # enable auto-merge or enter an enabled/required merge queue when ready
|
|
129
131
|
pr-shepherd iterate 42 # single tick
|
|
130
132
|
```
|
|
131
133
|
|
|
@@ -236,7 +238,10 @@ checks:
|
|
|
236
238
|
ciTriggerEvents:
|
|
237
239
|
- pull_request
|
|
238
240
|
- pull_request_target
|
|
239
|
-
|
|
241
|
+
merge:
|
|
242
|
+
commandArgs:
|
|
243
|
+
- --squash
|
|
244
|
+
- --delete-branch
|
|
240
245
|
actions:
|
|
241
246
|
autoMinimizeSuppressed: true
|
|
242
247
|
autoMarkReady: false
|
|
@@ -20,7 +20,9 @@ import type { CheckRun, ClassifiedCheck } from "../types.mts";
|
|
|
20
20
|
* @param checks Raw check runs from the batch query.
|
|
21
21
|
* @returns Classified checks. "filtered" items were excluded from the tally.
|
|
22
22
|
*/
|
|
23
|
-
export declare function classifyChecks(checks: CheckRun[]
|
|
23
|
+
export declare function classifyChecks(checks: CheckRun[], opts?: {
|
|
24
|
+
additionalRelevantEvents?: string[];
|
|
25
|
+
}): ClassifiedCheck[];
|
|
24
26
|
export interface CiVerdict {
|
|
25
27
|
/** True when all relevant (non-filtered, non-skipped, non-ignored) checks passed. */
|
|
26
28
|
allPassed: boolean;
|
package/bin/checks/classify.mjs
CHANGED
|
@@ -22,9 +22,12 @@ import picomatch from "picomatch";
|
|
|
22
22
|
* @param checks Raw check runs from the batch query.
|
|
23
23
|
* @returns Classified checks. "filtered" items were excluded from the tally.
|
|
24
24
|
*/
|
|
25
|
-
export function classifyChecks(checks) {
|
|
25
|
+
export function classifyChecks(checks, opts = {}) {
|
|
26
26
|
const config = loadConfig();
|
|
27
|
-
const relevantEvents = new Set(
|
|
27
|
+
const relevantEvents = new Set([
|
|
28
|
+
...config.checks.ciTriggerEvents,
|
|
29
|
+
...(opts.additionalRelevantEvents ?? []),
|
|
30
|
+
]);
|
|
28
31
|
const isIgnored = buildMatcher(config.ignoreChecks ?? []);
|
|
29
32
|
const isProtected = buildMatcher(config.actions.neverCancelRuns ?? []);
|
|
30
33
|
const protectedRunIds = buildProtectedRunIds(checks, isProtected);
|
package/bin/cli/args.mjs
CHANGED
package/bin/cli/default-poll.mjs
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { renderResolveCommand } from "../commands/iterate/render.mjs";
|
|
2
|
-
import { joinSections } from "../util/markdown.mjs";
|
|
2
|
+
import { inlineCode, joinSections } from "../util/markdown.mjs";
|
|
3
3
|
import { renderSuggestionBlock, renderLineRange } from "./suggestion-renderer.mjs";
|
|
4
4
|
import { renderThreadBullet, renderReviewBullet, renderThreadResolutionStatusTag, renderAuthor, buildFirstLookBullets, renderThreadConversation, blockquote, } from "./list-formatters.mjs";
|
|
5
5
|
import { numberInstructions } from "./iterate-instructions.mjs";
|
|
6
6
|
import { renderCheckAnnotation, renderProtectedRun } from "./fix-formatter-extra.mjs";
|
|
7
7
|
import { isFailingAgentCheck } from "../checks/conclusions.mjs";
|
|
8
|
+
import { renderMergeCommand } from "../commands/iterate/merge.mjs";
|
|
8
9
|
export function formatFixCodeResult(header, result) {
|
|
9
10
|
const sections = [header];
|
|
10
11
|
if (result.fix.threads.length > 0) {
|
|
@@ -50,7 +51,10 @@ export function formatFixCodeResult(header, result) {
|
|
|
50
51
|
? `external \`${ch.detailsUrl}\``
|
|
51
52
|
: "(no runId)";
|
|
52
53
|
const conclusionTag = ch.conclusion !== null ? ` [conclusion: ${ch.conclusion}]` : "";
|
|
53
|
-
const
|
|
54
|
+
const scopeTag = ch.scope
|
|
55
|
+
? ` [scope: ${ch.scope}${ch.commitOid ? `, commit: ${ch.commitOid}` : ""}]`
|
|
56
|
+
: "";
|
|
57
|
+
const lines = [`- ${locator} — \`${workflowPrefix}${jobLabel}\`${conclusionTag}${scopeTag}`];
|
|
54
58
|
if (ch.conclusion !== "CANCELLED") {
|
|
55
59
|
if (ch.failedStep)
|
|
56
60
|
lines.push(` > ${ch.failedStep}`);
|
|
@@ -133,6 +137,12 @@ export function formatFixCodeResult(header, result) {
|
|
|
133
137
|
if (result.fix.resolveCommand.hasMutations) {
|
|
134
138
|
postFixLines.push(`- apply review: \`${renderResolveCommand(result.fix.resolveCommand)}\``);
|
|
135
139
|
}
|
|
140
|
+
if (result.fix.requeue) {
|
|
141
|
+
postFixLines.push(`- requeue: ${inlineCode(renderMergeCommand(result.fix.requeue.command))}`);
|
|
142
|
+
if (result.fix.requeue.queueApiFallbackCommand) {
|
|
143
|
+
postFixLines.push(`- requeue API fallback: ${inlineCode(renderMergeCommand(result.fix.requeue.queueApiFallbackCommand))}`);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
136
146
|
sections.push(postFixLines.join("\n"));
|
|
137
147
|
sections.push("## Instructions");
|
|
138
148
|
sections.push(numberInstructions(result.fix.instructions));
|
package/bin/cli/handlers.mjs
CHANGED
|
@@ -124,6 +124,7 @@ export async function handleIterate(args) {
|
|
|
124
124
|
stallTimeoutSeconds: flags.stallTimeoutSeconds,
|
|
125
125
|
noAutoMarkReady: flags.noAutoMarkReady,
|
|
126
126
|
noAutoCancelActionable: flags.noAutoCancelActionable,
|
|
127
|
+
merge: flags.merge,
|
|
127
128
|
});
|
|
128
129
|
emitIterateResult(result, {
|
|
129
130
|
format: globalOpts.format,
|
|
@@ -192,8 +192,8 @@ Flags:
|
|
|
192
192
|
|
|
193
193
|
PR may be a number or GitHub pull request URL. When omitted, the current branch PR is inferred.
|
|
194
194
|
Exit code: 0 on success; nonzero on failure (sysexits.h — see docs/exit-codes.md).`;
|
|
195
|
-
readonly iterate: "pr-shepherd iterate\n\nRun one iterate tick for a pull request. The no-subcommand form polls; use this subcommand for a single tick.\nThe output contains one action and an action-specific ## Instructions section.\n\nUsage:\n pr-shepherd iterate [PR] [iterate-flags]\n\nIterate flags:\n --ready-delay <duration> Settle window before a clean PR cancels. Bare number = minutes. Example: 15m.\n --stall-timeout <duration> Escalate repeated unchanged failures after this duration. Bare number = minutes. 0 disables.\n --no-auto-mark-ready Do not convert draft PRs to ready for review.\n --no-auto-cancel-actionable Do not cancel in-progress runs before actionable fixes.\n --format text|json Output Markdown text or JSON. Default: text.\n --verbose Include verbose iterate fields.\n --help, -h Print this help and exit before GitHub, git, config, or log I/O.\n\nDurations accept s/m/h suffixes: 30s, 4.5m, 1h. A bare number is minutes; decimals are allowed only with an explicit unit (4.5m).\n\nActions:\n WAIT No immediate action; continue with the next poll.\n MARK_READY Draft PR was marked ready; continue with the next poll.\n FIX_CODE Agent action is required; follow the instructions, then continue polling.\n CANCEL Stop polling: merged/closed or ready-delay elapsed.\n ESCALATE Stop polling until a human provides direction.\n\nExit codes:\n 0 CANCEL (merged or ready-delay elapsed)\n 10 WAIT\n 11 MARK_READY\n 12 FIX_CODE\n 13 ESCALATE\n 14 CANCEL (closed without merging)\n A command/validation/GitHub failure exits with a sysexits.h code instead (see docs/exit-codes.md).";
|
|
196
|
-
readonly poll: "pr-shepherd poll\n\nRun iterate repeatedly for WAIT ticks and during the FIX_CODE debounce window. Print only the\nfinal tick to stdout.\nPoll exits as soon as iterate returns MARK_READY, CANCEL, or ESCALATE, or when timeout\nreturns the last WAIT result. FIX_CODE starts a --debounce settle window (default 1m): poll keeps\niterating at --interval, then runs one more tick after the window and returns that result.\nWith --until-terminal, poll also continues through MARK_READY.\n\nUsage:\n pr-shepherd poll [PR] [poll-flags] [iterate-flags]\n\nPoll flags:\n --interval <duration> Sleep between WAIT ticks. Bare number = seconds. Default: 60s.\n --timeout <duration> Maximum wall-clock wait for WAIT ticks. Bare number = seconds. Default: 4.5m.\n --debounce <duration> Settle window after first FIX_CODE before returning. Bare number = seconds. Default: 60s. 0 disables.\n --quiet-status During WAIT polling, print only changed status snapshots.\n --until-terminal Continue through WAIT/MARK_READY until FIX_CODE/CANCEL/ESCALATE.\n\nForwarded iterate flags:\n --ready-delay <duration> Settle window before a clean PR cancels. Bare number = minutes. Example: 15m.\n --stall-timeout <duration> Escalate repeated unchanged failures after this duration. Bare number = minutes. 0 disables.\n --no-auto-mark-ready Do not convert draft PRs to ready for review.\n --no-auto-cancel-actionable Do not cancel in-progress runs before actionable fixes.\n --format text|json Output Markdown text or JSON. Default: text.\n --verbose Include verbose iterate fields and detailed per-tick lines.\n --help, -h Print this help and exit before GitHub, git, config, or log I/O.\n\nDurations accept s/m/h suffixes: 30s, 4.5m, 1h. A bare number uses each flag's default unit (seconds\nfor --interval/--timeout/--debounce, minutes for --ready-delay/--stall-timeout); decimals are allowed only with\nan explicit unit (4.5m).\nEach WAIT tick writes an explicit still-running line to stderr by default; --quiet-status prints only changed WAIT snapshots, and --verbose emits detailed per-tick lines.\nFIX_CODE debounce writes a remaining-seconds line to stderr. --timeout does not cut an in-flight debounce short.\nWith --until-terminal, --timeout is ignored for WAIT ticks and polling continues until FIX_CODE, CANCEL, or ESCALATE.\n\nExit codes: same as iterate (the final tick's action/reason decides the code).\n 0 CANCEL (merged or ready-delay elapsed)\n 10 WAIT (including a WAIT returned by --timeout)\n 11 MARK_READY\n 12 FIX_CODE\n 13 ESCALATE\n 14 CANCEL (closed without merging)\n A command/validation/GitHub failure exits with a sysexits.h code instead (see docs/exit-codes.md).";
|
|
195
|
+
readonly iterate: "pr-shepherd iterate\n\nRun one iterate tick for a pull request. The no-subcommand form polls; use this subcommand for a single tick.\nThe output contains one action and an action-specific ## Instructions section.\n\nUsage:\n pr-shepherd iterate [PR] [iterate-flags]\n\nIterate flags:\n --ready-delay <duration> Settle window before a clean PR cancels. Bare number = minutes. Example: 15m.\n --stall-timeout <duration> Escalate repeated unchanged failures after this duration. Bare number = minutes. 0 disables.\n --no-auto-mark-ready Do not convert draft PRs to ready for review.\n --no-auto-cancel-actionable Do not cancel in-progress runs before actionable fixes.\n --merge Shepherd through readiness, then emit a merge or merge-queue command.\n --format text|json Output Markdown text or JSON. Default: text.\n --verbose Include verbose iterate fields.\n --help, -h Print this help and exit before GitHub, git, config, or log I/O.\n\nDurations accept s/m/h suffixes: 30s, 4.5m, 1h. A bare number is minutes; decimals are allowed only with an explicit unit (4.5m).\n\nActions:\n WAIT No immediate action; continue with the next poll.\n MARK_READY Draft PR was marked ready; continue with the next poll.\n FIX_CODE Agent action is required; follow the instructions, then continue polling.\n CANCEL Stop polling: merged/closed or ready-delay elapsed.\n ESCALATE Stop polling until a human provides direction.\n MERGE Run the emitted merge/queue command, then continue monitoring.\n\nExit codes:\n 0 CANCEL (merged or ready-delay elapsed)\n 10 WAIT\n 11 MARK_READY\n 12 FIX_CODE\n 13 ESCALATE\n 14 CANCEL (closed without merging)\n 15 MERGE\n A command/validation/GitHub failure exits with a sysexits.h code instead (see docs/exit-codes.md).";
|
|
196
|
+
readonly poll: "pr-shepherd poll\n\nRun iterate repeatedly for WAIT ticks and during the FIX_CODE debounce window. Print only the\nfinal tick to stdout.\nPoll exits as soon as iterate returns MARK_READY, CANCEL, or ESCALATE, or when timeout\nreturns the last WAIT result. FIX_CODE starts a --debounce settle window (default 1m): poll keeps\niterating at --interval, then runs one more tick after the window and returns that result.\nWith --until-terminal or --merge, poll also continues through MARK_READY.\n\nUsage:\n pr-shepherd poll [PR] [poll-flags] [iterate-flags]\n\nPoll flags:\n --interval <duration> Sleep between WAIT ticks. Bare number = seconds. Default: 60s.\n --timeout <duration> Maximum wall-clock wait for WAIT ticks. Bare number = seconds. Default: 4.5m.\n --debounce <duration> Settle window after first FIX_CODE before returning. Bare number = seconds. Default: 60s. 0 disables.\n --quiet-status During WAIT polling, print only changed status snapshots.\n --until-terminal Continue through WAIT/MARK_READY until FIX_CODE/CANCEL/ESCALATE.\n\nForwarded iterate flags:\n --ready-delay <duration> Settle window before a clean PR cancels. Bare number = minutes. Example: 15m.\n --stall-timeout <duration> Escalate repeated unchanged failures after this duration. Bare number = minutes. 0 disables.\n --no-auto-mark-ready Do not convert draft PRs to ready for review.\n --no-auto-cancel-actionable Do not cancel in-progress runs before actionable fixes.\n --merge Shepherd through readiness, then emit a merge or merge-queue command.\n --format text|json Output Markdown text or JSON. Default: text.\n --verbose Include verbose iterate fields and detailed per-tick lines.\n --help, -h Print this help and exit before GitHub, git, config, or log I/O.\n\nDurations accept s/m/h suffixes: 30s, 4.5m, 1h. A bare number uses each flag's default unit (seconds\nfor --interval/--timeout/--debounce, minutes for --ready-delay/--stall-timeout); decimals are allowed only with\nan explicit unit (4.5m).\nEach WAIT tick writes an explicit still-running line to stderr by default; --quiet-status prints only changed WAIT snapshots, and --verbose emits detailed per-tick lines.\nFIX_CODE debounce writes a remaining-seconds line to stderr. --timeout does not cut an in-flight debounce short.\nWith --until-terminal, --timeout is ignored for WAIT ticks and polling continues until FIX_CODE, MERGE, CANCEL, or ESCALATE. With --merge, --timeout still bounds WAIT ticks; it only continues through MARK_READY while polling remains within that timeout.\n\nExit codes: same as iterate (the final tick's action/reason decides the code).\n 0 CANCEL (merged or ready-delay elapsed)\n 10 WAIT (including a WAIT returned by --timeout)\n 11 MARK_READY\n 12 FIX_CODE\n 13 ESCALATE\n 14 CANCEL (closed without merging)\n 15 MERGE\n A command/validation/GitHub failure exits with a sysexits.h code instead (see docs/exit-codes.md).";
|
|
197
197
|
readonly clean: `pr-shepherd clean
|
|
198
198
|
|
|
199
199
|
Remove pr-shepherd state files from PR_SHEPHERD_STATE_DIR.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const ITERATE_USAGE = "pr-shepherd iterate\n\nRun one iterate tick for a pull request. The no-subcommand form polls; use this subcommand for a single tick.\nThe output contains one action and an action-specific ## Instructions section.\n\nUsage:\n pr-shepherd iterate [PR] [iterate-flags]\n\nIterate flags:\n --ready-delay <duration> Settle window before a clean PR cancels. Bare number = minutes. Example: 15m.\n --stall-timeout <duration> Escalate repeated unchanged failures after this duration. Bare number = minutes. 0 disables.\n --no-auto-mark-ready Do not convert draft PRs to ready for review.\n --no-auto-cancel-actionable Do not cancel in-progress runs before actionable fixes.\n --format text|json Output Markdown text or JSON. Default: text.\n --verbose Include verbose iterate fields.\n --help, -h Print this help and exit before GitHub, git, config, or log I/O.\n\nDurations accept s/m/h suffixes: 30s, 4.5m, 1h. A bare number is minutes; decimals are allowed only with an explicit unit (4.5m).\n\nActions:\n WAIT No immediate action; continue with the next poll.\n MARK_READY Draft PR was marked ready; continue with the next poll.\n FIX_CODE Agent action is required; follow the instructions, then continue polling.\n CANCEL Stop polling: merged/closed or ready-delay elapsed.\n ESCALATE Stop polling until a human provides direction.\n\nExit codes:\n 0 CANCEL (merged or ready-delay elapsed)\n 10 WAIT\n 11 MARK_READY\n 12 FIX_CODE\n 13 ESCALATE\n 14 CANCEL (closed without merging)\n A command/validation/GitHub failure exits with a sysexits.h code instead (see docs/exit-codes.md).";
|
|
2
|
-
export declare const POLL_USAGE = "pr-shepherd poll\n\nRun iterate repeatedly for WAIT ticks and during the FIX_CODE debounce window. Print only the\nfinal tick to stdout.\nPoll exits as soon as iterate returns MARK_READY, CANCEL, or ESCALATE, or when timeout\nreturns the last WAIT result. FIX_CODE starts a --debounce settle window (default 1m): poll keeps\niterating at --interval, then runs one more tick after the window and returns that result.\nWith --until-terminal, poll also continues through MARK_READY.\n\nUsage:\n pr-shepherd poll [PR] [poll-flags] [iterate-flags]\n\nPoll flags:\n --interval <duration> Sleep between WAIT ticks. Bare number = seconds. Default: 60s.\n --timeout <duration> Maximum wall-clock wait for WAIT ticks. Bare number = seconds. Default: 4.5m.\n --debounce <duration> Settle window after first FIX_CODE before returning. Bare number = seconds. Default: 60s. 0 disables.\n --quiet-status During WAIT polling, print only changed status snapshots.\n --until-terminal Continue through WAIT/MARK_READY until FIX_CODE/CANCEL/ESCALATE.\n\nForwarded iterate flags:\n --ready-delay <duration> Settle window before a clean PR cancels. Bare number = minutes. Example: 15m.\n --stall-timeout <duration> Escalate repeated unchanged failures after this duration. Bare number = minutes. 0 disables.\n --no-auto-mark-ready Do not convert draft PRs to ready for review.\n --no-auto-cancel-actionable Do not cancel in-progress runs before actionable fixes.\n --format text|json Output Markdown text or JSON. Default: text.\n --verbose Include verbose iterate fields and detailed per-tick lines.\n --help, -h Print this help and exit before GitHub, git, config, or log I/O.\n\nDurations accept s/m/h suffixes: 30s, 4.5m, 1h. A bare number uses each flag's default unit (seconds\nfor --interval/--timeout/--debounce, minutes for --ready-delay/--stall-timeout); decimals are allowed only with\nan explicit unit (4.5m).\nEach WAIT tick writes an explicit still-running line to stderr by default; --quiet-status prints only changed WAIT snapshots, and --verbose emits detailed per-tick lines.\nFIX_CODE debounce writes a remaining-seconds line to stderr. --timeout does not cut an in-flight debounce short.\nWith --until-terminal, --timeout is ignored for WAIT ticks and polling continues until FIX_CODE, CANCEL, or ESCALATE.\n\nExit codes: same as iterate (the final tick's action/reason decides the code).\n 0 CANCEL (merged or ready-delay elapsed)\n 10 WAIT (including a WAIT returned by --timeout)\n 11 MARK_READY\n 12 FIX_CODE\n 13 ESCALATE\n 14 CANCEL (closed without merging)\n A command/validation/GitHub failure exits with a sysexits.h code instead (see docs/exit-codes.md).";
|
|
1
|
+
export declare const ITERATE_USAGE = "pr-shepherd iterate\n\nRun one iterate tick for a pull request. The no-subcommand form polls; use this subcommand for a single tick.\nThe output contains one action and an action-specific ## Instructions section.\n\nUsage:\n pr-shepherd iterate [PR] [iterate-flags]\n\nIterate flags:\n --ready-delay <duration> Settle window before a clean PR cancels. Bare number = minutes. Example: 15m.\n --stall-timeout <duration> Escalate repeated unchanged failures after this duration. Bare number = minutes. 0 disables.\n --no-auto-mark-ready Do not convert draft PRs to ready for review.\n --no-auto-cancel-actionable Do not cancel in-progress runs before actionable fixes.\n --merge Shepherd through readiness, then emit a merge or merge-queue command.\n --format text|json Output Markdown text or JSON. Default: text.\n --verbose Include verbose iterate fields.\n --help, -h Print this help and exit before GitHub, git, config, or log I/O.\n\nDurations accept s/m/h suffixes: 30s, 4.5m, 1h. A bare number is minutes; decimals are allowed only with an explicit unit (4.5m).\n\nActions:\n WAIT No immediate action; continue with the next poll.\n MARK_READY Draft PR was marked ready; continue with the next poll.\n FIX_CODE Agent action is required; follow the instructions, then continue polling.\n CANCEL Stop polling: merged/closed or ready-delay elapsed.\n ESCALATE Stop polling until a human provides direction.\n MERGE Run the emitted merge/queue command, then continue monitoring.\n\nExit codes:\n 0 CANCEL (merged or ready-delay elapsed)\n 10 WAIT\n 11 MARK_READY\n 12 FIX_CODE\n 13 ESCALATE\n 14 CANCEL (closed without merging)\n 15 MERGE\n A command/validation/GitHub failure exits with a sysexits.h code instead (see docs/exit-codes.md).";
|
|
2
|
+
export declare const POLL_USAGE = "pr-shepherd poll\n\nRun iterate repeatedly for WAIT ticks and during the FIX_CODE debounce window. Print only the\nfinal tick to stdout.\nPoll exits as soon as iterate returns MARK_READY, CANCEL, or ESCALATE, or when timeout\nreturns the last WAIT result. FIX_CODE starts a --debounce settle window (default 1m): poll keeps\niterating at --interval, then runs one more tick after the window and returns that result.\nWith --until-terminal or --merge, poll also continues through MARK_READY.\n\nUsage:\n pr-shepherd poll [PR] [poll-flags] [iterate-flags]\n\nPoll flags:\n --interval <duration> Sleep between WAIT ticks. Bare number = seconds. Default: 60s.\n --timeout <duration> Maximum wall-clock wait for WAIT ticks. Bare number = seconds. Default: 4.5m.\n --debounce <duration> Settle window after first FIX_CODE before returning. Bare number = seconds. Default: 60s. 0 disables.\n --quiet-status During WAIT polling, print only changed status snapshots.\n --until-terminal Continue through WAIT/MARK_READY until FIX_CODE/CANCEL/ESCALATE.\n\nForwarded iterate flags:\n --ready-delay <duration> Settle window before a clean PR cancels. Bare number = minutes. Example: 15m.\n --stall-timeout <duration> Escalate repeated unchanged failures after this duration. Bare number = minutes. 0 disables.\n --no-auto-mark-ready Do not convert draft PRs to ready for review.\n --no-auto-cancel-actionable Do not cancel in-progress runs before actionable fixes.\n --merge Shepherd through readiness, then emit a merge or merge-queue command.\n --format text|json Output Markdown text or JSON. Default: text.\n --verbose Include verbose iterate fields and detailed per-tick lines.\n --help, -h Print this help and exit before GitHub, git, config, or log I/O.\n\nDurations accept s/m/h suffixes: 30s, 4.5m, 1h. A bare number uses each flag's default unit (seconds\nfor --interval/--timeout/--debounce, minutes for --ready-delay/--stall-timeout); decimals are allowed only with\nan explicit unit (4.5m).\nEach WAIT tick writes an explicit still-running line to stderr by default; --quiet-status prints only changed WAIT snapshots, and --verbose emits detailed per-tick lines.\nFIX_CODE debounce writes a remaining-seconds line to stderr. --timeout does not cut an in-flight debounce short.\nWith --until-terminal, --timeout is ignored for WAIT ticks and polling continues until FIX_CODE, MERGE, CANCEL, or ESCALATE. With --merge, --timeout still bounds WAIT ticks; it only continues through MARK_READY while polling remains within that timeout.\n\nExit codes: same as iterate (the final tick's action/reason decides the code).\n 0 CANCEL (merged or ready-delay elapsed)\n 10 WAIT (including a WAIT returned by --timeout)\n 11 MARK_READY\n 12 FIX_CODE\n 13 ESCALATE\n 14 CANCEL (closed without merging)\n 15 MERGE\n A command/validation/GitHub failure exits with a sysexits.h code instead (see docs/exit-codes.md).";
|
|
3
3
|
/** Public help page for the default PR polling invocation. */
|
|
4
4
|
export declare const DEFAULT_USAGE: string;
|
|
@@ -11,6 +11,7 @@ Iterate flags:
|
|
|
11
11
|
--stall-timeout <duration> Escalate repeated unchanged failures after this duration. Bare number = minutes. 0 disables.
|
|
12
12
|
--no-auto-mark-ready Do not convert draft PRs to ready for review.
|
|
13
13
|
--no-auto-cancel-actionable Do not cancel in-progress runs before actionable fixes.
|
|
14
|
+
--merge Shepherd through readiness, then emit a merge or merge-queue command.
|
|
14
15
|
--format text|json Output Markdown text or JSON. Default: text.
|
|
15
16
|
--verbose Include verbose iterate fields.
|
|
16
17
|
--help, -h Print this help and exit before GitHub, git, config, or log I/O.
|
|
@@ -23,6 +24,7 @@ Actions:
|
|
|
23
24
|
FIX_CODE Agent action is required; follow the instructions, then continue polling.
|
|
24
25
|
CANCEL Stop polling: merged/closed or ready-delay elapsed.
|
|
25
26
|
ESCALATE Stop polling until a human provides direction.
|
|
27
|
+
MERGE Run the emitted merge/queue command, then continue monitoring.
|
|
26
28
|
|
|
27
29
|
Exit codes:
|
|
28
30
|
0 CANCEL (merged or ready-delay elapsed)
|
|
@@ -31,6 +33,7 @@ Exit codes:
|
|
|
31
33
|
12 FIX_CODE
|
|
32
34
|
13 ESCALATE
|
|
33
35
|
14 CANCEL (closed without merging)
|
|
36
|
+
15 MERGE
|
|
34
37
|
A command/validation/GitHub failure exits with a sysexits.h code instead (see docs/exit-codes.md).`;
|
|
35
38
|
export const POLL_USAGE = `pr-shepherd poll
|
|
36
39
|
|
|
@@ -39,7 +42,7 @@ final tick to stdout.
|
|
|
39
42
|
Poll exits as soon as iterate returns MARK_READY, CANCEL, or ESCALATE, or when timeout
|
|
40
43
|
returns the last WAIT result. FIX_CODE starts a --debounce settle window (default 1m): poll keeps
|
|
41
44
|
iterating at --interval, then runs one more tick after the window and returns that result.
|
|
42
|
-
With --until-terminal, poll also continues through MARK_READY.
|
|
45
|
+
With --until-terminal or --merge, poll also continues through MARK_READY.
|
|
43
46
|
|
|
44
47
|
Usage:
|
|
45
48
|
pr-shepherd poll [PR] [poll-flags] [iterate-flags]
|
|
@@ -56,6 +59,7 @@ Forwarded iterate flags:
|
|
|
56
59
|
--stall-timeout <duration> Escalate repeated unchanged failures after this duration. Bare number = minutes. 0 disables.
|
|
57
60
|
--no-auto-mark-ready Do not convert draft PRs to ready for review.
|
|
58
61
|
--no-auto-cancel-actionable Do not cancel in-progress runs before actionable fixes.
|
|
62
|
+
--merge Shepherd through readiness, then emit a merge or merge-queue command.
|
|
59
63
|
--format text|json Output Markdown text or JSON. Default: text.
|
|
60
64
|
--verbose Include verbose iterate fields and detailed per-tick lines.
|
|
61
65
|
--help, -h Print this help and exit before GitHub, git, config, or log I/O.
|
|
@@ -65,7 +69,7 @@ for --interval/--timeout/--debounce, minutes for --ready-delay/--stall-timeout);
|
|
|
65
69
|
an explicit unit (4.5m).
|
|
66
70
|
Each WAIT tick writes an explicit still-running line to stderr by default; --quiet-status prints only changed WAIT snapshots, and --verbose emits detailed per-tick lines.
|
|
67
71
|
FIX_CODE debounce writes a remaining-seconds line to stderr. --timeout does not cut an in-flight debounce short.
|
|
68
|
-
With --until-terminal, --timeout is ignored for WAIT ticks and polling continues until FIX_CODE, CANCEL, or ESCALATE.
|
|
72
|
+
With --until-terminal, --timeout is ignored for WAIT ticks and polling continues until FIX_CODE, MERGE, CANCEL, or ESCALATE. With --merge, --timeout still bounds WAIT ticks; it only continues through MARK_READY while polling remains within that timeout.
|
|
69
73
|
|
|
70
74
|
Exit codes: same as iterate (the final tick's action/reason decides the code).
|
|
71
75
|
0 CANCEL (merged or ready-delay elapsed)
|
|
@@ -74,6 +78,7 @@ Exit codes: same as iterate (the final tick's action/reason decides the code).
|
|
|
74
78
|
12 FIX_CODE
|
|
75
79
|
13 ESCALATE
|
|
76
80
|
14 CANCEL (closed without merging)
|
|
81
|
+
15 MERGE
|
|
77
82
|
A command/validation/GitHub failure exits with a sysexits.h code instead (see docs/exit-codes.md).`;
|
|
78
83
|
/** Public help page for the default PR polling invocation. */
|
|
79
84
|
export const DEFAULT_USAGE = POLL_USAGE.replace(/^pr-shepherd poll$/m, "pr-shepherd [PR]").replace(/^ {2}pr-shepherd poll \[PR\]/m, " pr-shepherd [PR]");
|
package/bin/cli/help.d.mts
CHANGED
|
@@ -192,8 +192,8 @@ Flags:
|
|
|
192
192
|
|
|
193
193
|
PR may be a number or GitHub pull request URL. When omitted, the current branch PR is inferred.
|
|
194
194
|
Exit code: 0 on success; nonzero on failure (sysexits.h — see docs/exit-codes.md).`;
|
|
195
|
-
readonly iterate: "pr-shepherd iterate\n\nRun one iterate tick for a pull request. The no-subcommand form polls; use this subcommand for a single tick.\nThe output contains one action and an action-specific ## Instructions section.\n\nUsage:\n pr-shepherd iterate [PR] [iterate-flags]\n\nIterate flags:\n --ready-delay <duration> Settle window before a clean PR cancels. Bare number = minutes. Example: 15m.\n --stall-timeout <duration> Escalate repeated unchanged failures after this duration. Bare number = minutes. 0 disables.\n --no-auto-mark-ready Do not convert draft PRs to ready for review.\n --no-auto-cancel-actionable Do not cancel in-progress runs before actionable fixes.\n --format text|json Output Markdown text or JSON. Default: text.\n --verbose Include verbose iterate fields.\n --help, -h Print this help and exit before GitHub, git, config, or log I/O.\n\nDurations accept s/m/h suffixes: 30s, 4.5m, 1h. A bare number is minutes; decimals are allowed only with an explicit unit (4.5m).\n\nActions:\n WAIT No immediate action; continue with the next poll.\n MARK_READY Draft PR was marked ready; continue with the next poll.\n FIX_CODE Agent action is required; follow the instructions, then continue polling.\n CANCEL Stop polling: merged/closed or ready-delay elapsed.\n ESCALATE Stop polling until a human provides direction.\n\nExit codes:\n 0 CANCEL (merged or ready-delay elapsed)\n 10 WAIT\n 11 MARK_READY\n 12 FIX_CODE\n 13 ESCALATE\n 14 CANCEL (closed without merging)\n A command/validation/GitHub failure exits with a sysexits.h code instead (see docs/exit-codes.md).";
|
|
196
|
-
readonly poll: "pr-shepherd poll\n\nRun iterate repeatedly for WAIT ticks and during the FIX_CODE debounce window. Print only the\nfinal tick to stdout.\nPoll exits as soon as iterate returns MARK_READY, CANCEL, or ESCALATE, or when timeout\nreturns the last WAIT result. FIX_CODE starts a --debounce settle window (default 1m): poll keeps\niterating at --interval, then runs one more tick after the window and returns that result.\nWith --until-terminal, poll also continues through MARK_READY.\n\nUsage:\n pr-shepherd poll [PR] [poll-flags] [iterate-flags]\n\nPoll flags:\n --interval <duration> Sleep between WAIT ticks. Bare number = seconds. Default: 60s.\n --timeout <duration> Maximum wall-clock wait for WAIT ticks. Bare number = seconds. Default: 4.5m.\n --debounce <duration> Settle window after first FIX_CODE before returning. Bare number = seconds. Default: 60s. 0 disables.\n --quiet-status During WAIT polling, print only changed status snapshots.\n --until-terminal Continue through WAIT/MARK_READY until FIX_CODE/CANCEL/ESCALATE.\n\nForwarded iterate flags:\n --ready-delay <duration> Settle window before a clean PR cancels. Bare number = minutes. Example: 15m.\n --stall-timeout <duration> Escalate repeated unchanged failures after this duration. Bare number = minutes. 0 disables.\n --no-auto-mark-ready Do not convert draft PRs to ready for review.\n --no-auto-cancel-actionable Do not cancel in-progress runs before actionable fixes.\n --format text|json Output Markdown text or JSON. Default: text.\n --verbose Include verbose iterate fields and detailed per-tick lines.\n --help, -h Print this help and exit before GitHub, git, config, or log I/O.\n\nDurations accept s/m/h suffixes: 30s, 4.5m, 1h. A bare number uses each flag's default unit (seconds\nfor --interval/--timeout/--debounce, minutes for --ready-delay/--stall-timeout); decimals are allowed only with\nan explicit unit (4.5m).\nEach WAIT tick writes an explicit still-running line to stderr by default; --quiet-status prints only changed WAIT snapshots, and --verbose emits detailed per-tick lines.\nFIX_CODE debounce writes a remaining-seconds line to stderr. --timeout does not cut an in-flight debounce short.\nWith --until-terminal, --timeout is ignored for WAIT ticks and polling continues until FIX_CODE, CANCEL, or ESCALATE.\n\nExit codes: same as iterate (the final tick's action/reason decides the code).\n 0 CANCEL (merged or ready-delay elapsed)\n 10 WAIT (including a WAIT returned by --timeout)\n 11 MARK_READY\n 12 FIX_CODE\n 13 ESCALATE\n 14 CANCEL (closed without merging)\n A command/validation/GitHub failure exits with a sysexits.h code instead (see docs/exit-codes.md).";
|
|
195
|
+
readonly iterate: "pr-shepherd iterate\n\nRun one iterate tick for a pull request. The no-subcommand form polls; use this subcommand for a single tick.\nThe output contains one action and an action-specific ## Instructions section.\n\nUsage:\n pr-shepherd iterate [PR] [iterate-flags]\n\nIterate flags:\n --ready-delay <duration> Settle window before a clean PR cancels. Bare number = minutes. Example: 15m.\n --stall-timeout <duration> Escalate repeated unchanged failures after this duration. Bare number = minutes. 0 disables.\n --no-auto-mark-ready Do not convert draft PRs to ready for review.\n --no-auto-cancel-actionable Do not cancel in-progress runs before actionable fixes.\n --merge Shepherd through readiness, then emit a merge or merge-queue command.\n --format text|json Output Markdown text or JSON. Default: text.\n --verbose Include verbose iterate fields.\n --help, -h Print this help and exit before GitHub, git, config, or log I/O.\n\nDurations accept s/m/h suffixes: 30s, 4.5m, 1h. A bare number is minutes; decimals are allowed only with an explicit unit (4.5m).\n\nActions:\n WAIT No immediate action; continue with the next poll.\n MARK_READY Draft PR was marked ready; continue with the next poll.\n FIX_CODE Agent action is required; follow the instructions, then continue polling.\n CANCEL Stop polling: merged/closed or ready-delay elapsed.\n ESCALATE Stop polling until a human provides direction.\n MERGE Run the emitted merge/queue command, then continue monitoring.\n\nExit codes:\n 0 CANCEL (merged or ready-delay elapsed)\n 10 WAIT\n 11 MARK_READY\n 12 FIX_CODE\n 13 ESCALATE\n 14 CANCEL (closed without merging)\n 15 MERGE\n A command/validation/GitHub failure exits with a sysexits.h code instead (see docs/exit-codes.md).";
|
|
196
|
+
readonly poll: "pr-shepherd poll\n\nRun iterate repeatedly for WAIT ticks and during the FIX_CODE debounce window. Print only the\nfinal tick to stdout.\nPoll exits as soon as iterate returns MARK_READY, CANCEL, or ESCALATE, or when timeout\nreturns the last WAIT result. FIX_CODE starts a --debounce settle window (default 1m): poll keeps\niterating at --interval, then runs one more tick after the window and returns that result.\nWith --until-terminal or --merge, poll also continues through MARK_READY.\n\nUsage:\n pr-shepherd poll [PR] [poll-flags] [iterate-flags]\n\nPoll flags:\n --interval <duration> Sleep between WAIT ticks. Bare number = seconds. Default: 60s.\n --timeout <duration> Maximum wall-clock wait for WAIT ticks. Bare number = seconds. Default: 4.5m.\n --debounce <duration> Settle window after first FIX_CODE before returning. Bare number = seconds. Default: 60s. 0 disables.\n --quiet-status During WAIT polling, print only changed status snapshots.\n --until-terminal Continue through WAIT/MARK_READY until FIX_CODE/CANCEL/ESCALATE.\n\nForwarded iterate flags:\n --ready-delay <duration> Settle window before a clean PR cancels. Bare number = minutes. Example: 15m.\n --stall-timeout <duration> Escalate repeated unchanged failures after this duration. Bare number = minutes. 0 disables.\n --no-auto-mark-ready Do not convert draft PRs to ready for review.\n --no-auto-cancel-actionable Do not cancel in-progress runs before actionable fixes.\n --merge Shepherd through readiness, then emit a merge or merge-queue command.\n --format text|json Output Markdown text or JSON. Default: text.\n --verbose Include verbose iterate fields and detailed per-tick lines.\n --help, -h Print this help and exit before GitHub, git, config, or log I/O.\n\nDurations accept s/m/h suffixes: 30s, 4.5m, 1h. A bare number uses each flag's default unit (seconds\nfor --interval/--timeout/--debounce, minutes for --ready-delay/--stall-timeout); decimals are allowed only with\nan explicit unit (4.5m).\nEach WAIT tick writes an explicit still-running line to stderr by default; --quiet-status prints only changed WAIT snapshots, and --verbose emits detailed per-tick lines.\nFIX_CODE debounce writes a remaining-seconds line to stderr. --timeout does not cut an in-flight debounce short.\nWith --until-terminal, --timeout is ignored for WAIT ticks and polling continues until FIX_CODE, MERGE, CANCEL, or ESCALATE. With --merge, --timeout still bounds WAIT ticks; it only continues through MARK_READY while polling remains within that timeout.\n\nExit codes: same as iterate (the final tick's action/reason decides the code).\n 0 CANCEL (merged or ready-delay elapsed)\n 10 WAIT (including a WAIT returned by --timeout)\n 11 MARK_READY\n 12 FIX_CODE\n 13 ESCALATE\n 14 CANCEL (closed without merging)\n 15 MERGE\n A command/validation/GitHub failure exits with a sysexits.h code instead (see docs/exit-codes.md).";
|
|
197
197
|
readonly clean: `pr-shepherd clean
|
|
198
198
|
|
|
199
199
|
Remove pr-shepherd state files from PR_SHEPHERD_STATE_DIR.
|
|
@@ -6,6 +6,7 @@ interface IterateFlags {
|
|
|
6
6
|
stallTimeoutSeconds: number;
|
|
7
7
|
noAutoMarkReady: boolean;
|
|
8
8
|
noAutoCancelActionable: boolean;
|
|
9
|
+
merge: boolean;
|
|
9
10
|
}
|
|
10
11
|
export declare function parseIterateFlags(extra: string[], cfg: ReturnType<typeof loadConfig>): IterateFlags;
|
|
11
12
|
export {};
|
|
@@ -10,6 +10,7 @@ export function parseIterateFlags(extra, cfg) {
|
|
|
10
10
|
const readyDelaySeconds = parseDurationToSeconds(readyDelaySuffix ?? "", cfg.watch.readyDelayMinutes * 60, MINUTE_FLAG_OPTS);
|
|
11
11
|
const noAutoMarkReady = hasFlag(extra, "--no-auto-mark-ready");
|
|
12
12
|
const noAutoCancelActionable = hasFlag(extra, "--no-auto-cancel-actionable");
|
|
13
|
+
const merge = hasFlag(extra, "--merge");
|
|
13
14
|
const stallTimeoutStr = getFlag(extra, "--stall-timeout");
|
|
14
15
|
const stallTimeoutSuffix = validateSecondsDurationFlag("pr-shepherd", "--stall-timeout", stallTimeoutStr, hasFlag(extra, "--stall-timeout"), MINUTE_FLAG_OPTS);
|
|
15
16
|
const stallTimeoutSeconds = parseDurationToSeconds(stallTimeoutSuffix ?? "", cfg.iterate.stallTimeoutMinutes * 60, MINUTE_FLAG_OPTS);
|
|
@@ -20,5 +21,6 @@ export function parseIterateFlags(extra, cfg) {
|
|
|
20
21
|
stallTimeoutSeconds,
|
|
21
22
|
noAutoMarkReady,
|
|
22
23
|
noAutoCancelActionable,
|
|
24
|
+
merge,
|
|
23
25
|
};
|
|
24
26
|
}
|
|
@@ -2,6 +2,7 @@ import { formatFixCodeResult } from "./fix-formatter.mjs";
|
|
|
2
2
|
import { joinSections } from "../util/markdown.mjs";
|
|
3
3
|
import { adaptIterateLog, buildSimpleIterateInstructions, numberInstructions, } from "./iterate-instructions.mjs";
|
|
4
4
|
import { formatMergeRequirementLines } from "../merge-status/requirements-format.mjs";
|
|
5
|
+
import { appendMergeQueueHeader, formatMergeAction } from "./iterate-merge-formatter.mjs";
|
|
5
6
|
function formatActivityLine(result) {
|
|
6
7
|
const activity = result.activity ?? {
|
|
7
8
|
commitCount: 0,
|
|
@@ -89,7 +90,6 @@ export function formatIterateResult(result, opts) {
|
|
|
89
90
|
}
|
|
90
91
|
// Surface an explicit `--ready-delay` override (set only when the user passed the flag)
|
|
91
92
|
// so the active settle window stays visible on every tick. Replaces the rerun command
|
|
92
|
-
// that previously carried the suffix in the (now removed) recheck instruction.
|
|
93
93
|
if (readyDelaySuffix) {
|
|
94
94
|
summaryLine += ` · **ready-delay** \`${readyDelaySuffix}\` (override)`;
|
|
95
95
|
}
|
|
@@ -127,6 +127,7 @@ export function formatIterateResult(result, opts) {
|
|
|
127
127
|
const names = result.supersededNames.map((n) => "`" + n + "`").join(", ");
|
|
128
128
|
headerLines.push(`**superseded** ${names}`);
|
|
129
129
|
}
|
|
130
|
+
appendMergeQueueHeader(headerLines, result);
|
|
130
131
|
const activityLine = formatActivityLine(result);
|
|
131
132
|
if (activityLine)
|
|
132
133
|
headerLines.push(activityLine);
|
|
@@ -144,6 +145,8 @@ export function formatIterateResult(result, opts) {
|
|
|
144
145
|
adaptIterateLog(result.log),
|
|
145
146
|
`## Instructions\n\n${numberInstructions(buildSimpleIterateInstructions(result))}`,
|
|
146
147
|
]);
|
|
148
|
+
case "merge":
|
|
149
|
+
return formatMergeAction(header, result);
|
|
147
150
|
case "cancel": {
|
|
148
151
|
const cancelHeaderLines = [`${heading} — ${result.reason}`, "", baseLine, summaryLine];
|
|
149
152
|
if (result.mergeRequirements) {
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { renderMergeCommand } from "../commands/iterate/merge.mjs";
|
|
2
|
+
import { inlineCode } from "../util/markdown.mjs";
|
|
1
3
|
export function buildSimpleIterateInstructions(result) {
|
|
2
4
|
switch (result.action) {
|
|
3
5
|
case "wait":
|
|
@@ -8,6 +10,19 @@ export function buildSimpleIterateInstructions(result) {
|
|
|
8
10
|
return [
|
|
9
11
|
"The CLI marked the PR ready for review. Iterate again with the same options to continue.",
|
|
10
12
|
];
|
|
13
|
+
case "merge": {
|
|
14
|
+
const instructions = [
|
|
15
|
+
`Run the \`${result.merge.mode === "queue" ? "merge queue" : "auto-merge"}\` command shown above exactly as printed.`,
|
|
16
|
+
];
|
|
17
|
+
if (result.merge.mode === "queue" && result.merge.queueApiFallbackCommand) {
|
|
18
|
+
instructions.push(`If the gh CLI says auto-merge is disabled instead of adding the PR to the queue, run the \`queue API fallback\` command: ${inlineCode(renderMergeCommand(result.merge.queueApiFallbackCommand))}.`);
|
|
19
|
+
}
|
|
20
|
+
else if (result.merge.fallbackCommand) {
|
|
21
|
+
instructions.push(`Only if GitHub reports that auto-merge is unavailable, run the \`plain merge fallback\` command: ${inlineCode(renderMergeCommand(result.merge.fallbackCommand))}.`);
|
|
22
|
+
}
|
|
23
|
+
instructions.push("Then iterate again with the same options to monitor until the PR merges or needs work.");
|
|
24
|
+
return instructions;
|
|
25
|
+
}
|
|
11
26
|
case "cancel":
|
|
12
27
|
return ["Stop — the PR loop is complete. No further polling is needed."];
|
|
13
28
|
case "escalate":
|
|
@@ -8,5 +8,4 @@ interface IterateProjectionOptions {
|
|
|
8
8
|
* outside the state where they are meaningful.
|
|
9
9
|
*/
|
|
10
10
|
export declare function projectIterateLean(result: IterateResult, opts?: IterateProjectionOptions): unknown;
|
|
11
|
-
export
|
|
12
|
-
export {};
|
|
11
|
+
export { projectIterateVerbose } from "./iterate-verbose.mts";
|
package/bin/cli/iterate-lean.mjs
CHANGED
|
@@ -42,6 +42,7 @@ export function projectIterateLean(result, opts) {
|
|
|
42
42
|
...(result.baseBranch && { baseBranch: result.baseBranch }),
|
|
43
43
|
...(result.branchProtection !== null && { branchProtection: result.branchProtection }),
|
|
44
44
|
...(result.mergeRequirements && { mergeRequirements: result.mergeRequirements }),
|
|
45
|
+
...(result.mergeQueue && { mergeQueue: result.mergeQueue }),
|
|
45
46
|
...(hasActivity && {
|
|
46
47
|
activity: {
|
|
47
48
|
commitCount: activity.commitCount,
|
|
@@ -85,6 +86,12 @@ export function projectIterateLean(result, opts) {
|
|
|
85
86
|
log: adaptIterateLog(result.log),
|
|
86
87
|
instructions: simpleInstructions(result),
|
|
87
88
|
};
|
|
89
|
+
case "merge":
|
|
90
|
+
return {
|
|
91
|
+
...base,
|
|
92
|
+
merge: result.merge,
|
|
93
|
+
instructions: simpleInstructions(result),
|
|
94
|
+
};
|
|
88
95
|
case "fix_code":
|
|
89
96
|
return {
|
|
90
97
|
...base,
|
|
@@ -122,6 +129,7 @@ export function projectIterateLean(result, opts) {
|
|
|
122
129
|
...(result.fix.protectedRuns.length > 0 && {
|
|
123
130
|
protectedRuns: result.fix.protectedRuns,
|
|
124
131
|
}),
|
|
132
|
+
...(result.fix.requeue && { requeue: result.fix.requeue }),
|
|
125
133
|
...(result.fix.checks.length > 0 && { checks: result.fix.checks }),
|
|
126
134
|
...(result.fix.changesRequestedReviews.length > 0 && {
|
|
127
135
|
changesRequestedReviews: result.fix.changesRequestedReviews,
|
|
@@ -157,6 +165,9 @@ export function projectIterateLean(result, opts) {
|
|
|
157
165
|
result.escalate.thrashHistory.length > 0 && {
|
|
158
166
|
thrashHistory: result.escalate.thrashHistory,
|
|
159
167
|
}),
|
|
168
|
+
...(result.escalate.mergeQueueRemoval && {
|
|
169
|
+
mergeQueueRemoval: result.escalate.mergeQueueRemoval,
|
|
170
|
+
}),
|
|
160
171
|
suggestion: result.escalate.suggestion,
|
|
161
172
|
humanMessage: result.escalate.humanMessage,
|
|
162
173
|
},
|
|
@@ -164,20 +175,4 @@ export function projectIterateLean(result, opts) {
|
|
|
164
175
|
};
|
|
165
176
|
}
|
|
166
177
|
}
|
|
167
|
-
export
|
|
168
|
-
const readyDelaySuffix = opts?.readyDelaySuffix;
|
|
169
|
-
const readyDelayOverride = readyDelaySuffix ? { readyDelayOverride: readyDelaySuffix } : {};
|
|
170
|
-
if (result.action === "fix_code") {
|
|
171
|
-
return {
|
|
172
|
-
...result,
|
|
173
|
-
...readyDelayOverride,
|
|
174
|
-
};
|
|
175
|
-
}
|
|
176
|
-
const log = "log" in result && typeof result.log === "string" ? { log: adaptIterateLog(result.log) } : {};
|
|
177
|
-
return {
|
|
178
|
-
...result,
|
|
179
|
-
...log,
|
|
180
|
-
...readyDelayOverride,
|
|
181
|
-
instructions: buildSimpleIterateInstructions(result),
|
|
182
|
-
};
|
|
183
|
-
}
|
|
178
|
+
export { projectIterateVerbose } from "./iterate-verbose.mjs";
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { renderMergeCommand } from "../commands/iterate/merge.mjs";
|
|
2
|
+
import { inlineCode, joinSections } from "../util/markdown.mjs";
|
|
3
|
+
import { buildSimpleIterateInstructions, numberInstructions } from "./iterate-instructions.mjs";
|
|
4
|
+
export function appendMergeQueueHeader(lines, result) {
|
|
5
|
+
const queue = result.mergeQueue;
|
|
6
|
+
if (!queue)
|
|
7
|
+
return;
|
|
8
|
+
const parts = [`enabled \`${queue.enabled}\``, `inQueue \`${queue.inQueue}\``];
|
|
9
|
+
if (queue.entry) {
|
|
10
|
+
parts.push(`state \`${queue.entry.state}\``, `position \`${queue.entry.position}\``);
|
|
11
|
+
if (queue.entry.estimatedTimeToMerge !== null) {
|
|
12
|
+
parts.push(`estimatedTimeToMerge \`${queue.entry.estimatedTimeToMerge}\``);
|
|
13
|
+
}
|
|
14
|
+
if (queue.entry.enqueuedAtUnix !== undefined) {
|
|
15
|
+
parts.push(`enqueuedAtUnix \`${queue.entry.enqueuedAtUnix}\``);
|
|
16
|
+
}
|
|
17
|
+
if (queue.entry.enqueuer)
|
|
18
|
+
parts.push(`enqueuer \`@${queue.entry.enqueuer}\``);
|
|
19
|
+
if (queue.entry.headCommitOid)
|
|
20
|
+
parts.push(`headCommit \`${queue.entry.headCommitOid}\``);
|
|
21
|
+
}
|
|
22
|
+
if (queue.checkCommitOid)
|
|
23
|
+
parts.push(`checkCommit \`${queue.checkCommitOid}\``);
|
|
24
|
+
if (queue.checksIncomplete)
|
|
25
|
+
parts.push("checks incomplete (first 100 shown)");
|
|
26
|
+
if (queue.headUpdatedAfterRemoval)
|
|
27
|
+
parts.push("head updated after removal");
|
|
28
|
+
lines.push(`**merge queue** ${parts.join(" · ")}`);
|
|
29
|
+
if (queue.autoMergeRequest) {
|
|
30
|
+
lines.push(`**auto-merge** method \`${queue.autoMergeRequest.mergeMethod}\` · enabledAtUnix \`${queue.autoMergeRequest.enabledAtUnix}\`${queue.autoMergeRequest.enabledBy ? ` · by \`@${queue.autoMergeRequest.enabledBy}\`` : ""}`);
|
|
31
|
+
}
|
|
32
|
+
if (queue.latestRemoval) {
|
|
33
|
+
const removal = queue.latestRemoval;
|
|
34
|
+
lines.push(`**queue removal** reason \`${removal.reason ?? "not provided"}\` · createdAtUnix \`${removal.createdAtUnix}\`${removal.actor ? ` · actor \`@${removal.actor}\`` : ""}${removal.beforeCommitOid ? ` · commit \`${removal.beforeCommitOid}\`` : ""}${removal.beforeCommitParentOids ? ` · parents \`${removal.beforeCommitParentOids.join(",")}\`` : ""}`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
export function formatMergeAction(header, result) {
|
|
38
|
+
const commandLines = [
|
|
39
|
+
`- ${result.merge.mode === "queue" ? "merge queue" : "auto-merge"}: ${inlineCode(renderMergeCommand(result.merge.command))}`,
|
|
40
|
+
];
|
|
41
|
+
if (result.merge.fallbackCommand) {
|
|
42
|
+
commandLines.push(`- plain merge fallback: ${inlineCode(renderMergeCommand(result.merge.fallbackCommand))}`);
|
|
43
|
+
}
|
|
44
|
+
if (result.merge.queueApiFallbackCommand) {
|
|
45
|
+
commandLines.push(`- queue API fallback: ${inlineCode(renderMergeCommand(result.merge.queueApiFallbackCommand))}`);
|
|
46
|
+
}
|
|
47
|
+
return joinSections([
|
|
48
|
+
header,
|
|
49
|
+
`## Merge command\n\n${commandLines.join("\n")}`,
|
|
50
|
+
`## Instructions\n\n${numberInstructions(buildSimpleIterateInstructions(result))}`,
|
|
51
|
+
]);
|
|
52
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { adaptIterateLog, buildSimpleIterateInstructions } from "./iterate-instructions.mjs";
|
|
2
|
+
export function projectIterateVerbose(result, opts) {
|
|
3
|
+
const readyDelaySuffix = opts?.readyDelaySuffix;
|
|
4
|
+
const readyDelayOverride = readyDelaySuffix ? { readyDelayOverride: readyDelaySuffix } : {};
|
|
5
|
+
if (result.action === "fix_code")
|
|
6
|
+
return { ...result, ...readyDelayOverride };
|
|
7
|
+
const log = "log" in result && typeof result.log === "string" ? { log: adaptIterateLog(result.log) } : {};
|
|
8
|
+
return {
|
|
9
|
+
...result,
|
|
10
|
+
...log,
|
|
11
|
+
...readyDelayOverride,
|
|
12
|
+
instructions: buildSimpleIterateInstructions(result),
|
|
13
|
+
};
|
|
14
|
+
}
|
package/bin/cli/poll-handler.mjs
CHANGED
|
@@ -36,6 +36,7 @@ export async function handlePoll(args) {
|
|
|
36
36
|
stallTimeoutSeconds: flags.stallTimeoutSeconds,
|
|
37
37
|
noAutoMarkReady: flags.noAutoMarkReady,
|
|
38
38
|
noAutoCancelActionable: flags.noAutoCancelActionable,
|
|
39
|
+
merge: flags.merge,
|
|
39
40
|
intervalSeconds,
|
|
40
41
|
timeoutSeconds,
|
|
41
42
|
debounceSeconds,
|
package/bin/cli/runner.mjs
CHANGED
|
@@ -8,11 +8,12 @@ export function renderShellCommand(argv) {
|
|
|
8
8
|
function renderShellArg(arg) {
|
|
9
9
|
if (/^\$[A-Z_][A-Z0-9_]*$/.test(arg))
|
|
10
10
|
return `"${arg}"`;
|
|
11
|
+
const assignment = /^([A-Za-z_][A-Za-z0-9_]*)=(\$[A-Z_][A-Z0-9_]*)$/.exec(arg);
|
|
12
|
+
if (assignment)
|
|
13
|
+
return `${assignment[1]}="${assignment[2]}"`;
|
|
11
14
|
if (/^[A-Za-z0-9_./:@%+=,-]+$/.test(arg))
|
|
12
15
|
return arg;
|
|
13
16
|
if (!/["$`\\]/.test(arg))
|
|
14
17
|
return `"${arg}"`;
|
|
15
|
-
|
|
16
|
-
return `'${arg}'`;
|
|
17
|
-
throw new Error(`Unexpected character in shell arg: ${JSON.stringify(arg)}`);
|
|
18
|
+
return `'${arg.replaceAll("'", `'"'"'`)}'`;
|
|
18
19
|
}
|