pr-shepherd 0.52.0 → 0.53.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 +17 -12
- 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 +4 -3
- package/bin/cli/help-top-page.d.mts +1 -1
- package/bin/cli/help-top-page.mjs +3 -2
- package/bin/cli/help.d.mts +2 -2
- package/bin/cli/iterate-instructions.mjs +22 -0
- package/bin/cli/iterate-lean.mjs +1 -0
- package/bin/cli/poll-summary-formatter.mjs +4 -3
- package/bin/cli/runner.d.mts +1 -0
- package/bin/cli/runner.mjs +3 -1
- package/bin/commands/check.mjs +13 -4
- package/bin/commands/clean.mjs +7 -13
- package/bin/commands/iterate/api-usage.mjs +2 -2
- package/bin/commands/iterate/check-instructions.d.mts +2 -2
- package/bin/commands/iterate/check-instructions.mjs +11 -7
- package/bin/commands/iterate/escalate.mjs +4 -0
- package/bin/commands/iterate/fix-code.mjs +6 -1
- package/bin/commands/iterate/helpers.d.mts +0 -1
- package/bin/commands/iterate/helpers.mjs +0 -15
- package/bin/commands/iterate/index.mjs +48 -27
- package/bin/commands/iterate/merge-state.mjs +6 -4
- package/bin/commands/iterate/native-stack-rebase.d.mts +34 -0
- package/bin/commands/iterate/native-stack-rebase.mjs +43 -0
- package/bin/commands/iterate/parent-first.d.mts +6 -7
- package/bin/commands/iterate/parent-first.mjs +10 -54
- package/bin/commands/iterate/render.d.mts +1 -1
- package/bin/commands/iterate/render.mjs +7 -12
- package/bin/commands/iterate/stale-ancestry.d.mts +1 -1
- package/bin/commands/iterate/stale-ancestry.mjs +10 -7
- package/bin/commands/iterate/stall.mjs +40 -3
- package/bin/commands/poll-progress.d.mts +5 -1
- package/bin/commands/poll-progress.mjs +7 -1
- package/bin/commands/poll-quota.mjs +2 -2
- package/bin/commands/poll-summary-instructions.d.mts +6 -1
- package/bin/commands/poll-summary-instructions.mjs +71 -122
- package/bin/commands/poll-summary.mjs +4 -2
- package/bin/commands/ready-delay.d.mts +9 -4
- package/bin/commands/ready-delay.mjs +34 -20
- package/bin/commands/shepherd-journal.mjs +4 -1
- package/bin/commands/stack-drain.d.mts +35 -0
- package/bin/commands/stack-drain.mjs +138 -0
- package/bin/commands/stack-layer-readiness.d.mts +6 -0
- package/bin/commands/stack-layer-readiness.mjs +34 -0
- package/bin/commands/stack-stall.d.mts +14 -0
- package/bin/commands/stack-stall.mjs +68 -0
- package/bin/commands/stack-work.d.mts +32 -0
- package/bin/commands/stack-work.mjs +38 -0
- package/bin/config/load.d.mts +2 -0
- package/bin/config/load.mjs +10 -0
- package/bin/config.json +1 -0
- package/bin/github/api-telemetry-aggregate.d.mts +1 -0
- package/bin/github/api-telemetry-aggregate.mjs +8 -2
- package/bin/github/api-telemetry.d.mts +4 -0
- package/bin/github/api-telemetry.mjs +12 -0
- package/bin/github/batch-parsers.mjs +1 -1
- package/bin/github/batch-raw-rules.d.mts +0 -3
- package/bin/github/batch-raw-types.d.mts +2 -0
- package/bin/github/errors.d.mts +5 -0
- package/bin/github/errors.mjs +4 -0
- package/bin/github/gql/batch-pr.gql +1 -0
- package/bin/github/gql/poll-stack-summary.gql +8 -2
- package/bin/github/gql/poll-stack-topology.gql +38 -0
- package/bin/github/gql/poll-summary-check-contexts.gql +34 -0
- package/bin/github/gql/poll-summary-check-page.gql +23 -0
- package/bin/github/gql/poll-summary-fragment.gql +5 -62
- package/bin/github/gql/pr-merge-policy.gql +0 -3
- package/bin/github/graphql-http.mjs +6 -0
- package/bin/github/http-auth.d.mts +3 -0
- package/bin/github/http-auth.mjs +6 -0
- package/bin/github/http-intermediate.d.mts +1 -0
- package/bin/github/http-intermediate.mjs +3 -0
- package/bin/github/merge-queue-checks.mjs +10 -1
- package/bin/github/poll-summary-check-hydration.d.mts +12 -0
- package/bin/github/poll-summary-check-hydration.mjs +55 -0
- package/bin/github/poll-summary-fingerprint.mjs +24 -4
- package/bin/github/poll-summary-projector.mjs +8 -7
- package/bin/github/poll-summary-queue-removal.mjs +10 -1
- package/bin/github/poll-summary-raw.d.mts +19 -31
- package/bin/github/poll-summary-route.mjs +8 -5
- package/bin/github/poll-summary.mjs +16 -73
- package/bin/github/queries.d.mts +7 -0
- package/bin/github/queries.mjs +9 -1
- package/bin/github/queue-removal-freshness.d.mts +16 -0
- package/bin/github/queue-removal-freshness.mjs +26 -0
- package/bin/github/stack-read.d.mts +34 -0
- package/bin/github/stack-read.mjs +92 -0
- package/bin/log/log-file.d.mts +1 -1
- package/bin/log/log-file.mjs +4 -17
- package/bin/state/base.d.mts +18 -1
- package/bin/state/base.mjs +65 -13
- package/bin/state/fix-attempts.d.mts +1 -1
- package/bin/state/fix-attempts.mjs +1 -1
- package/bin/state/graphql-quota-policy.d.mts +7 -1
- package/bin/state/graphql-quota-policy.mjs +41 -14
- package/bin/state/graphql-quota-warnings.mjs +4 -6
- package/bin/state/iterate-stall.d.mts +7 -15
- package/bin/state/iterate-stall.mjs +6 -64
- package/bin/state/rest-cache.d.mts +1 -1
- package/bin/state/rest-cache.mjs +1 -1
- package/bin/state/stack-stall.d.mts +16 -0
- package/bin/state/stack-stall.mjs +12 -0
- package/bin/state/stall-state-store.d.mts +37 -0
- package/bin/state/stall-state-store.mjs +74 -0
- package/bin/types/api-usage.d.mts +2 -0
- package/bin/types/escalate.d.mts +1 -1
- package/bin/types/github.d.mts +1 -1
- package/bin/types/iterate.d.mts +2 -1
- package/bin/types/merge-requirements.d.mts +9 -0
- package/bin/types/poll-summary.d.mts +5 -2
- package/bin/types/report.d.mts +1 -1
- 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
|
@@ -147,20 +147,24 @@ needed, every selected PR is complete, the bounded timeout expires, or `--until-
|
|
|
147
147
|
configured GraphQL quota-warning band. Explicit PR sets give each actionable row an exact single-PR
|
|
148
148
|
`pollCommand`, so independent rows can proceed before the next aggregate poll.
|
|
149
149
|
|
|
150
|
-
Native-stack rows are ordered bottom-to-top. `--stack` never performs a mutation itself
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
150
|
+
Native-stack rows are ordered bottom-to-top. `--stack` never performs a mutation itself. Every
|
|
151
|
+
layer that still has work gets its own one-PR session on the same tick, including a clean draft
|
|
152
|
+
whose session marks it ready. Layers do not wait for a lower layer's READY receipt, so their
|
|
153
|
+
ready-delays overlap. With automatic mark-ready disabled, the instructions ask the agent to mark
|
|
154
|
+
a clean draft ready after its probe. A queued stack, or one whose remaining layers can only wait,
|
|
155
|
+
returns `WAIT`; an idle `WAIT` that stays unchanged past the stall timeout returns `ESCALATE` with
|
|
156
|
+
`stall-timeout`. A terminal READY or fully merged stack returns `CANCEL`. Closed or unverified
|
|
157
157
|
topology returns `ESCALATE` for human direction after any other shepherdable PRs are handled;
|
|
158
158
|
until then, `SHEPHERD` remains the immediate action and lists the human blockers too.
|
|
159
159
|
|
|
160
|
-
With `--stack --merge`,
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
160
|
+
With `--stack --merge`, the highest open layer whose open lower layers all have current READY
|
|
161
|
+
receipts, and whose bottom open layer GitHub has retargeted onto the stack base, returns `MERGE`
|
|
162
|
+
with `gh stack merge <that PR number> --yes --squash`. That lands the named layer and every
|
|
163
|
+
unmerged layer below it. When the base uses a merge queue, the same command queues the prefix
|
|
164
|
+
together and GitHub evaluates each layer from the bottom; a failure ejects that layer and those
|
|
165
|
+
above it. Layers above the prefix keep their one-PR sessions. After the merge, GitHub retargets
|
|
166
|
+
the next layer, so the rerun continues until the stack returns `CANCEL`. API and MCP aggregate
|
|
167
|
+
calls perform one summary tick and leave recurrence to the caller.
|
|
164
168
|
|
|
165
169
|
Polling defaults can be set under `poll` in `.pr-shepherdrc.yml`: `intervalSeconds`, `timeoutSeconds`, `debounceSeconds`, and `quietStatus`. Explicit flags override configuration, including `--no-quiet-status` when a shared config enables quiet output. Quiet status remains off by default.
|
|
166
170
|
|
|
@@ -199,7 +203,7 @@ Unsupported platforms fail closed with that same exit code.
|
|
|
199
203
|
|
|
200
204
|
### Clean Local State
|
|
201
205
|
|
|
202
|
-
`pr-shepherd` stores seen markers, fix-attempt counters, stall fingerprints, ready-delay markers, and logs under `$PR_SHEPHERD_STATE_DIR` (default
|
|
206
|
+
`pr-shepherd` stores seen markers, fix-attempt counters, stall fingerprints, ready-delay markers, and logs under `$PR_SHEPHERD_STATE_DIR` (default: `pr-shepherd-state` in the per-user temp dir; see [configuration](docs/configuration.md#environment-variables)).
|
|
203
207
|
|
|
204
208
|
```sh
|
|
205
209
|
pr-shepherd admin clean current
|
|
@@ -271,6 +275,7 @@ Replace `<version>` with a published version. Full config-file examples, tool sc
|
|
|
271
275
|
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.
|
|
272
276
|
|
|
273
277
|
```yaml
|
|
278
|
+
cliCommand: [pnpm, exec, pr-shepherd] # launcher for emitted commands; defaults to [pr-shepherd]
|
|
274
279
|
ignoreChecks:
|
|
275
280
|
- "Kilo Code Review"
|
|
276
281
|
iterate:
|
|
@@ -194,7 +194,7 @@ Flags:
|
|
|
194
194
|
PR may be a number or GitHub pull request URL. When omitted, the current branch PR is inferred.
|
|
195
195
|
Exit code: 0 on success; nonzero on failure (sysexits.h — see docs/exit-codes.md).`;
|
|
196
196
|
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 Legacy no-op; workflow runs are never cancelled.\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).";
|
|
197
|
-
readonly poll: "pr-shepherd poll\n\nRun iterate repeatedly for one PR, or read compact summaries for an explicit PR set or native\nGitHub stack. Aggregate mode returns when any row needs work, every row is terminal, or timeout.\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:\npoll.debounceSeconds; built-in 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 pr-shepherd poll --stack PR [poll-flags] [iterate-flags]\n\nPoll flags:\n --stack PR Select all entries in PR's native GitHub stack, bottom to top.\n --interval <duration> Sleep between WAIT ticks. Bare number = seconds. Default: poll.intervalSeconds (built-in 60s).\n --timeout <duration> Maximum wall-clock wait for WAIT ticks. Bare number = seconds. Default: poll.timeoutSeconds (built-in 4.5m).\n --debounce <duration> Settle window after first FIX_CODE before returning. Bare number = seconds. Default: poll.debounceSeconds (built-in 60s). 0 disables.\n --quiet-status Print only changed WAIT snapshots. Overrides poll.quietStatus.\n --no-quiet-status Print every WAIT snapshot. Overrides poll.quietStatus.\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 Legacy no-op; workflow runs are never cancelled.\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
|
|
197
|
+
readonly poll: "pr-shepherd poll\n\nRun iterate repeatedly for one PR, or read compact summaries for an explicit PR set or native\nGitHub stack. Aggregate mode returns when any row needs work, every row is terminal, or timeout.\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:\npoll.debounceSeconds; built-in 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 pr-shepherd poll --stack PR [poll-flags] [iterate-flags]\n\nPoll flags:\n --stack PR Select all entries in PR's native GitHub stack, bottom to top.\n --interval <duration> Sleep between WAIT ticks. Bare number = seconds. Default: poll.intervalSeconds (built-in 60s).\n --timeout <duration> Maximum wall-clock wait for WAIT ticks. Bare number = seconds. Default: poll.timeoutSeconds (built-in 4.5m).\n --debounce <duration> Settle window after first FIX_CODE or stack SHEPHERD before returning. Bare number = seconds. Default: poll.debounceSeconds (built-in 60s). 0 disables.\n --quiet-status Print only changed WAIT snapshots. Overrides poll.quietStatus.\n --no-quiet-status Print every WAIT snapshot. Overrides poll.quietStatus.\n --until-terminal Continue through WAIT/MARK_READY until FIX_CODE/MERGE/CANCEL/ESCALATE or stack SHEPHERD.\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 Legacy no-op; workflow runs are never cancelled.\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 a stderr line naming what it is waiting on by default; poll.quietStatus can change that default, --quiet-status/--no-quiet-status override it, 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 16 SHEPHERD (--stack only: run the listed one-PR sessions, then rerun the selector)\n A command/validation/GitHub failure exits with a sysexits.h code instead (see docs/exit-codes.md).";
|
|
198
198
|
readonly clean: `pr-shepherd clean
|
|
199
199
|
|
|
200
200
|
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 Legacy no-op; workflow runs are never cancelled.\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 one PR, or read compact summaries for an explicit PR set or native\nGitHub stack. Aggregate mode returns when any row needs work, every row is terminal, or timeout.\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:\npoll.debounceSeconds; built-in 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 pr-shepherd poll --stack PR [poll-flags] [iterate-flags]\n\nPoll flags:\n --stack PR Select all entries in PR's native GitHub stack, bottom to top.\n --interval <duration> Sleep between WAIT ticks. Bare number = seconds. Default: poll.intervalSeconds (built-in 60s).\n --timeout <duration> Maximum wall-clock wait for WAIT ticks. Bare number = seconds. Default: poll.timeoutSeconds (built-in 4.5m).\n --debounce <duration> Settle window after first FIX_CODE before returning. Bare number = seconds. Default: poll.debounceSeconds (built-in 60s). 0 disables.\n --quiet-status Print only changed WAIT snapshots. Overrides poll.quietStatus.\n --no-quiet-status Print every WAIT snapshot. Overrides poll.quietStatus.\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 Legacy no-op; workflow runs are never cancelled.\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
|
|
2
|
+
export declare const POLL_USAGE = "pr-shepherd poll\n\nRun iterate repeatedly for one PR, or read compact summaries for an explicit PR set or native\nGitHub stack. Aggregate mode returns when any row needs work, every row is terminal, or timeout.\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:\npoll.debounceSeconds; built-in 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 pr-shepherd poll --stack PR [poll-flags] [iterate-flags]\n\nPoll flags:\n --stack PR Select all entries in PR's native GitHub stack, bottom to top.\n --interval <duration> Sleep between WAIT ticks. Bare number = seconds. Default: poll.intervalSeconds (built-in 60s).\n --timeout <duration> Maximum wall-clock wait for WAIT ticks. Bare number = seconds. Default: poll.timeoutSeconds (built-in 4.5m).\n --debounce <duration> Settle window after first FIX_CODE or stack SHEPHERD before returning. Bare number = seconds. Default: poll.debounceSeconds (built-in 60s). 0 disables.\n --quiet-status Print only changed WAIT snapshots. Overrides poll.quietStatus.\n --no-quiet-status Print every WAIT snapshot. Overrides poll.quietStatus.\n --until-terminal Continue through WAIT/MARK_READY until FIX_CODE/MERGE/CANCEL/ESCALATE or stack SHEPHERD.\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 Legacy no-op; workflow runs are never cancelled.\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 a stderr line naming what it is waiting on by default; poll.quietStatus can change that default, --quiet-status/--no-quiet-status override it, 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 16 SHEPHERD (--stack only: run the listed one-PR sessions, then rerun the selector)\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;
|
|
@@ -53,10 +53,10 @@ Poll flags:
|
|
|
53
53
|
--stack PR Select all entries in PR's native GitHub stack, bottom to top.
|
|
54
54
|
--interval <duration> Sleep between WAIT ticks. Bare number = seconds. Default: poll.intervalSeconds (built-in 60s).
|
|
55
55
|
--timeout <duration> Maximum wall-clock wait for WAIT ticks. Bare number = seconds. Default: poll.timeoutSeconds (built-in 4.5m).
|
|
56
|
-
--debounce <duration> Settle window after first FIX_CODE before returning. Bare number = seconds. Default: poll.debounceSeconds (built-in 60s). 0 disables.
|
|
56
|
+
--debounce <duration> Settle window after first FIX_CODE or stack SHEPHERD before returning. Bare number = seconds. Default: poll.debounceSeconds (built-in 60s). 0 disables.
|
|
57
57
|
--quiet-status Print only changed WAIT snapshots. Overrides poll.quietStatus.
|
|
58
58
|
--no-quiet-status Print every WAIT snapshot. Overrides poll.quietStatus.
|
|
59
|
-
--until-terminal Continue through WAIT/MARK_READY until FIX_CODE/CANCEL/ESCALATE.
|
|
59
|
+
--until-terminal Continue through WAIT/MARK_READY until FIX_CODE/MERGE/CANCEL/ESCALATE or stack SHEPHERD.
|
|
60
60
|
|
|
61
61
|
Forwarded iterate flags:
|
|
62
62
|
--ready-delay <duration> Settle window before a clean PR cancels. Bare number = minutes. Example: 15m.
|
|
@@ -71,7 +71,7 @@ Forwarded iterate flags:
|
|
|
71
71
|
Durations accept s/m/h suffixes: 30s, 4.5m, 1h. A bare number uses each flag's default unit (seconds
|
|
72
72
|
for --interval/--timeout/--debounce, minutes for --ready-delay/--stall-timeout); decimals are allowed only with
|
|
73
73
|
an explicit unit (4.5m).
|
|
74
|
-
Each WAIT tick writes
|
|
74
|
+
Each WAIT tick writes a stderr line naming what it is waiting on by default; poll.quietStatus can change that default, --quiet-status/--no-quiet-status override it, and --verbose emits detailed per-tick lines.
|
|
75
75
|
FIX_CODE debounce writes a remaining-seconds line to stderr. --timeout does not cut an in-flight debounce short.
|
|
76
76
|
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.
|
|
77
77
|
|
|
@@ -83,6 +83,7 @@ Exit codes: same as iterate (the final tick's action/reason decides the code).
|
|
|
83
83
|
13 ESCALATE
|
|
84
84
|
14 CANCEL (closed without merging)
|
|
85
85
|
15 MERGE
|
|
86
|
+
16 SHEPHERD (--stack only: run the listed one-PR sessions, then rerun the selector)
|
|
86
87
|
A command/validation/GitHub failure exits with a sysexits.h code instead (see docs/exit-codes.md).`;
|
|
87
88
|
/** Public help page for the default PR polling invocation. */
|
|
88
89
|
export const DEFAULT_USAGE = POLL_USAGE.replace(/^pr-shepherd poll$/m, "pr-shepherd [PR]")
|
|
@@ -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 --stack 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 journal extract --body-file <path>\n pr-shepherd build-suggestion-patches [PR] --thread-id ID --message MSG [groups...]\n pr-shepherd admin clean <pr|branch|current|repo|all> [value] [flags]\n pr-shepherd admin log-file [--format text|json]\n\nCommands:\n [PR ...] Poll one PR, an explicit same-repository set, or a native stack.\n iterate Run one iterate tick (single-tick alias).\n apply review Apply review-state mutations after fixes.\n apply files Mark selected changed files as viewed.\n apply journal Append a list item to the Shepherd Journal details block of a PR body.\n journal extract Extract a validated Shepherd Journal from a local PR-body file as JSON.\n build-suggestion-patches\n Convert ordered GitHub suggestion threads into patches and commit instructions.\n admin clean Remove pr-shepherd state files.\n admin log-file Print the per-worktree debug log path.\n\nPR argument:\n PR may be a number, owner/repo#number, or a GitHub pull request URL.\n Multiple PRs must name one repository. --stack PR selects every entry in PR's native stack.\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 Legacy no-op; workflow runs are never cancelled.\n --merge Shepherd through readiness, then emit a merge or merge-queue command.\n\nPolling flags:\n --interval <duration> Delay between WAIT ticks. Bare number = seconds. Default: poll.intervalSeconds (built-in 60s).\n --timeout <duration> Poll wall-clock cap for WAIT ticks. Bare number = seconds. Default: poll.timeoutSeconds (built-in 4.5m).\n --debounce <duration> Settle window after first FIX_CODE before returning. Bare number = seconds. Default: poll.debounceSeconds (built-in 60s). 0 disables.\n --quiet-status Print only changed WAIT snapshots. Overrides poll.quietStatus.\n --no-quiet-status Print every WAIT snapshot. Overrides poll.quietStatus.\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)\n 15 MERGE\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 --stack 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 journal extract --body-file <path>\n pr-shepherd build-suggestion-patches [PR] --thread-id ID --message MSG [groups...]\n pr-shepherd admin clean <pr|branch|current|repo|all> [value] [flags]\n pr-shepherd admin log-file [--format text|json]\n\nCommands:\n [PR ...] Poll one PR, an explicit same-repository set, or a native stack.\n iterate Run one iterate tick (single-tick alias).\n apply review Apply review-state mutations after fixes.\n apply files Mark selected changed files as viewed.\n apply journal Append a list item to the Shepherd Journal details block of a PR body.\n journal extract Extract a validated Shepherd Journal from a local PR-body file as JSON.\n build-suggestion-patches\n Convert ordered GitHub suggestion threads into patches and commit instructions.\n admin clean Remove pr-shepherd state files.\n admin log-file Print the per-worktree debug log path.\n\nPR argument:\n PR may be a number, owner/repo#number, or a GitHub pull request URL.\n Multiple PRs must name one repository. --stack PR selects every entry in PR's native stack.\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 Legacy no-op; workflow runs are never cancelled.\n --merge Shepherd through readiness, then emit a merge or merge-queue command.\n\nPolling flags:\n --interval <duration> Delay between WAIT ticks. Bare number = seconds. Default: poll.intervalSeconds (built-in 60s).\n --timeout <duration> Poll wall-clock cap for WAIT ticks. Bare number = seconds. Default: poll.timeoutSeconds (built-in 4.5m).\n --debounce <duration> Settle window after first FIX_CODE or stack SHEPHERD before returning. Bare number = seconds. Default: poll.debounceSeconds (built-in 60s). 0 disables.\n --quiet-status Print only changed WAIT snapshots. Overrides poll.quietStatus.\n --no-quiet-status Print every WAIT snapshot. Overrides poll.quietStatus.\n --until-terminal Continue through WAIT/MARK_READY until FIX_CODE/MERGE/CANCEL/ESCALATE or stack SHEPHERD.\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)\n 15 MERGE\n 16 SHEPHERD (--stack only: run the listed one-PR sessions, then rerun the selector)\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.";
|
|
@@ -48,10 +48,10 @@ Iterate flags:
|
|
|
48
48
|
Polling flags:
|
|
49
49
|
--interval <duration> Delay between WAIT ticks. Bare number = seconds. Default: poll.intervalSeconds (built-in 60s).
|
|
50
50
|
--timeout <duration> Poll wall-clock cap for WAIT ticks. Bare number = seconds. Default: poll.timeoutSeconds (built-in 4.5m).
|
|
51
|
-
--debounce <duration> Settle window after first FIX_CODE before returning. Bare number = seconds. Default: poll.debounceSeconds (built-in 60s). 0 disables.
|
|
51
|
+
--debounce <duration> Settle window after first FIX_CODE or stack SHEPHERD before returning. Bare number = seconds. Default: poll.debounceSeconds (built-in 60s). 0 disables.
|
|
52
52
|
--quiet-status Print only changed WAIT snapshots. Overrides poll.quietStatus.
|
|
53
53
|
--no-quiet-status Print every WAIT snapshot. Overrides poll.quietStatus.
|
|
54
|
-
--until-terminal Continue through WAIT/MARK_READY until FIX_CODE/CANCEL/ESCALATE.
|
|
54
|
+
--until-terminal Continue through WAIT/MARK_READY until FIX_CODE/MERGE/CANCEL/ESCALATE or stack SHEPHERD.
|
|
55
55
|
|
|
56
56
|
Clean variants:
|
|
57
57
|
pr [number] Remove state for one PR. Defaults to current branch PR.
|
|
@@ -68,6 +68,7 @@ Exit codes: 0 done, 10-19 PR state, 64-78 shepherd failed (sysexits.h).
|
|
|
68
68
|
13 ESCALATE
|
|
69
69
|
14 CANCEL (closed without merging)
|
|
70
70
|
15 MERGE
|
|
71
|
+
16 SHEPHERD (--stack only: run the listed one-PR sessions, then rerun the selector)
|
|
71
72
|
See docs/exit-codes.md for the full sysexits.h error-code table.
|
|
72
73
|
|
|
73
74
|
Duration 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).
|
package/bin/cli/help.d.mts
CHANGED
|
@@ -194,7 +194,7 @@ Flags:
|
|
|
194
194
|
PR may be a number or GitHub pull request URL. When omitted, the current branch PR is inferred.
|
|
195
195
|
Exit code: 0 on success; nonzero on failure (sysexits.h — see docs/exit-codes.md).`;
|
|
196
196
|
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 Legacy no-op; workflow runs are never cancelled.\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).";
|
|
197
|
-
readonly poll: "pr-shepherd poll\n\nRun iterate repeatedly for one PR, or read compact summaries for an explicit PR set or native\nGitHub stack. Aggregate mode returns when any row needs work, every row is terminal, or timeout.\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:\npoll.debounceSeconds; built-in 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 pr-shepherd poll --stack PR [poll-flags] [iterate-flags]\n\nPoll flags:\n --stack PR Select all entries in PR's native GitHub stack, bottom to top.\n --interval <duration> Sleep between WAIT ticks. Bare number = seconds. Default: poll.intervalSeconds (built-in 60s).\n --timeout <duration> Maximum wall-clock wait for WAIT ticks. Bare number = seconds. Default: poll.timeoutSeconds (built-in 4.5m).\n --debounce <duration> Settle window after first FIX_CODE before returning. Bare number = seconds. Default: poll.debounceSeconds (built-in 60s). 0 disables.\n --quiet-status Print only changed WAIT snapshots. Overrides poll.quietStatus.\n --no-quiet-status Print every WAIT snapshot. Overrides poll.quietStatus.\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 Legacy no-op; workflow runs are never cancelled.\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
|
|
197
|
+
readonly poll: "pr-shepherd poll\n\nRun iterate repeatedly for one PR, or read compact summaries for an explicit PR set or native\nGitHub stack. Aggregate mode returns when any row needs work, every row is terminal, or timeout.\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:\npoll.debounceSeconds; built-in 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 pr-shepherd poll --stack PR [poll-flags] [iterate-flags]\n\nPoll flags:\n --stack PR Select all entries in PR's native GitHub stack, bottom to top.\n --interval <duration> Sleep between WAIT ticks. Bare number = seconds. Default: poll.intervalSeconds (built-in 60s).\n --timeout <duration> Maximum wall-clock wait for WAIT ticks. Bare number = seconds. Default: poll.timeoutSeconds (built-in 4.5m).\n --debounce <duration> Settle window after first FIX_CODE or stack SHEPHERD before returning. Bare number = seconds. Default: poll.debounceSeconds (built-in 60s). 0 disables.\n --quiet-status Print only changed WAIT snapshots. Overrides poll.quietStatus.\n --no-quiet-status Print every WAIT snapshot. Overrides poll.quietStatus.\n --until-terminal Continue through WAIT/MARK_READY until FIX_CODE/MERGE/CANCEL/ESCALATE or stack SHEPHERD.\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 Legacy no-op; workflow runs are never cancelled.\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 a stderr line naming what it is waiting on by default; poll.quietStatus can change that default, --quiet-status/--no-quiet-status override it, 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 16 SHEPHERD (--stack only: run the listed one-PR sessions, then rerun the selector)\n A command/validation/GitHub failure exits with a sysexits.h code instead (see docs/exit-codes.md).";
|
|
198
198
|
readonly clean: `pr-shepherd clean
|
|
199
199
|
|
|
200
200
|
Remove pr-shepherd state files from PR_SHEPHERD_STATE_DIR.
|
|
@@ -258,7 +258,7 @@ On POSIX, the final body-file path entry must be a readable regular file in a tr
|
|
|
258
258
|
symlinks, FIFOs, devices, and unreadable paths exit 66. Unsupported platforms fail closed with exit 66.
|
|
259
259
|
--help, -h Print this help and exit before any I/O.`;
|
|
260
260
|
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.";
|
|
261
|
-
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 --stack 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 journal extract --body-file <path>\n pr-shepherd build-suggestion-patches [PR] --thread-id ID --message MSG [groups...]\n pr-shepherd admin clean <pr|branch|current|repo|all> [value] [flags]\n pr-shepherd admin log-file [--format text|json]\n\nCommands:\n [PR ...] Poll one PR, an explicit same-repository set, or a native stack.\n iterate Run one iterate tick (single-tick alias).\n apply review Apply review-state mutations after fixes.\n apply files Mark selected changed files as viewed.\n apply journal Append a list item to the Shepherd Journal details block of a PR body.\n journal extract Extract a validated Shepherd Journal from a local PR-body file as JSON.\n build-suggestion-patches\n Convert ordered GitHub suggestion threads into patches and commit instructions.\n admin clean Remove pr-shepherd state files.\n admin log-file Print the per-worktree debug log path.\n\nPR argument:\n PR may be a number, owner/repo#number, or a GitHub pull request URL.\n Multiple PRs must name one repository. --stack PR selects every entry in PR's native stack.\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 Legacy no-op; workflow runs are never cancelled.\n --merge Shepherd through readiness, then emit a merge or merge-queue command.\n\nPolling flags:\n --interval <duration> Delay between WAIT ticks. Bare number = seconds. Default: poll.intervalSeconds (built-in 60s).\n --timeout <duration> Poll wall-clock cap for WAIT ticks. Bare number = seconds. Default: poll.timeoutSeconds (built-in 4.5m).\n --debounce <duration> Settle window after first FIX_CODE before returning. Bare number = seconds. Default: poll.debounceSeconds (built-in 60s). 0 disables.\n --quiet-status Print only changed WAIT snapshots. Overrides poll.quietStatus.\n --no-quiet-status Print every WAIT snapshot. Overrides poll.quietStatus.\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)\n 15 MERGE\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.";
|
|
261
|
+
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 --stack 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 journal extract --body-file <path>\n pr-shepherd build-suggestion-patches [PR] --thread-id ID --message MSG [groups...]\n pr-shepherd admin clean <pr|branch|current|repo|all> [value] [flags]\n pr-shepherd admin log-file [--format text|json]\n\nCommands:\n [PR ...] Poll one PR, an explicit same-repository set, or a native stack.\n iterate Run one iterate tick (single-tick alias).\n apply review Apply review-state mutations after fixes.\n apply files Mark selected changed files as viewed.\n apply journal Append a list item to the Shepherd Journal details block of a PR body.\n journal extract Extract a validated Shepherd Journal from a local PR-body file as JSON.\n build-suggestion-patches\n Convert ordered GitHub suggestion threads into patches and commit instructions.\n admin clean Remove pr-shepherd state files.\n admin log-file Print the per-worktree debug log path.\n\nPR argument:\n PR may be a number, owner/repo#number, or a GitHub pull request URL.\n Multiple PRs must name one repository. --stack PR selects every entry in PR's native stack.\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 Legacy no-op; workflow runs are never cancelled.\n --merge Shepherd through readiness, then emit a merge or merge-queue command.\n\nPolling flags:\n --interval <duration> Delay between WAIT ticks. Bare number = seconds. Default: poll.intervalSeconds (built-in 60s).\n --timeout <duration> Poll wall-clock cap for WAIT ticks. Bare number = seconds. Default: poll.timeoutSeconds (built-in 4.5m).\n --debounce <duration> Settle window after first FIX_CODE or stack SHEPHERD before returning. Bare number = seconds. Default: poll.debounceSeconds (built-in 60s). 0 disables.\n --quiet-status Print only changed WAIT snapshots. Overrides poll.quietStatus.\n --no-quiet-status Print every WAIT snapshot. Overrides poll.quietStatus.\n --until-terminal Continue through WAIT/MARK_READY until FIX_CODE/MERGE/CANCEL/ESCALATE or stack SHEPHERD.\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)\n 15 MERGE\n 16 SHEPHERD (--stack only: run the listed one-PR sessions, then rerun the selector)\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.";
|
|
262
262
|
};
|
|
263
263
|
/** Resolve help keys for nested public commands before any command I/O. */
|
|
264
264
|
export declare function helpKeyForArgs(args: string[]): keyof typeof USAGE;
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import { renderMergeCommand } from "../commands/iterate/merge.mjs";
|
|
2
2
|
import { inlineCode } from "../util/markdown.mjs";
|
|
3
3
|
import { buildQuotaAwareContinuation } from "../quota-warning.mjs";
|
|
4
|
+
import { formatPrUrl } from "../pr-reference.mjs";
|
|
5
|
+
import { AUTO_MARK_READY_DISABLED_HOLD } from "../commands/stack-work.mjs";
|
|
6
|
+
import { buildPrShepherdCommand } from "./runner.mjs";
|
|
4
7
|
export function buildSimpleIterateInstructions(result) {
|
|
5
8
|
switch (result.action) {
|
|
6
9
|
case "wait":
|
|
10
|
+
if (result.stackDraftHold)
|
|
11
|
+
return [buildStackDraftHoldInstruction(result, result.stackDraftHold)];
|
|
7
12
|
if (result.quotaWarning) {
|
|
8
13
|
return [
|
|
9
14
|
buildQuotaAwareContinuation(result.quotaWarning, "Non-terminal — no action needed this tick."),
|
|
@@ -49,6 +54,23 @@ export function buildSimpleIterateInstructions(result) {
|
|
|
49
54
|
}
|
|
50
55
|
}
|
|
51
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* A held stack draft cannot advance by repeating its one-PR session, so hand control back
|
|
59
|
+
* to the stack selector instead of asking for another immediate iteration.
|
|
60
|
+
*/
|
|
61
|
+
function buildStackDraftHoldInstruction(result, hold) {
|
|
62
|
+
const stackCommand = buildPrShepherdCommand([
|
|
63
|
+
"--stack",
|
|
64
|
+
formatPrUrl(result.repo, result.pr),
|
|
65
|
+
"--until-terminal",
|
|
66
|
+
]).text;
|
|
67
|
+
const handoff = `a \`--stack\` selector listed this session, finish that selector's remaining steps and rerun it with its original flags; otherwise run ${inlineCode(stackCommand)}, adding \`--merge\` when merging was requested.`;
|
|
68
|
+
const reason = hold.kind === "auto-mark-ready-disabled" ? AUTO_MARK_READY_DISABLED_HOLD : hold.kind;
|
|
69
|
+
const instruction = `PR #${result.pr} stays in draft because ${reason}, so repeating this one-PR session cannot advance it. If ${handoff}`;
|
|
70
|
+
return result.quotaWarning
|
|
71
|
+
? buildQuotaAwareContinuation(result.quotaWarning, instruction)
|
|
72
|
+
: instruction;
|
|
73
|
+
}
|
|
52
74
|
export function adaptIterateLog(log) {
|
|
53
75
|
return log.replace(/\s+—\s+\d+s until auto-cancel/g, "");
|
|
54
76
|
}
|
package/bin/cli/iterate-lean.mjs
CHANGED
|
@@ -72,6 +72,7 @@ export function projectIterateLean(result, opts) {
|
|
|
72
72
|
return {
|
|
73
73
|
...base,
|
|
74
74
|
...(result.deferredWork && { deferredWork: result.deferredWork }),
|
|
75
|
+
...(result.stackDraftHold && { stackDraftHold: result.stackDraftHold }),
|
|
75
76
|
log: adaptIterateLog(result.log),
|
|
76
77
|
instructions: simpleInstructions(result),
|
|
77
78
|
};
|
|
@@ -43,12 +43,11 @@ function formatItem(item) {
|
|
|
43
43
|
: "";
|
|
44
44
|
const readyDelay = item.remainingSeconds !== undefined ? ` · ready delay \`${item.remainingSeconds}s\`` : "";
|
|
45
45
|
const readyReceipt = item.readyReceipt ? " · Shepherd READY completion `verified`" : "";
|
|
46
|
-
const blockedBy = item.blockedByPr ? ` · stack blocked by PR #${item.blockedByPr}` : "";
|
|
47
46
|
const checks = item.checks;
|
|
48
47
|
const review = item.review;
|
|
49
48
|
return [
|
|
50
49
|
`- [PR #${item.pr}: ${escapeMarkdownText(item.title)}](${item.url}) [${item.action.toUpperCase()}]`,
|
|
51
|
-
` - state \`${item.state}\` · mergeable \`${item.mergeable}\` · merge \`${item.mergeStateStatus}\`${reviewDecision}${stateFlags}${blockingReviewer}${readyDelay}${readyReceipt}${
|
|
50
|
+
` - state \`${item.state}\` · mergeable \`${item.mergeable}\` · merge \`${item.mergeStateStatus}\`${reviewDecision}${stateFlags}${blockingReviewer}${readyDelay}${readyReceipt}${stack}`,
|
|
52
51
|
` - head \`${item.headRefName}\` at \`${item.headRefOid}\` · base \`${item.baseRefName}\``,
|
|
53
52
|
...(checks
|
|
54
53
|
? [` - checks: ${formatCounts(checks, checks.incomplete ? ", incomplete" : "")}`]
|
|
@@ -62,7 +61,9 @@ function formatItem(item) {
|
|
|
62
61
|
]
|
|
63
62
|
: []),
|
|
64
63
|
` - reasons: ${item.reasons.map((reason) => `\`${reason}\``).join(", ")}`,
|
|
65
|
-
...(item.pollCommand
|
|
64
|
+
...(item.pollCommand
|
|
65
|
+
? [` - pollCommand: \`${item.pollCommand}\`${item.pollProbe ? " · bounded probe" : ""}`]
|
|
66
|
+
: []),
|
|
66
67
|
].join("\n");
|
|
67
68
|
}
|
|
68
69
|
function formatCounts(counts, suffix) {
|
package/bin/cli/runner.d.mts
CHANGED
|
@@ -2,6 +2,7 @@ interface PrShepherdCommand {
|
|
|
2
2
|
argv: string[];
|
|
3
3
|
text: string;
|
|
4
4
|
}
|
|
5
|
+
/** Every emitted pr-shepherd command starts with the configured `cliCommand` launcher. */
|
|
5
6
|
export declare function buildPrShepherdCommand(args: string[]): PrShepherdCommand;
|
|
6
7
|
export declare function renderShellCommand(argv: string[]): string;
|
|
7
8
|
export {};
|
package/bin/cli/runner.mjs
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { loadConfig } from "../config/load.mjs";
|
|
2
|
+
/** Every emitted pr-shepherd command starts with the configured `cliCommand` launcher. */
|
|
1
3
|
export function buildPrShepherdCommand(args) {
|
|
2
|
-
const argv = [
|
|
4
|
+
const argv = [...loadConfig().cliCommand, ...args];
|
|
3
5
|
return { argv, text: renderShellCommand(argv) };
|
|
4
6
|
}
|
|
5
7
|
export function renderShellCommand(argv) {
|
package/bin/commands/check.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { fetchPrBatch } from "../github/batch.mjs";
|
|
2
|
+
import { queueRemovalAppliesToHead } from "../github/queue-removal-freshness.mjs";
|
|
2
3
|
import { storePrFingerprint } from "../state/pr-fingerprint.mjs";
|
|
3
4
|
import { tryReuseFingerprintReport } from "./check-fingerprint.mjs";
|
|
4
5
|
import { getRepoInfo, getCurrentPrNumber } from "../github/client.mjs";
|
|
@@ -64,11 +65,19 @@ export async function runCheck(opts) {
|
|
|
64
65
|
// historical event forever. When GitHub omits the removed queue commit for that old event
|
|
65
66
|
// (e.g. after the synthetic commit is garbage collected), freshness is unverifiable — treat
|
|
66
67
|
// it as stale/updated rather than as still current, so Shepherd doesn't escalate
|
|
67
|
-
// `merge-queue-removed` permanently on data it can no longer check.
|
|
68
|
-
//
|
|
68
|
+
// `merge-queue-removed` permanently on data it can no longer check. A squash or rebase
|
|
69
|
+
// queue commit has one parent and does not list the PR head; that removal stays current
|
|
70
|
+
// until the head's committer time is later than the removal. The raw removal fields still
|
|
71
|
+
// render in the merge-queue header regardless of this flag.
|
|
72
|
+
const headCommittedAtUnix = batchData.activity?.latestCommitCommittedAtUnix;
|
|
69
73
|
const headUpdatedAfterRemoval = Boolean(latestRemoval &&
|
|
70
|
-
(
|
|
71
|
-
|
|
74
|
+
!queueRemovalAppliesToHead({
|
|
75
|
+
parentOids: latestRemoval.beforeCommitParentOids,
|
|
76
|
+
headOid: batchData.headRefOid,
|
|
77
|
+
...(headCommittedAtUnix !== undefined &&
|
|
78
|
+
headCommittedAtUnix !== null && { headCommittedAtUnix }),
|
|
79
|
+
removedAtUnix: latestRemoval.createdAtUnix,
|
|
80
|
+
}));
|
|
72
81
|
const queueRawChecks = batchData.isInMergeQueue
|
|
73
82
|
? (batchData.mergeQueueChecks ?? [])
|
|
74
83
|
: latestRemoval && !headUpdatedAfterRemoval
|
package/bin/commands/clean.mjs
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { rm, readdir, realpath, stat } from "node:fs/promises";
|
|
2
2
|
import { join } from "node:path";
|
|
3
|
-
import { resolveStateBase } from "../state/base.mjs";
|
|
3
|
+
import { resolveRepoStateDir, resolveStateBase } from "../state/base.mjs";
|
|
4
4
|
import { getRepoInfo, getCurrentPrNumber, getCurrentBranch, getPrNumberForBranch, } from "../github/client.mjs";
|
|
5
|
-
import { SAFE_SEGMENT } from "../util/path-segment.mjs";
|
|
6
5
|
export async function runClean(opts) {
|
|
7
6
|
const dryRun = opts.dryRun ?? false;
|
|
8
7
|
const rawBase = resolveStateBase();
|
|
@@ -107,20 +106,15 @@ async function resolveTarget(base, opts) {
|
|
|
107
106
|
}
|
|
108
107
|
const repo = await getRepoInfo();
|
|
109
108
|
const { owner, name } = repo;
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
if (!SAFE_SEGMENT.test(val)) {
|
|
115
|
-
throw new Error(`Invalid repository segment "${field}": ${val}`);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
const ownerRepo = `${owner}-${name}`;
|
|
109
|
+
// Same segment rules as every other state path. The directory itself stays under
|
|
110
|
+
// `base`, which runClean has already realpath'd.
|
|
111
|
+
resolveRepoStateDir({ owner, repo: name });
|
|
112
|
+
const repoDir = join(base, owner, name);
|
|
119
113
|
if (variant === "repo") {
|
|
120
114
|
if (value !== undefined) {
|
|
121
115
|
throw new Error(`"clean repo" does not accept a positional argument; got "${value}". Did you mean "clean pr" or "clean branch"?`);
|
|
122
116
|
}
|
|
123
|
-
return
|
|
117
|
+
return repoDir;
|
|
124
118
|
}
|
|
125
119
|
let prNumber;
|
|
126
120
|
if (variant === "pr") {
|
|
@@ -152,5 +146,5 @@ async function resolveTarget(base, opts) {
|
|
|
152
146
|
throw new Error(`No open PR found for branch: ${branchName}`);
|
|
153
147
|
prNumber = n;
|
|
154
148
|
}
|
|
155
|
-
return join(
|
|
149
|
+
return join(repoDir, String(prNumber));
|
|
156
150
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { loadConfig } from "../../config/load.mjs";
|
|
2
|
-
import { summarizeApiTelemetry } from "../../github/api-telemetry.mjs";
|
|
2
|
+
import { summarizeApiTelemetry, withGraphqlCredentialFingerprint, } from "../../github/api-telemetry.mjs";
|
|
3
3
|
import { evaluateWorktreeGraphqlQuotaWarning } from "../../state/graphql-quota-warnings.mjs";
|
|
4
4
|
import { buildQuotaAwareContinuation } from "../../quota-warning.mjs";
|
|
5
5
|
function shouldWarn(result) {
|
|
@@ -17,7 +17,7 @@ export async function attachApiUsage(result, persistWarning, preservePersistedWa
|
|
|
17
17
|
...band,
|
|
18
18
|
pollIntervalMinutes: Math.max(band.pollIntervalMinutes, minimumPollIntervalMinutes),
|
|
19
19
|
}));
|
|
20
|
-
quotaWarning = await evaluateWorktreeGraphqlQuotaWarning({ owner, repo }, bands, apiUsage.graphql, persistWarning);
|
|
20
|
+
quotaWarning = await evaluateWorktreeGraphqlQuotaWarning({ owner, repo }, bands, withGraphqlCredentialFingerprint(apiUsage.graphql), persistWarning);
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
23
|
const { quotaWarning: _deferredWarning, ...baseResult } = result;
|
|
@@ -19,7 +19,7 @@ export declare function buildBehindBaseHintInstruction(baseBranch: string, hint:
|
|
|
19
19
|
export declare function buildRepeatedWorkflowBranchRecoveryInstructions(baseBranch: string, hasExhaustedWorkflowRerun: boolean, branch: {
|
|
20
20
|
isBehind: boolean;
|
|
21
21
|
hasConflicts: boolean;
|
|
22
|
-
}): string[];
|
|
22
|
+
}, stackRebase?: string): string[];
|
|
23
23
|
/**
|
|
24
24
|
* Build the `Run the apply review: command` instruction. Steps stay here (not in the skill)
|
|
25
25
|
* whenever the *unmodified, as-printed* command is unsafe without them:
|
|
@@ -33,4 +33,4 @@ export declare function buildRepeatedWorkflowBranchRecoveryInstructions(baseBran
|
|
|
33
33
|
export declare function buildResolveCommandInstruction(resolveCommand: ResolveCommand): string[];
|
|
34
34
|
/** Build the CI-triage pointer; the skill limits follow-up actions to included evidence. */
|
|
35
35
|
export declare function buildFailingCheckInstructions(checks: AgentCheck[]): string[];
|
|
36
|
-
export declare function buildFixCompletionInstruction(checks: AgentCheck[], hasConflicts?: boolean, hasShaGatedReviewMutations?: boolean): string;
|
|
36
|
+
export declare function buildFixCompletionInstruction(checks: AgentCheck[], hasConflicts?: boolean, hasShaGatedReviewMutations?: boolean, pushesRewrittenStack?: boolean): string;
|
|
@@ -25,16 +25,17 @@ export function buildBehindBaseHintInstruction(baseBranch, hint, isBehind) {
|
|
|
25
25
|
* The fetched PR base branch is raw context; the caller still owns repository-specific git
|
|
26
26
|
* mechanics and decides whether the base contains a relevant fix.
|
|
27
27
|
*/
|
|
28
|
-
export function buildRepeatedWorkflowBranchRecoveryInstructions(baseBranch, hasExhaustedWorkflowRerun, branch) {
|
|
28
|
+
export function buildRepeatedWorkflowBranchRecoveryInstructions(baseBranch, hasExhaustedWorkflowRerun, branch, stackRebase) {
|
|
29
29
|
if (!hasExhaustedWorkflowRerun || (!branch.isBehind && !branch.hasConflicts))
|
|
30
30
|
return [];
|
|
31
31
|
const state = branch.hasConflicts ? "conflicts with" : "is behind";
|
|
32
32
|
const instructions = [
|
|
33
33
|
`The workflow rerun still fails while the branch ${state} PR base branch \`${baseBranch}\`. Inspect the current base branch for an existing fix before choosing a remediation.`,
|
|
34
34
|
];
|
|
35
|
-
instructions.push(
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
instructions.push(stackRebase ??
|
|
36
|
+
(branch.hasConflicts
|
|
37
|
+
? `Rebase or otherwise update the PR branch from \`${baseBranch}\` according to repository conventions, resolving conflicts as part of that update.`
|
|
38
|
+
: `Rebase or otherwise update the PR branch from \`${baseBranch}\` according to repository conventions.`));
|
|
38
39
|
return instructions;
|
|
39
40
|
}
|
|
40
41
|
/**
|
|
@@ -79,11 +80,14 @@ export function buildFailingCheckInstructions(checks) {
|
|
|
79
80
|
}
|
|
80
81
|
return instructions;
|
|
81
82
|
}
|
|
82
|
-
export function buildFixCompletionInstruction(checks, hasConflicts = false, hasShaGatedReviewMutations = false) {
|
|
83
|
+
export function buildFixCompletionInstruction(checks, hasConflicts = false, hasShaGatedReviewMutations = false, pushesRewrittenStack = false) {
|
|
84
|
+
const push = pushesRewrittenStack
|
|
85
|
+
? "push the rewritten stack with `gh stack push`"
|
|
86
|
+
: "push to the PR head branch";
|
|
83
87
|
if (hasConflicts)
|
|
84
|
-
return
|
|
88
|
+
return `\`[FIX_CODE]\` is non-terminal: resolve the conflicts, commit, ${push}, then iterate immediately with the same options.`;
|
|
85
89
|
if (hasShaGatedReviewMutations) {
|
|
86
|
-
return
|
|
90
|
+
return `\`[FIX_CODE]\` is non-terminal: if you changed code, commit and ${push}, then run the review mutations using the pushed commit SHA and iterate immediately with the same options; if you did not change code, complete the authorized review mutations and iterate immediately with the same options.`;
|
|
87
91
|
}
|
|
88
92
|
if (checks.some((check) => check.rerunCommand)) {
|
|
89
93
|
return "`[FIX_CODE]` is non-terminal. Run any warranted reruns for `[rerun authorized]` checks (or apply code fixes for real failures), then iterate immediately with the same options to continue.";
|
|
@@ -240,6 +240,10 @@ export function buildEscalateSuggestion(triggers, detail) {
|
|
|
240
240
|
const duration = detail ?? "60 minutes";
|
|
241
241
|
return `No progress detected for ${duration} — state has not changed. This is a manual checkpoint: inspect the PR and apply a manual fix before resuming.`;
|
|
242
242
|
}
|
|
243
|
+
if (triggers.includes("stall-state-unavailable")) {
|
|
244
|
+
const reason = detail ?? "unknown error";
|
|
245
|
+
return `The stall timer could not be saved (${reason}). Fix PR_SHEPHERD_STATE_DIR or the directory permissions, then resume. Automated polling is paused because a stuck loop would not be detected.`;
|
|
246
|
+
}
|
|
243
247
|
if (triggers.includes("base-branch-unknown")) {
|
|
244
248
|
const reason = detail ? ` (${detail})` : "";
|
|
245
249
|
return `Could not determine the PR's base branch${reason} — automated rebases are paused because branch safety is unclear. Run the rebase manually against the PR's real target branch.`;
|
|
@@ -6,6 +6,7 @@ import { checkEscalateTriggers, validateBaseBranch, buildEscalateSuggestion, bui
|
|
|
6
6
|
import { buildResolveCommand } from "./classify.mjs";
|
|
7
7
|
import { buildThreadMutationRouting, threadHasAuthorizedMutation, } from "./thread-mutation-routing.mjs";
|
|
8
8
|
import { buildFixInstructions } from "./render.mjs";
|
|
9
|
+
import { buildNativeStackLayerRebase } from "./native-stack-rebase.mjs";
|
|
9
10
|
import { applyStallGuard } from "./stall.mjs";
|
|
10
11
|
import { annotationMarkerBody, checksWithActionableAnnotations } from "../check-annotations.mjs";
|
|
11
12
|
import { threadTranscriptBody } from "../../threads/transcript.mjs";
|
|
@@ -271,7 +272,11 @@ export async function handleFixCode(ctx) {
|
|
|
271
272
|
}
|
|
272
273
|
const firstLookThreads = report.threads.firstLook;
|
|
273
274
|
const firstLookComments = report.comments.firstLook;
|
|
274
|
-
|
|
275
|
+
// Conflicts, and a behind branch whose rerun already failed, both ask for a branch update.
|
|
276
|
+
const stackRebase = hasConflicts || (isBehind && exhaustedAttempts.length > 0)
|
|
277
|
+
? buildNativeStackLayerRebase(report.repo, { number: prNumber, baseBranch: baseLookup.branch }, report.mergeStatus.mergeRequirements?.stack)
|
|
278
|
+
: undefined;
|
|
279
|
+
const instructions = buildFixInstructions(threads, actionableComments, checks, changesRequestedReviews, baseLookup.branch, resolveCommand, hasConflicts, prReference, cancelled.length, firstLookThreads, firstLookComments, firstLookSummaries, editedSummaries, inProgressRunIds, resolutionOnlyThreads, resolveOnlyCommand, behindBaseHint, isBehind, report.viewerAuthorization?.viewerCanUpdate === true, exhaustedAttempts.length > 0, stackRebase);
|
|
275
280
|
if (repairInstructions && repairInstructions.length > 0) {
|
|
276
281
|
instructions.unshift(...repairInstructions);
|
|
277
282
|
}
|
|
@@ -7,6 +7,5 @@ export declare function buildTerminalCancelResult(report: ShepherdReport): Itera
|
|
|
7
7
|
/** Build completed, non-skipped checks relevant to PR readiness. */
|
|
8
8
|
export declare function buildRelevantChecks(report: ShepherdReport): RelevantCheck[];
|
|
9
9
|
export declare function buildActiveChecks(report: ShepherdReport): ActiveCheck[];
|
|
10
|
-
export declare function getCurrentHeadSha(): Promise<string | null>;
|
|
11
10
|
export declare function buildWaitLog(base: IterateResultBase): string;
|
|
12
11
|
export declare function blockedCancelNote(base: IterateResultBase): string;
|
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
import { execFile as execFileCb } from "node:child_process";
|
|
2
|
-
import { promisify } from "node:util";
|
|
3
|
-
import { getExecutionCwd } from "../../execution-context.mjs";
|
|
4
1
|
import { blockedReasonFromRequirements } from "../../merge-status/requirements-format.mjs";
|
|
5
|
-
const execFile = promisify(execFileCb);
|
|
6
2
|
export function buildSummary(report) {
|
|
7
3
|
return {
|
|
8
4
|
passing: report.checks.passing.length,
|
|
@@ -104,17 +100,6 @@ export function buildActiveChecks(report) {
|
|
|
104
100
|
...(c.commitOid !== undefined && { commitOid: c.commitOid }),
|
|
105
101
|
}));
|
|
106
102
|
}
|
|
107
|
-
export async function getCurrentHeadSha() {
|
|
108
|
-
try {
|
|
109
|
-
const { stdout } = await execFile("git", ["rev-parse", "HEAD"], {
|
|
110
|
-
cwd: getExecutionCwd(),
|
|
111
|
-
});
|
|
112
|
-
return stdout.trim();
|
|
113
|
-
}
|
|
114
|
-
catch {
|
|
115
|
-
return null;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
103
|
export function buildWaitLog(base) {
|
|
119
104
|
const { summary, remainingSeconds } = base;
|
|
120
105
|
const parts = [`WAIT: ${summary.passing} passing, ${summary.inProgress} in-progress`];
|