pr-shepherd 0.35.0 → 0.36.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 +32 -12
- package/bin/checks/triage.mjs +11 -3
- package/bin/cli/args.mjs +1 -0
- package/bin/cli/default-poll.mjs +1 -0
- package/bin/cli/help-command-pages.d.mts +1 -1
- package/bin/cli/help-iterate-poll-pages.d.mts +1 -1
- package/bin/cli/help-iterate-poll-pages.mjs +10 -5
- package/bin/cli/help-top-page.d.mts +1 -1
- package/bin/cli/help-top-page.mjs +2 -1
- package/bin/cli/help.d.mts +2 -2
- package/bin/cli/iterate-formatter.mjs +11 -2
- package/bin/cli/iterate-lean.mjs +1 -0
- package/bin/cli/poll-handler.mjs +7 -0
- package/bin/commands/check.d.mts +1 -0
- package/bin/commands/check.mjs +26 -22
- package/bin/commands/commit-suggestion.mjs +11 -5
- package/bin/commands/iterate/fix-code.mjs +1 -1
- package/bin/commands/iterate/helpers.d.mts +1 -0
- package/bin/commands/iterate/helpers.mjs +15 -6
- package/bin/commands/iterate/index.mjs +3 -10
- package/bin/commands/poll.d.mts +2 -0
- package/bin/commands/poll.mjs +51 -17
- package/bin/commands/ready-delay.mjs +3 -13
- package/bin/config/load.mjs +67 -25
- package/bin/github/batch-page-helpers.d.mts +45 -0
- package/bin/github/batch-page-helpers.mjs +63 -0
- package/bin/github/batch-page.d.mts +14 -0
- package/bin/github/batch-page.mjs +62 -0
- package/bin/github/batch-parse-suites.d.mts +4 -0
- package/bin/github/batch-parse-suites.mjs +25 -0
- package/bin/github/batch-parsers-rules.d.mts +6 -0
- package/bin/github/batch-parsers-rules.mjs +122 -0
- package/bin/github/batch-parsers.mjs +6 -0
- package/bin/github/batch-raw-rules.d.mts +59 -0
- package/bin/github/batch-raw-rules.mjs +1 -0
- package/bin/github/batch-raw-types.d.mts +20 -11
- package/bin/github/batch.d.mts +2 -0
- package/bin/github/batch.mjs +14 -120
- package/bin/github/gql/batch-pr-page.gql +189 -0
- package/bin/github/gql/batch-pr.gql +74 -21
- package/bin/github/gql/commit-suggestion-thread.gql +40 -0
- package/bin/github/http.d.mts +2 -1
- package/bin/github/http.mjs +2 -1
- package/bin/github/pagination.d.mts +3 -2
- package/bin/github/pagination.mjs +3 -2
- package/bin/github/queries.d.mts +4 -0
- package/bin/github/queries.mjs +4 -0
- package/bin/github/rest-http.d.mts +6 -1
- package/bin/github/rest-http.mjs +25 -86
- package/bin/github/rest-text.d.mts +1 -0
- package/bin/github/rest-text.mjs +88 -0
- package/bin/github/suggestion-thread.d.mts +9 -0
- package/bin/github/suggestion-thread.mjs +45 -0
- package/bin/github/thread-comments.mjs +12 -8
- package/bin/merge-status/derive.mjs +2 -0
- package/bin/merge-status/requirements-format.d.mts +3 -0
- package/bin/merge-status/requirements-format.mjs +88 -0
- package/bin/merge-status/requirements.d.mts +2 -0
- package/bin/merge-status/requirements.mjs +51 -0
- package/bin/state/base.d.mts +9 -0
- package/bin/state/base.mjs +23 -0
- package/bin/state/bot-cr-seen.mjs +3 -13
- package/bin/state/fix-attempts.mjs +3 -13
- package/bin/state/iterate-stall.mjs +3 -13
- package/bin/state/seen-comments.mjs +6 -13
- package/bin/types/github.d.mts +4 -7
- package/bin/types/iterate.d.mts +6 -7
- package/bin/types/merge-requirements.d.mts +82 -0
- package/bin/types/merge-requirements.mjs +2 -0
- package/bin/types.d.mts +1 -0
- package/bin/types.mjs +1 -0
- package/bin/util/path-segment.d.mts +2 -0
- package/bin/util/path-segment.mjs +2 -0
- package/bin/util/pool.d.mts +2 -0
- package/bin/util/pool.mjs +18 -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/README.md
CHANGED
|
@@ -2,11 +2,28 @@
|
|
|
2
2
|
|
|
3
3
|
Autonomous PR CI monitor and review-comment resolver for agentic coding tools, including Claude Code and Codex.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Why
|
|
6
|
+
|
|
7
|
+
An agent finishing a PR should think about code, not reconstruct GitHub state or invent a next-step policy each tick. Without Shepherd it fans out across GitHub MCP, `gh`, and GraphQL, then guesses what to do with the result.
|
|
8
|
+
|
|
9
|
+
## What it does
|
|
10
|
+
|
|
11
|
+
1. **Gather all context for a PR** in one invocation: review threads, comments, replies, summaries, CI, mergeability, merge requirements, first-look / outdated / edited items, and author provenance.
|
|
12
|
+
2. **Provide deterministic actions for the agent**: exactly one of `WAIT`, `MARK_READY`, `FIX_CODE`, `CANCEL`, or `ESCALATE`, plus numbered `## Instructions` and explicit `apply` / `build_suggestion_patch` mutations. 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
|
+
|
|
14
|
+
Highlights:
|
|
15
|
+
|
|
16
|
+
- Batched GraphQL reads and writes (plus REST where GraphQL cannot) so one poll replaces a tool-call fan-out. MCP `iterate` is one tick and the client owns recurrence; `--debounce` is a poll-dispatcher settle window, not an MCP tool.
|
|
17
|
+
- CI summaries include failed checks, and the failed job/step plus a log excerpt when triage can fetch them. Job and log details are omitted for `STARTUP_FAILURE` and `CANCELLED`; agents may still inspect logs.
|
|
18
|
+
- Handles GitHub comment types (comments, threads, replies) and their states, including first-look, outdated, resolved, minimized, and edited.
|
|
19
|
+
- `apply` batches resolve / reply / minimize / dismiss. `build_suggestion_patch` emits a unified diff in output, not a patch file, and does not mutate git.
|
|
20
|
+
- `BEHIND` is mergeability information, not a rebase or a guarantee that the next push is at the default-branch tip. The agent can update the branch before pushing.
|
|
21
|
+
|
|
22
|
+
Full reference: [docs/README.md](docs/README.md). Feature matrix: [docs/features.md](docs/features.md).
|
|
6
23
|
|
|
7
24
|
## How It Works
|
|
8
25
|
|
|
9
|
-
`pr-shepherd` moves deterministic PR orchestration into a local MCP server, with a CLI for shells and CI. Both interfaces fetch the same GitHub state, emit raw-enough context, and return a numbered plan for the calling agent to follow.
|
|
26
|
+
`pr-shepherd` moves deterministic PR orchestration into a local MCP server, with a CLI for shells and CI. Both interfaces fetch the same GitHub state, emit raw-enough context, and return a numbered plan for the calling agent to follow.
|
|
10
27
|
|
|
11
28
|
The MCP server exposes three tools: `iterate`, `apply`, and `build_suggestion_patch`. `apply` accepts ordered review mutations, file-view mutations, and journal entries. The shipped skills are thin dispatchers for those tools.
|
|
12
29
|
|
|
@@ -25,8 +42,10 @@ Example shape:
|
|
|
25
42
|
|
|
26
43
|
# PR #123 [FIX_CODE]
|
|
27
44
|
|
|
28
|
-
**status** `UNRESOLVED_COMMENTS` · **merge** `
|
|
45
|
+
**status** `UNRESOLVED_COMMENTS` · **merge** `CLEAN` · **state** `OPEN` · **repo** `owner/repo`
|
|
29
46
|
**summary** 3 passing
|
|
47
|
+
Approvals: None [Not Required]
|
|
48
|
+
Conversations Resolved: No [Not Required]
|
|
30
49
|
|
|
31
50
|
## Review threads
|
|
32
51
|
|
|
@@ -39,20 +58,20 @@ Example shape:
|
|
|
39
58
|
- `24697658766` — `CI › lint / typecheck / test (22.x)` [conclusion: FAILURE]
|
|
40
59
|
> oxfmt
|
|
41
60
|
|
|
42
|
-
## Post-fix
|
|
61
|
+
## Post-fix push
|
|
43
62
|
|
|
44
63
|
- base: `main`
|
|
45
|
-
- apply:
|
|
64
|
+
- apply review: `pr-shepherd apply review 123 --reply-thread-ids PRRT_kwDOSGizTs58XB1L --message "$DISMISS_MESSAGE" --require-sha "$HEAD_SHA"`
|
|
46
65
|
|
|
47
66
|
## Instructions
|
|
48
67
|
|
|
49
|
-
1. Decide for each item under `## Review threads` and `## Failing checks` whether a code change is warranted. If code changes are needed, apply edits, commit,
|
|
68
|
+
1. Decide for each item under `## Review threads` and `## Failing checks` whether a code change is warranted. If code changes are needed, apply edits, commit, push, then run the `apply review:` command.
|
|
50
69
|
2. For each failing check under `## Failing checks`: fetch logs when needed and decide whether to rerun or fix.
|
|
51
|
-
3.
|
|
70
|
+
3. Run the `apply review:` command shown above, substituting `$HEAD_SHA` and `$DISMISS_MESSAGE`.
|
|
52
71
|
4. Stop this iteration.
|
|
53
72
|
```
|
|
54
73
|
|
|
55
|
-
See [docs/actions.md](docs/actions.md) for the complete output contract.
|
|
74
|
+
See [docs/actions.md](docs/actions.md) for the complete output contract. Iterate/poll PR outcomes use exit codes `0` and `10`–`14`; command and GitHub failures use `sysexits.h` codes — [docs/exit-codes.md](docs/exit-codes.md).
|
|
56
75
|
|
|
57
76
|
## Workflow Assumptions
|
|
58
77
|
|
|
@@ -100,6 +119,7 @@ pr-shepherd 42 # poll until non-WAIT or timeout
|
|
|
100
119
|
pr-shepherd 42 --interval 60s --timeout 270s
|
|
101
120
|
pr-shepherd 42 --quiet-status # print only changed WAIT status snapshots
|
|
102
121
|
pr-shepherd 42 --until-terminal # continue through WAIT/MARK_READY until work or terminal state
|
|
122
|
+
pr-shepherd 42 --debounce 5m # wait 5m after first FIX_CODE, then return one batched tick
|
|
103
123
|
pr-shepherd 42 --ready-delay 15m
|
|
104
124
|
pr-shepherd iterate 42 # single tick
|
|
105
125
|
```
|
|
@@ -179,7 +199,7 @@ Replace `<version>` with a published version. Full config-file examples, tool sc
|
|
|
179
199
|
|
|
180
200
|
## Configuration
|
|
181
201
|
|
|
182
|
-
Create `.pr-shepherdrc.yml` in your project root
|
|
202
|
+
Create `.pr-shepherdrc.yml` in your project root, an ancestor directory, or `$HOME`. Every file on the walk is deep-merged; closer directories override farther ones.
|
|
183
203
|
|
|
184
204
|
```yaml
|
|
185
205
|
ignoreChecks:
|
|
@@ -231,9 +251,9 @@ TypeScript rules are loaded by the runtime's native TypeScript support; keep the
|
|
|
231
251
|
|
|
232
252
|
Ready-to-use examples for common patterns are in [`examples/classification/`](examples/classification/).
|
|
233
253
|
|
|
234
|
-
##
|
|
254
|
+
## CLI aliases
|
|
235
255
|
|
|
236
|
-
|
|
256
|
+
`poll`, `resolve`, `commit-suggestion`, `mark-files-as-viewed`, `journal`, `clean`, and `log-file` are CLI aliases. Prefer default polling/`iterate` in a shell and the MCP `iterate`, `apply`, and `build_suggestion_patch` tools in an agent client.
|
|
237
257
|
|
|
238
258
|
## Requirements
|
|
239
259
|
|
|
@@ -243,7 +263,7 @@ The legacy CLI subcommands `poll`, `resolve`, `commit-suggestion`, and `mark-fil
|
|
|
243
263
|
|
|
244
264
|
## Docs
|
|
245
265
|
|
|
246
|
-
Full reference: [docs/README.md](docs/README.md).
|
|
266
|
+
Full reference, grouped by the two jobs (gather context / emit actions): [docs/README.md](docs/README.md).
|
|
247
267
|
|
|
248
268
|
## Harness Ecosystem
|
|
249
269
|
|
package/bin/checks/triage.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* eslint-disable max-lines */
|
|
2
|
-
import {
|
|
2
|
+
import { restWithRateLimit, restText } from "../github/http.mjs";
|
|
3
3
|
const STARTUP_FAILURE_STATUS = "startup_failure";
|
|
4
4
|
const LOG_EXCERPT_CONTEXT_LINES = 16;
|
|
5
5
|
const LOG_EXCERPT_TAIL_LINES = 28;
|
|
@@ -43,10 +43,14 @@ async function fetchStartupFailureChecksUncached(repo, headSha, prNumber) {
|
|
|
43
43
|
const MAX_RUN_PAGES = 10;
|
|
44
44
|
const checks = [];
|
|
45
45
|
for (let page = 1; page <= MAX_RUN_PAGES; page++) {
|
|
46
|
-
const data = await
|
|
46
|
+
const { data, rateLimit } = await restWithRateLimit("GET", `/repos/${owner}/${name}/actions/runs?head_sha=${encodeURIComponent(headSha)}&status=${STARTUP_FAILURE_STATUS}&per_page=${perPage}&page=${page}`);
|
|
47
47
|
checks.push(...data.workflow_runs
|
|
48
48
|
.filter((run) => runBelongsToPr(run, prNumber, headSha))
|
|
49
49
|
.map(workflowRunToCheckRun));
|
|
50
|
+
if (rateLimit?.remaining === 0) {
|
|
51
|
+
process.stderr.write(`pr-shepherd: REST rate limit remaining is 0 while listing startup-failure runs for ${headSha} — detection may be incomplete\n`);
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
50
54
|
if (data.workflow_runs.length < perPage)
|
|
51
55
|
break;
|
|
52
56
|
if (page === MAX_RUN_PAGES) {
|
|
@@ -91,8 +95,12 @@ async function fetchJobsUncached(runId, repo) {
|
|
|
91
95
|
process.stderr.write(`pr-shepherd: job pagination cap (${MAX_JOB_PAGES * 100} jobs) reached for run ${runId} — triage may be incomplete\n`);
|
|
92
96
|
break;
|
|
93
97
|
}
|
|
94
|
-
const data = await
|
|
98
|
+
const { data, rateLimit } = await restWithRateLimit("GET", `/repos/${owner}/${name}/actions/runs/${runId}/jobs?filter=latest&per_page=${perPage}&page=${page}`);
|
|
95
99
|
allJobs.push(...data.jobs);
|
|
100
|
+
if (rateLimit?.remaining === 0) {
|
|
101
|
+
process.stderr.write(`pr-shepherd: REST rate limit remaining is 0 while listing jobs for run ${runId} — triage may be incomplete\n`);
|
|
102
|
+
break;
|
|
103
|
+
}
|
|
96
104
|
if (data.jobs.length < perPage)
|
|
97
105
|
break;
|
|
98
106
|
}
|
package/bin/cli/args.mjs
CHANGED
package/bin/cli/default-poll.mjs
CHANGED
|
@@ -177,7 +177,7 @@ Flags:
|
|
|
177
177
|
PR may be a number or GitHub pull request URL. When omitted, the current branch PR is inferred.
|
|
178
178
|
Exit code: 0 on success; nonzero on failure (sysexits.h — see docs/exit-codes.md).`;
|
|
179
179
|
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 code action; run another iterate tick later.\n MARK_READY Draft PR was marked ready for review.\n FIX_CODE Apply fixes, commit, push, and run the printed apply command.\n CANCEL Terminal state: merged/closed or ready-delay elapsed.\n ESCALATE Terminal state requiring human 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).";
|
|
180
|
-
readonly poll: "pr-shepherd poll\n\nRun iterate repeatedly
|
|
180
|
+
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 a single dot 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).";
|
|
181
181
|
readonly clean: `pr-shepherd clean
|
|
182
182
|
|
|
183
183
|
Remove pr-shepherd state files from PR_SHEPHERD_STATE_DIR.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
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 code action; run another iterate tick later.\n MARK_READY Draft PR was marked ready for review.\n FIX_CODE Apply fixes, commit, push, and run the printed apply command.\n CANCEL Terminal state: merged/closed or ready-delay elapsed.\n ESCALATE Terminal state requiring human 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
|
|
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 a single dot 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).";
|
|
3
3
|
/** Public help page for the default PR polling invocation. */
|
|
4
4
|
export declare const DEFAULT_USAGE: string;
|
|
@@ -34,16 +34,20 @@ Exit codes:
|
|
|
34
34
|
A command/validation/GitHub failure exits with a sysexits.h code instead (see docs/exit-codes.md).`;
|
|
35
35
|
export const POLL_USAGE = `pr-shepherd poll
|
|
36
36
|
|
|
37
|
-
Run iterate repeatedly
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
Run iterate repeatedly for WAIT ticks and during the FIX_CODE debounce window. Print only the
|
|
38
|
+
final tick to stdout.
|
|
39
|
+
Poll exits as soon as iterate returns MARK_READY, CANCEL, or ESCALATE, or when timeout
|
|
40
|
+
returns the last WAIT result. FIX_CODE starts a --debounce settle window (default 1m): poll keeps
|
|
41
|
+
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.
|
|
40
43
|
|
|
41
44
|
Usage:
|
|
42
45
|
pr-shepherd poll [PR] [poll-flags] [iterate-flags]
|
|
43
46
|
|
|
44
47
|
Poll flags:
|
|
45
48
|
--interval <duration> Sleep between WAIT ticks. Bare number = seconds. Default: 60s.
|
|
46
|
-
--timeout <duration> Maximum wall-clock wait. Bare number = seconds. Default: 4.5m.
|
|
49
|
+
--timeout <duration> Maximum wall-clock wait for WAIT ticks. Bare number = seconds. Default: 4.5m.
|
|
50
|
+
--debounce <duration> Settle window after first FIX_CODE before returning. Bare number = seconds. Default: 60s. 0 disables.
|
|
47
51
|
--quiet-status During WAIT polling, print only changed status snapshots.
|
|
48
52
|
--until-terminal Continue through WAIT/MARK_READY until FIX_CODE/CANCEL/ESCALATE.
|
|
49
53
|
|
|
@@ -57,9 +61,10 @@ Forwarded iterate flags:
|
|
|
57
61
|
--help, -h Print this help and exit before GitHub, git, config, or log I/O.
|
|
58
62
|
|
|
59
63
|
Durations accept s/m/h suffixes: 30s, 4.5m, 1h. A bare number uses each flag's default unit (seconds
|
|
60
|
-
for --interval/--timeout, minutes for --ready-delay/--stall-timeout); decimals are allowed only with
|
|
64
|
+
for --interval/--timeout/--debounce, minutes for --ready-delay/--stall-timeout); decimals are allowed only with
|
|
61
65
|
an explicit unit (4.5m).
|
|
62
66
|
Each WAIT tick writes a single dot to stderr by default; --quiet-status prints only changed WAIT snapshots, and --verbose emits detailed per-tick lines.
|
|
67
|
+
FIX_CODE debounce writes a remaining-seconds line to stderr. --timeout does not cut an in-flight debounce short.
|
|
63
68
|
With --until-terminal, --timeout is ignored for WAIT ticks and polling continues until FIX_CODE, CANCEL, or ESCALATE.
|
|
64
69
|
|
|
65
70
|
Exit codes: same as iterate (the final tick's action/reason decides the code).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const TOP_USAGE = "pr-shepherd\n\nAutonomous PR CI monitor and review-comment resolver for agentic coding tools.\n\nUsage:\n pr-shepherd --version | -v\n pr-shepherd --help | -h\n pr-shepherd [PR] [poll-flags] [iterate-flags]\n pr-shepherd iterate [PR] [iterate-flags]\n pr-shepherd apply review [PR] [review-flags]\n pr-shepherd apply files [PR] [files...] [--tests] [--match REGEX]\n pr-shepherd apply journal [PR] <item> [--dry-run] [--format text|json]\n pr-shepherd build-suggestion-patch [PR] --thread-id ID --message MSG [flags]\n pr-shepherd admin clean <pr|branch|current|repo|all> [value] [flags]\n pr-shepherd admin log-file [--format text|json]\n\nCommands:\n [PR] Poll until non-WAIT or timeout. This is the default command.\n iterate Run one iterate tick (single-tick alias).\n apply review Apply review-state mutations after fixes.\n apply files Mark changed files as viewed in GitHub.\n apply journal Append a list item to the ## Shepherd Journal section of a PR body.\n build-suggestion-patch\n Convert one GitHub suggestion thread into a patch and commit instructions.\n admin clean Remove pr-shepherd state files.\n admin log-file Print the per-worktree debug log path.\n\nPR argument:\n PR may be a number such as 42 or a GitHub pull request URL.\n When omitted, pr-shepherd infers the current branch's pull request.\n\nCommon flags:\n --format text|json Output Markdown text or JSON. Default: text.\n --verbose Include verbose iterate fields and detailed poll-tick lines.\n --help, -h Print help and exit before any GitHub, git, config, or log I/O.\n\nIterate flags:\n --ready-delay <duration> Settle window before a clean PR cancels. Bare number = minutes. Example: 15m.\n --stall-timeout <duration> Escalate repeated unchanged failures after this duration. Bare number = minutes. 0 disables.\n --no-auto-mark-ready Do not convert draft PRs to ready for review.\n --no-auto-cancel-actionable Do not cancel in-progress runs before actionable fixes.\n\nPolling flags:\n --interval <duration> Delay between WAIT ticks. Bare number = seconds. Default: 60s.\n --timeout <duration> Poll wall-clock cap. Bare number = seconds. Default: 4.5m.\n --quiet-status During WAIT polling, print only changed status snapshots.\n --until-terminal Continue through WAIT/MARK_READY until FIX_CODE/CANCEL/ESCALATE.\n\nClean variants:\n pr [number] Remove state for one PR. Defaults to current branch PR.\n branch [name] Remove state for a branch's PR. Defaults to current branch.\n current Alias for branch against the current branch.\n repo Remove all state for the current repository.\n all Remove all pr-shepherd state.\n\nExit codes: 0 done, 10-19 PR state, 64-78 shepherd failed (sysexits.h).\n 0 CANCEL (merged or ready-delay elapsed)\n 10 WAIT\n 11 MARK_READY\n 12 FIX_CODE\n 13 ESCALATE\n 14 CANCEL (closed without merging)\nSee docs/exit-codes.md for the full sysexits.h error-code table.\n\nDuration examples: 30s, 4.5m, 1h. A bare number uses each flag's default unit (see above); decimals are allowed with an explicit unit (4.5m).\n\nRun 'pr-shepherd <command> --help' for command-specific details.";
|
|
1
|
+
export declare const TOP_USAGE = "pr-shepherd\n\nAutonomous PR CI monitor and review-comment resolver for agentic coding tools.\n\nUsage:\n pr-shepherd --version | -v\n pr-shepherd --help | -h\n pr-shepherd [PR] [poll-flags] [iterate-flags]\n pr-shepherd iterate [PR] [iterate-flags]\n pr-shepherd apply review [PR] [review-flags]\n pr-shepherd apply files [PR] [files...] [--tests] [--match REGEX]\n pr-shepherd apply journal [PR] <item> [--dry-run] [--format text|json]\n pr-shepherd build-suggestion-patch [PR] --thread-id ID --message MSG [flags]\n pr-shepherd admin clean <pr|branch|current|repo|all> [value] [flags]\n pr-shepherd admin log-file [--format text|json]\n\nCommands:\n [PR] Poll until non-WAIT or timeout. This is the default command.\n iterate Run one iterate tick (single-tick alias).\n apply review Apply review-state mutations after fixes.\n apply files Mark changed files as viewed in GitHub.\n apply journal Append a list item to the ## Shepherd Journal section of a PR body.\n build-suggestion-patch\n Convert one GitHub suggestion thread into a patch and commit instructions.\n admin clean Remove pr-shepherd state files.\n admin log-file Print the per-worktree debug log path.\n\nPR argument:\n PR may be a number such as 42 or a GitHub pull request URL.\n When omitted, pr-shepherd infers the current branch's pull request.\n\nCommon flags:\n --format text|json Output Markdown text or JSON. Default: text.\n --verbose Include verbose iterate fields and detailed poll-tick lines.\n --help, -h Print help and exit before any GitHub, git, config, or log I/O.\n\nIterate flags:\n --ready-delay <duration> Settle window before a clean PR cancels. Bare number = minutes. Example: 15m.\n --stall-timeout <duration> Escalate repeated unchanged failures after this duration. Bare number = minutes. 0 disables.\n --no-auto-mark-ready Do not convert draft PRs to ready for review.\n --no-auto-cancel-actionable Do not cancel in-progress runs before actionable fixes.\n\nPolling flags:\n --interval <duration> Delay between WAIT ticks. Bare number = seconds. Default: 60s.\n --timeout <duration> Poll wall-clock cap for WAIT ticks. Bare number = seconds. Default: 4.5m.\n --debounce <duration> Settle window after first FIX_CODE before returning. Bare number = seconds. Default: 60s. 0 disables.\n --quiet-status During WAIT polling, print only changed status snapshots.\n --until-terminal Continue through WAIT/MARK_READY until FIX_CODE/CANCEL/ESCALATE.\n\nClean variants:\n pr [number] Remove state for one PR. Defaults to current branch PR.\n branch [name] Remove state for a branch's PR. Defaults to current branch.\n current Alias for branch against the current branch.\n repo Remove all state for the current repository.\n all Remove all pr-shepherd state.\n\nExit codes: 0 done, 10-19 PR state, 64-78 shepherd failed (sysexits.h).\n 0 CANCEL (merged or ready-delay elapsed)\n 10 WAIT\n 11 MARK_READY\n 12 FIX_CODE\n 13 ESCALATE\n 14 CANCEL (closed without merging)\nSee docs/exit-codes.md for the full sysexits.h error-code table.\n\nDuration examples: 30s, 4.5m, 1h. A bare number uses each flag's default unit (see above); decimals are allowed with an explicit unit (4.5m).\n\nRun 'pr-shepherd <command> --help' for command-specific details.";
|
|
@@ -42,7 +42,8 @@ Iterate flags:
|
|
|
42
42
|
|
|
43
43
|
Polling flags:
|
|
44
44
|
--interval <duration> Delay between WAIT ticks. Bare number = seconds. Default: 60s.
|
|
45
|
-
--timeout <duration> Poll wall-clock cap. Bare number = seconds. Default: 4.5m.
|
|
45
|
+
--timeout <duration> Poll wall-clock cap for WAIT ticks. Bare number = seconds. Default: 4.5m.
|
|
46
|
+
--debounce <duration> Settle window after first FIX_CODE before returning. Bare number = seconds. Default: 60s. 0 disables.
|
|
46
47
|
--quiet-status During WAIT polling, print only changed status snapshots.
|
|
47
48
|
--until-terminal Continue through WAIT/MARK_READY until FIX_CODE/CANCEL/ESCALATE.
|
|
48
49
|
|
package/bin/cli/help.d.mts
CHANGED
|
@@ -177,7 +177,7 @@ Flags:
|
|
|
177
177
|
PR may be a number or GitHub pull request URL. When omitted, the current branch PR is inferred.
|
|
178
178
|
Exit code: 0 on success; nonzero on failure (sysexits.h — see docs/exit-codes.md).`;
|
|
179
179
|
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 code action; run another iterate tick later.\n MARK_READY Draft PR was marked ready for review.\n FIX_CODE Apply fixes, commit, push, and run the printed apply command.\n CANCEL Terminal state: merged/closed or ready-delay elapsed.\n ESCALATE Terminal state requiring human 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).";
|
|
180
|
-
readonly poll: "pr-shepherd poll\n\nRun iterate repeatedly
|
|
180
|
+
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 a single dot 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).";
|
|
181
181
|
readonly clean: `pr-shepherd clean
|
|
182
182
|
|
|
183
183
|
Remove pr-shepherd state files from PR_SHEPHERD_STATE_DIR.
|
|
@@ -228,7 +228,7 @@ Flags:
|
|
|
228
228
|
|
|
229
229
|
Exit code: 0 on success (including no-change no-op); nonzero on failure (sysexits.h — see docs/exit-codes.md).`;
|
|
230
230
|
readonly "log-file": "pr-shepherd log-file\n\nPrint the per-worktree append-only debug log path for the current repository.\nThe log is created by the first non-help pr-shepherd command that initializes logging.\n\nUsage:\n pr-shepherd log-file [--format text|json]\n\nFlags:\n --format text|json Print a raw path or {\"path\": \"...\"} JSON. Default: text.\n --help, -h Print this help and exit before logging setup.\n\nEnvironment:\n PR_SHEPHERD_LOG_DISABLED=1 disables logging.\n PR_SHEPHERD_STATE_DIR overrides the base state directory.\n\nExit code: 0 on success; 1 if repository identity cannot be resolved.";
|
|
231
|
-
readonly top: "pr-shepherd\n\nAutonomous PR CI monitor and review-comment resolver for agentic coding tools.\n\nUsage:\n pr-shepherd --version | -v\n pr-shepherd --help | -h\n pr-shepherd [PR] [poll-flags] [iterate-flags]\n pr-shepherd iterate [PR] [iterate-flags]\n pr-shepherd apply review [PR] [review-flags]\n pr-shepherd apply files [PR] [files...] [--tests] [--match REGEX]\n pr-shepherd apply journal [PR] <item> [--dry-run] [--format text|json]\n pr-shepherd build-suggestion-patch [PR] --thread-id ID --message MSG [flags]\n pr-shepherd admin clean <pr|branch|current|repo|all> [value] [flags]\n pr-shepherd admin log-file [--format text|json]\n\nCommands:\n [PR] Poll until non-WAIT or timeout. This is the default command.\n iterate Run one iterate tick (single-tick alias).\n apply review Apply review-state mutations after fixes.\n apply files Mark changed files as viewed in GitHub.\n apply journal Append a list item to the ## Shepherd Journal section of a PR body.\n build-suggestion-patch\n Convert one GitHub suggestion thread into a patch and commit instructions.\n admin clean Remove pr-shepherd state files.\n admin log-file Print the per-worktree debug log path.\n\nPR argument:\n PR may be a number such as 42 or a GitHub pull request URL.\n When omitted, pr-shepherd infers the current branch's pull request.\n\nCommon flags:\n --format text|json Output Markdown text or JSON. Default: text.\n --verbose Include verbose iterate fields and detailed poll-tick lines.\n --help, -h Print help and exit before any GitHub, git, config, or log I/O.\n\nIterate flags:\n --ready-delay <duration> Settle window before a clean PR cancels. Bare number = minutes. Example: 15m.\n --stall-timeout <duration> Escalate repeated unchanged failures after this duration. Bare number = minutes. 0 disables.\n --no-auto-mark-ready Do not convert draft PRs to ready for review.\n --no-auto-cancel-actionable Do not cancel in-progress runs before actionable fixes.\n\nPolling flags:\n --interval <duration> Delay between WAIT ticks. Bare number = seconds. Default: 60s.\n --timeout <duration> Poll wall-clock cap. Bare number = seconds. Default: 4.5m.\n --quiet-status During WAIT polling, print only changed status snapshots.\n --until-terminal Continue through WAIT/MARK_READY until FIX_CODE/CANCEL/ESCALATE.\n\nClean variants:\n pr [number] Remove state for one PR. Defaults to current branch PR.\n branch [name] Remove state for a branch's PR. Defaults to current branch.\n current Alias for branch against the current branch.\n repo Remove all state for the current repository.\n all Remove all pr-shepherd state.\n\nExit codes: 0 done, 10-19 PR state, 64-78 shepherd failed (sysexits.h).\n 0 CANCEL (merged or ready-delay elapsed)\n 10 WAIT\n 11 MARK_READY\n 12 FIX_CODE\n 13 ESCALATE\n 14 CANCEL (closed without merging)\nSee docs/exit-codes.md for the full sysexits.h error-code table.\n\nDuration examples: 30s, 4.5m, 1h. A bare number uses each flag's default unit (see above); decimals are allowed with an explicit unit (4.5m).\n\nRun 'pr-shepherd <command> --help' for command-specific details.";
|
|
231
|
+
readonly top: "pr-shepherd\n\nAutonomous PR CI monitor and review-comment resolver for agentic coding tools.\n\nUsage:\n pr-shepherd --version | -v\n pr-shepherd --help | -h\n pr-shepherd [PR] [poll-flags] [iterate-flags]\n pr-shepherd iterate [PR] [iterate-flags]\n pr-shepherd apply review [PR] [review-flags]\n pr-shepherd apply files [PR] [files...] [--tests] [--match REGEX]\n pr-shepherd apply journal [PR] <item> [--dry-run] [--format text|json]\n pr-shepherd build-suggestion-patch [PR] --thread-id ID --message MSG [flags]\n pr-shepherd admin clean <pr|branch|current|repo|all> [value] [flags]\n pr-shepherd admin log-file [--format text|json]\n\nCommands:\n [PR] Poll until non-WAIT or timeout. This is the default command.\n iterate Run one iterate tick (single-tick alias).\n apply review Apply review-state mutations after fixes.\n apply files Mark changed files as viewed in GitHub.\n apply journal Append a list item to the ## Shepherd Journal section of a PR body.\n build-suggestion-patch\n Convert one GitHub suggestion thread into a patch and commit instructions.\n admin clean Remove pr-shepherd state files.\n admin log-file Print the per-worktree debug log path.\n\nPR argument:\n PR may be a number such as 42 or a GitHub pull request URL.\n When omitted, pr-shepherd infers the current branch's pull request.\n\nCommon flags:\n --format text|json Output Markdown text or JSON. Default: text.\n --verbose Include verbose iterate fields and detailed poll-tick lines.\n --help, -h Print help and exit before any GitHub, git, config, or log I/O.\n\nIterate flags:\n --ready-delay <duration> Settle window before a clean PR cancels. Bare number = minutes. Example: 15m.\n --stall-timeout <duration> Escalate repeated unchanged failures after this duration. Bare number = minutes. 0 disables.\n --no-auto-mark-ready Do not convert draft PRs to ready for review.\n --no-auto-cancel-actionable Do not cancel in-progress runs before actionable fixes.\n\nPolling flags:\n --interval <duration> Delay between WAIT ticks. Bare number = seconds. Default: 60s.\n --timeout <duration> Poll wall-clock cap for WAIT ticks. Bare number = seconds. Default: 4.5m.\n --debounce <duration> Settle window after first FIX_CODE before returning. Bare number = seconds. Default: 60s. 0 disables.\n --quiet-status During WAIT polling, print only changed status snapshots.\n --until-terminal Continue through WAIT/MARK_READY until FIX_CODE/CANCEL/ESCALATE.\n\nClean variants:\n pr [number] Remove state for one PR. Defaults to current branch PR.\n branch [name] Remove state for a branch's PR. Defaults to current branch.\n current Alias for branch against the current branch.\n repo Remove all state for the current repository.\n all Remove all pr-shepherd state.\n\nExit codes: 0 done, 10-19 PR state, 64-78 shepherd failed (sysexits.h).\n 0 CANCEL (merged or ready-delay elapsed)\n 10 WAIT\n 11 MARK_READY\n 12 FIX_CODE\n 13 ESCALATE\n 14 CANCEL (closed without merging)\nSee docs/exit-codes.md for the full sysexits.h error-code table.\n\nDuration examples: 30s, 4.5m, 1h. A bare number uses each flag's default unit (see above); decimals are allowed with an explicit unit (4.5m).\n\nRun 'pr-shepherd <command> --help' for command-specific details.";
|
|
232
232
|
};
|
|
233
233
|
/** Resolve help keys for nested public commands before any command I/O. */
|
|
234
234
|
export declare function helpKeyForArgs(args: string[]): keyof typeof USAGE;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
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
|
+
import { formatMergeRequirementLines } from "../merge-status/requirements-format.mjs";
|
|
4
5
|
function formatActivityLine(result) {
|
|
5
6
|
const activity = result.activity ?? {
|
|
6
7
|
commitCount: 0,
|
|
@@ -112,8 +113,12 @@ export function formatIterateResult(result, opts) {
|
|
|
112
113
|
}
|
|
113
114
|
const requiredLine = requiredParts.length > 0 ? `**required** ${requiredParts.join(", ")}` : null;
|
|
114
115
|
const headerLines = [heading, "", baseLine, summaryLine];
|
|
115
|
-
if (
|
|
116
|
+
if (result.mergeRequirements) {
|
|
117
|
+
headerLines.push(...formatMergeRequirementLines(result.mergeRequirements));
|
|
118
|
+
}
|
|
119
|
+
else if (requiredLine) {
|
|
116
120
|
headerLines.push(requiredLine);
|
|
121
|
+
}
|
|
117
122
|
if (result.ignoredNames && result.ignoredNames.length > 0) {
|
|
118
123
|
const names = result.ignoredNames.map((n) => "`" + n + "`").join(", ");
|
|
119
124
|
headerLines.push(`**ignored** ${names}`);
|
|
@@ -141,8 +146,12 @@ export function formatIterateResult(result, opts) {
|
|
|
141
146
|
]);
|
|
142
147
|
case "cancel": {
|
|
143
148
|
const cancelHeaderLines = [`${heading} — ${result.reason}`, "", baseLine, summaryLine];
|
|
144
|
-
if (
|
|
149
|
+
if (result.mergeRequirements) {
|
|
150
|
+
cancelHeaderLines.push(...formatMergeRequirementLines(result.mergeRequirements));
|
|
151
|
+
}
|
|
152
|
+
else if (requiredLine) {
|
|
145
153
|
cancelHeaderLines.push(requiredLine);
|
|
154
|
+
}
|
|
146
155
|
if (result.ignoredNames && result.ignoredNames.length > 0) {
|
|
147
156
|
const ignoredStr = result.ignoredNames.map((n) => "`" + n + "`").join(", ");
|
|
148
157
|
cancelHeaderLines.push(`**ignored** ${ignoredStr}`);
|
package/bin/cli/iterate-lean.mjs
CHANGED
|
@@ -41,6 +41,7 @@ export function projectIterateLean(result, opts) {
|
|
|
41
41
|
}),
|
|
42
42
|
...(result.baseBranch && { baseBranch: result.baseBranch }),
|
|
43
43
|
...(result.branchProtection !== null && { branchProtection: result.branchProtection }),
|
|
44
|
+
...(result.mergeRequirements && { mergeRequirements: result.mergeRequirements }),
|
|
44
45
|
...(hasActivity && {
|
|
45
46
|
activity: {
|
|
46
47
|
commitCount: activity.commitCount,
|
package/bin/cli/poll-handler.mjs
CHANGED
|
@@ -7,6 +7,7 @@ import { parseIterateFlags } from "./iterate-flags.mjs";
|
|
|
7
7
|
import { emitIterateResult } from "./iterate-emitter.mjs";
|
|
8
8
|
const DEFAULT_POLL_INTERVAL_SECONDS = 60;
|
|
9
9
|
const DEFAULT_POLL_TIMEOUT_SECONDS = 270;
|
|
10
|
+
const DEFAULT_POLL_DEBOUNCE_SECONDS = 60;
|
|
10
11
|
export async function handlePoll(args) {
|
|
11
12
|
const { prNumber, global: globalOpts, extra } = parseCommonArgs(args);
|
|
12
13
|
const cfg = loadConfig();
|
|
@@ -23,6 +24,11 @@ export async function handlePoll(args) {
|
|
|
23
24
|
if (timeoutSuffix === null)
|
|
24
25
|
return;
|
|
25
26
|
const timeoutSeconds = parseDurationToSeconds(timeoutSuffix ?? "", DEFAULT_POLL_TIMEOUT_SECONDS);
|
|
27
|
+
const debounceStr = getFlag(extra, "--debounce");
|
|
28
|
+
const debounceSuffix = validateSecondsDurationFlag("pr-shepherd", "--debounce", debounceStr, hasFlag(extra, "--debounce"), { allowZero: true });
|
|
29
|
+
if (debounceSuffix === null)
|
|
30
|
+
return;
|
|
31
|
+
const debounceSeconds = parseDurationToSeconds(debounceSuffix ?? "", DEFAULT_POLL_DEBOUNCE_SECONDS, { allowZero: true });
|
|
26
32
|
const result = await runPoll({
|
|
27
33
|
...globalOpts,
|
|
28
34
|
prNumber,
|
|
@@ -32,6 +38,7 @@ export async function handlePoll(args) {
|
|
|
32
38
|
noAutoCancelActionable: flags.noAutoCancelActionable,
|
|
33
39
|
intervalSeconds,
|
|
34
40
|
timeoutSeconds,
|
|
41
|
+
debounceSeconds,
|
|
35
42
|
quietStatus: hasFlag(extra, "--quiet-status"),
|
|
36
43
|
untilTerminal: hasFlag(extra, "--until-terminal"),
|
|
37
44
|
});
|
package/bin/commands/check.d.mts
CHANGED
package/bin/commands/check.mjs
CHANGED
|
@@ -38,7 +38,9 @@ export async function runCheck(opts) {
|
|
|
38
38
|
if (mergeStatus.state === "MERGED" || mergeStatus.state === "CLOSED") {
|
|
39
39
|
return buildTerminalReport(prNumber, repo, batchData, mergeStatus, mergeStatus.state);
|
|
40
40
|
}
|
|
41
|
-
const startupFailureChecks =
|
|
41
|
+
const startupFailureChecks = result.checkSuitesComplete
|
|
42
|
+
? []
|
|
43
|
+
: await fetchStartupFailureChecks(repo, batchData.headRefOid, prNumber);
|
|
42
44
|
const allChecks = mergeStartupFailureChecks(batchData.checks, startupFailureChecks);
|
|
43
45
|
const classifiedChecks = classifyChecks(allChecks);
|
|
44
46
|
const verdict = getCiVerdict(classifiedChecks);
|
|
@@ -80,27 +82,29 @@ export async function runCheck(opts) {
|
|
|
80
82
|
}
|
|
81
83
|
const changesRequestedReviewVisibility = classifyChangesRequestedReviewsForDisplay(batchData.changesRequestedReviews.filter((r) => !partition.suppressedChangesRequestedIds.has(r.id)), seenMap, botUsernames);
|
|
82
84
|
const approvedReviewVisibility = classifyReviewsForDisplay(batchData.approvedReviews, seenMap);
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
.
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
.
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
.
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
.
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
85
|
+
if (opts.persistSeen !== false) {
|
|
86
|
+
await Promise.allSettled([
|
|
87
|
+
...firstLookComments.map((c) => markSeen(stateKey, c.id, c.body)),
|
|
88
|
+
...threadVisibility.toMarkSeen.map((t) => markSeen(stateKey, t.id, threadTranscriptBody(t))),
|
|
89
|
+
...visibleCommentClassification.toMarkSeen.map((c) => markSeen(stateKey, c.id, c.body)),
|
|
90
|
+
...[...firstLookSummaries, ...editedSummaries].map((r) => markSeen(stateKey, r.id, r.body)),
|
|
91
|
+
...changesRequestedReviewVisibility.toMarkSeen.map((r) => markSeen(stateKey, r.id, r.body)),
|
|
92
|
+
...approvedReviewVisibility.toMarkSeen.map((r) => markSeen(stateKey, r.id, r.body)),
|
|
93
|
+
...batchData.comments
|
|
94
|
+
.filter((c) => partition.suppressedCommentIds.has(c.id))
|
|
95
|
+
.map((c) => markSeen(stateKey, c.id, c.body)),
|
|
96
|
+
...batchData.reviewThreads
|
|
97
|
+
.filter((t) => partition.suppressedThreadIds.has(t.id))
|
|
98
|
+
.map((t) => markSeen(stateKey, t.id, threadTranscriptBody(t))),
|
|
99
|
+
...batchData.reviewSummaries
|
|
100
|
+
.filter((r) => partition.suppressedReviewSummaryIds.has(r.id))
|
|
101
|
+
.map((r) => markSeen(stateKey, r.id, r.body)),
|
|
102
|
+
...batchData.changesRequestedReviews
|
|
103
|
+
.filter((r) => partition.suppressedChangesRequestedIds.has(r.id))
|
|
104
|
+
.map((r) => markSeen(stateKey, r.id, r.body)),
|
|
105
|
+
]);
|
|
106
|
+
await markReviewInlineThreadMarkers(stateKey, batchData.reviewThreads);
|
|
107
|
+
}
|
|
104
108
|
const { threadIds: ruleAutoResolveThreadIds, commentIds: ruleAutoResolveCommentIds, reviewSummaryIds: ruleAutoResolveReviewSummaryIds, } = await remainingRuleAutoResolveIds(partition, opts.autoMinimizeSuppressed);
|
|
105
109
|
const changesRequestedReviews = changesRequestedReviewVisibility.visible;
|
|
106
110
|
const changesRequestedReviewCount = batchData.changesRequestedReviews.filter((r) => !partition.suppressedChangesRequestedIds.has(r.id)).length;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { execFile as execFileCb } from "node:child_process";
|
|
2
2
|
import { readFile } from "node:fs/promises";
|
|
3
|
-
import { resolve } from "node:path";
|
|
3
|
+
import { relative, resolve } from "node:path";
|
|
4
4
|
import { promisify } from "node:util";
|
|
5
5
|
import { getRepoInfo, getCurrentPrNumber, getCurrentBranch } from "../github/client.mjs";
|
|
6
|
-
import {
|
|
6
|
+
import { fetchSuggestionThread } from "../github/suggestion-thread.mjs";
|
|
7
7
|
import { parseSuggestion, isCommittableSuggestion } from "../suggestions/parse.mjs";
|
|
8
8
|
import { buildUnifiedDiff } from "../suggestions/patch.mjs";
|
|
9
9
|
import { EXIT, ShepherdError } from "../exit-codes.mjs";
|
|
@@ -28,7 +28,7 @@ export async function runCommitSuggestion(opts) {
|
|
|
28
28
|
cwd: getExecutionCwd(),
|
|
29
29
|
});
|
|
30
30
|
const localHeadSha = localHeadOut.trim();
|
|
31
|
-
const
|
|
31
|
+
const data = await fetchSuggestionThread(prNumber, repo, opts.threadId);
|
|
32
32
|
if (!data.headRepoWithOwner) {
|
|
33
33
|
throw new ShepherdError(`PR #${prNumber} head repository is unavailable (fork may have been deleted).`, EXIT.UNAVAILABLE);
|
|
34
34
|
}
|
|
@@ -40,7 +40,7 @@ export async function runCommitSuggestion(opts) {
|
|
|
40
40
|
throw new ShepherdError(`Local HEAD ${localHeadSha} does not match PR head ${data.headRefOid}. ` +
|
|
41
41
|
`Pull/rebase "${data.headRefName}" to the latest PR head and try again.`, EXIT.UNAVAILABLE);
|
|
42
42
|
}
|
|
43
|
-
const thread = data.
|
|
43
|
+
const thread = data.thread;
|
|
44
44
|
if (!thread) {
|
|
45
45
|
throw new ShepherdError(`Thread ${opts.threadId} not found on PR #${prNumber}.`, EXIT.UNAVAILABLE);
|
|
46
46
|
}
|
|
@@ -73,7 +73,13 @@ export async function runCommitSuggestion(opts) {
|
|
|
73
73
|
const startLine = thread.startLine ?? thread.line;
|
|
74
74
|
const endLine = thread.line;
|
|
75
75
|
const filePath = thread.path;
|
|
76
|
-
const
|
|
76
|
+
const cwd = getEffectiveCwd();
|
|
77
|
+
const resolvedPath = resolve(cwd, filePath);
|
|
78
|
+
const rel = relative(cwd, resolvedPath);
|
|
79
|
+
if (rel.startsWith("..") || rel === "") {
|
|
80
|
+
throw new ShepherdError(`Thread ${opts.threadId} path escapes the working tree.`, EXIT.UNAVAILABLE);
|
|
81
|
+
}
|
|
82
|
+
const originalContent = await readFile(resolvedPath, "utf8");
|
|
77
83
|
const patch = buildUnifiedDiff({
|
|
78
84
|
path: filePath,
|
|
79
85
|
originalContent,
|
|
@@ -166,7 +166,7 @@ export async function handleFixCode(ctx) {
|
|
|
166
166
|
cancelled,
|
|
167
167
|
};
|
|
168
168
|
const result = await applyStallGuard(stallKey, stallTimeoutSeconds, headSha, base, prNumber, prospectiveResult, report, reviewSummaryIds);
|
|
169
|
-
if (result.action === "fix_code") {
|
|
169
|
+
if (result.action === "fix_code" && opts.persistSeen !== false) {
|
|
170
170
|
await Promise.allSettled(result.fix.checks.flatMap((ch) => (ch.annotations ?? []).map((a) => markSeen(stallKey, a.id, annotationMarkerBody(a)))));
|
|
171
171
|
}
|
|
172
172
|
return result;
|
|
@@ -11,3 +11,4 @@ export declare function buildActiveChecks(report: ShepherdReport): ActiveCheck[]
|
|
|
11
11
|
export declare function tryCancelRun(runId: string, owner: string, repo: string): Promise<string | null>;
|
|
12
12
|
export declare function getCurrentHeadSha(): Promise<string | null>;
|
|
13
13
|
export declare function buildWaitLog(base: IterateResultBase): string;
|
|
14
|
+
export declare function blockedCancelNote(base: IterateResultBase): string;
|
|
@@ -2,6 +2,7 @@ import { execFile as execFileCb } from "node:child_process";
|
|
|
2
2
|
import { promisify } from "node:util";
|
|
3
3
|
import { rest } from "../../github/http.mjs";
|
|
4
4
|
import { getExecutionCwd } from "../../execution-context.mjs";
|
|
5
|
+
import { blockedReasonFromRequirements } from "../../merge-status/requirements-format.mjs";
|
|
5
6
|
const execFile = promisify(execFileCb);
|
|
6
7
|
export { buildAutoCancelRunIdsWithOptions, buildInProgressRunIds, buildRunProtection, } from "./reruns.mjs";
|
|
7
8
|
export function buildSummary(report) {
|
|
@@ -40,6 +41,7 @@ export function buildTerminalCancelResult(report) {
|
|
|
40
41
|
summary: buildSummary(report),
|
|
41
42
|
baseBranch: report.baseBranch,
|
|
42
43
|
branchProtection: report.branchProtection,
|
|
44
|
+
mergeRequirements: report.mergeStatus.mergeRequirements,
|
|
43
45
|
checks: buildRelevantChecks(report),
|
|
44
46
|
inProgressChecks: buildActiveChecks(report),
|
|
45
47
|
...buildSuppressedCheckFields(report),
|
|
@@ -134,14 +136,15 @@ export function buildWaitLog(base) {
|
|
|
134
136
|
.join(", ")}`);
|
|
135
137
|
}
|
|
136
138
|
switch (base.mergeStatus) {
|
|
137
|
-
case "BLOCKED":
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
else
|
|
139
|
+
case "BLOCKED": {
|
|
140
|
+
const fromRules = blockedReasonFromRequirements(base.mergeRequirements);
|
|
141
|
+
if (fromRules)
|
|
142
|
+
parts.push(fromRules);
|
|
143
|
+
else if (!base.blockingBotReviewInProgress) {
|
|
143
144
|
parts.push("awaiting human review or branch protection");
|
|
145
|
+
}
|
|
144
146
|
break;
|
|
147
|
+
}
|
|
145
148
|
case "BEHIND":
|
|
146
149
|
parts.push("branch is behind base");
|
|
147
150
|
break;
|
|
@@ -157,3 +160,9 @@ export function buildWaitLog(base) {
|
|
|
157
160
|
}
|
|
158
161
|
return parts.join(" — ");
|
|
159
162
|
}
|
|
163
|
+
export function blockedCancelNote(base) {
|
|
164
|
+
if (base.mergeStatus !== "BLOCKED")
|
|
165
|
+
return "has been ready for review";
|
|
166
|
+
const fromRules = blockedReasonFromRequirements(base.mergeRequirements);
|
|
167
|
+
return fromRules ? `is ${fromRules}` : "is awaiting human review or branch protection resolution";
|
|
168
|
+
}
|