pr-shepherd 0.54.1 → 0.55.1
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 +3 -3
- package/bin/checks/unreported-required.d.mts +29 -0
- package/bin/checks/unreported-required.mjs +52 -0
- package/bin/classify/apply.d.mts +2 -0
- package/bin/classify/apply.mjs +31 -31
- package/bin/classify/rule-action.d.mts +8 -0
- package/bin/classify/rule-action.mjs +29 -0
- package/bin/classify/types.d.mts +1 -1
- package/bin/cli/help-command-pages.d.mts +2 -2
- package/bin/cli/help-iterate-poll-pages.d.mts +2 -2
- package/bin/cli/help-iterate-poll-pages.mjs +6 -5
- package/bin/cli/help-top-page.d.mts +1 -1
- package/bin/cli/help-top-page.mjs +2 -2
- package/bin/cli/help.d.mts +3 -3
- package/bin/cli/iterate-formatter.mjs +32 -9
- package/bin/cli/iterate-instructions.mjs +6 -0
- package/bin/cli/iterate-lean.mjs +17 -0
- package/bin/cli/poll-summary-emitter.mjs +4 -1
- package/bin/cli/poll-summary-formatter.mjs +10 -3
- package/bin/cli/stack-overview.d.mts +48 -0
- package/bin/cli/stack-overview.mjs +138 -0
- package/bin/commands/check-fingerprint.mjs +2 -1
- package/bin/commands/check-status.d.mts +1 -1
- package/bin/commands/check-status.mjs +8 -3
- package/bin/commands/check-unreported.d.mts +28 -0
- package/bin/commands/check-unreported.mjs +101 -0
- package/bin/commands/check.mjs +45 -38
- package/bin/commands/commit-suggestion-instruction.d.mts +1 -1
- package/bin/commands/commit-suggestion-instruction.mjs +1 -1
- package/bin/commands/iterate/base.mjs +11 -0
- package/bin/commands/iterate/check-instructions.d.mts +1 -1
- package/bin/commands/iterate/check-instructions.mjs +1 -1
- package/bin/commands/iterate/escalate.mjs +4 -0
- package/bin/commands/iterate/index.mjs +69 -3
- package/bin/commands/iterate/merge-state.mjs +12 -12
- package/bin/commands/iterate/merge.d.mts +12 -2
- package/bin/commands/iterate/merge.mjs +32 -2
- package/bin/commands/iterate/unreported-required.d.mts +18 -0
- package/bin/commands/iterate/unreported-required.mjs +136 -0
- package/bin/commands/poll-summary.mjs +1 -0
- package/bin/commands/poll.mjs +9 -2
- package/bin/commands/ready-mergeability.d.mts +1 -1
- package/bin/commands/ready-mergeability.mjs +2 -2
- package/bin/commands/rule-auto-resolve-format.d.mts +22 -0
- package/bin/commands/rule-auto-resolve-format.mjs +151 -0
- package/bin/commands/rule-auto-resolve.d.mts +21 -0
- package/bin/commands/rule-auto-resolve.mjs +113 -0
- package/bin/commands/shepherd-journal.d.mts +1 -1
- package/bin/commands/shepherd-journal.mjs +1 -1
- package/bin/commands/stack-drain.d.mts +0 -5
- package/bin/commands/stack-drain.mjs +26 -16
- package/bin/commands/stack-merge-flag.d.mts +7 -0
- package/bin/commands/stack-merge-flag.mjs +6 -0
- package/bin/config/load.d.mts +3 -0
- package/bin/config/load.mjs +9 -2
- package/bin/config/merge-method.d.mts +27 -0
- package/bin/config/merge-method.mjs +56 -0
- package/bin/exit-codes.d.mts +1 -1
- package/bin/exit-codes.mjs +2 -1
- package/bin/github/batch-parse-suites.d.mts +3 -0
- package/bin/github/batch-parse-suites.mjs +15 -0
- package/bin/github/batch-parsers.d.mts +1 -1
- package/bin/github/batch-parsers.mjs +7 -0
- package/bin/github/batch-raw-types.d.mts +5 -0
- package/bin/github/batch.d.mts +3 -0
- package/bin/github/batch.mjs +9 -1
- package/bin/github/errors.d.mts +6 -0
- package/bin/github/errors.mjs +23 -5
- package/bin/github/fingerprint-fields.d.mts +1 -0
- package/bin/github/fingerprint-fields.mjs +1 -1
- package/bin/github/gql/base-behind.gql +20 -0
- package/bin/github/gql/batch-pr-page.gql +2 -0
- package/bin/github/gql/batch-pr.gql +5 -0
- package/bin/github/gql/commit-check-suites.gql +1 -0
- package/bin/github/gql/poll-stack-summary.gql +6 -0
- package/bin/github/gql/poll-summary-annotation-probe.gql +32 -0
- package/bin/github/gql/poll-summary-check-contexts.gql +2 -3
- package/bin/github/gql/poll-summary-fragment.gql +16 -0
- package/bin/github/gql/pr-merge-policy.gql +1 -44
- package/bin/github/gql/ref-rules-query.gql +18 -0
- package/bin/github/gql/ref-rules.gql +46 -0
- package/bin/github/graphql-internal-retry.d.mts +1 -1
- package/bin/github/graphql-internal-retry.mjs +4 -3
- package/bin/github/merge-queue-checks.mjs +7 -3
- package/bin/github/merge-target-rules.d.mts +28 -0
- package/bin/github/merge-target-rules.mjs +77 -0
- package/bin/github/poll-summary-annotation-probe.d.mts +19 -0
- package/bin/github/poll-summary-annotation-probe.mjs +88 -0
- package/bin/github/poll-summary-fingerprint.mjs +1 -1
- package/bin/github/poll-summary-projector.d.mts +1 -1
- package/bin/github/poll-summary-projector.mjs +19 -12
- package/bin/github/poll-summary-queue-removal.mjs +7 -3
- package/bin/github/poll-summary-raw.d.mts +16 -0
- package/bin/github/poll-summary-readiness.mjs +1 -0
- package/bin/github/poll-summary-route.mjs +5 -0
- package/bin/github/poll-summary-unreported.d.mts +6 -0
- package/bin/github/poll-summary-unreported.mjs +51 -0
- package/bin/github/poll-summary.d.mts +1 -0
- package/bin/github/poll-summary.mjs +28 -3
- package/bin/github/queries.d.mts +9 -0
- package/bin/github/queries.mjs +11 -2
- package/bin/github/queue-removal-freshness.d.mts +20 -5
- package/bin/github/queue-removal-freshness.mjs +37 -10
- package/bin/github/stack-read.d.mts +4 -0
- package/bin/github/stack-read.mjs +13 -1
- package/bin/mcp/server.mjs +6 -1
- package/bin/state/ci-retrigger.d.mts +25 -0
- package/bin/state/ci-retrigger.mjs +48 -0
- package/bin/types/escalate.d.mts +1 -1
- package/bin/types/github.d.mts +11 -0
- package/bin/types/iterate.d.mts +16 -3
- package/bin/types/poll-summary.d.mts +13 -0
- package/bin/types/report.d.mts +34 -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/plugins/pr-shepherd/skills/pr-shepherd/SKILL.md +3 -3
- package/plugins/pr-shepherd/skills/reduce-pr-noise/references/classifiers.md +1 -1
- package/src/classify/types.mts +1 -1
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One close/reopen of a head that was missing required checks.
|
|
3
|
+
*
|
|
4
|
+
* `$PR_SHEPHERD_STATE_DIR/<owner>/<repo>/<pr>/ci-retrigger.json`
|
|
5
|
+
* Reopening does not change the head SHA, so the next tick must not close the PR again.
|
|
6
|
+
*/
|
|
7
|
+
interface Retrigger {
|
|
8
|
+
headSha: string;
|
|
9
|
+
contexts: string[];
|
|
10
|
+
}
|
|
11
|
+
/** The stored head and context set, or undefined when no usable marker exists. */
|
|
12
|
+
export declare function readCiRetrigger(key: {
|
|
13
|
+
owner: string;
|
|
14
|
+
repo: string;
|
|
15
|
+
pr: number;
|
|
16
|
+
}): Promise<Retrigger | undefined>;
|
|
17
|
+
/** Remember that this head was already closed and reopened for these contexts. */
|
|
18
|
+
export declare function writeCiRetrigger(key: {
|
|
19
|
+
owner: string;
|
|
20
|
+
repo: string;
|
|
21
|
+
pr: number;
|
|
22
|
+
}, record: Retrigger): Promise<void>;
|
|
23
|
+
/** True when this head was already retriggered for the same required contexts. */
|
|
24
|
+
export declare function sameCiRetrigger(record: Retrigger | undefined, headSha: string, contexts: readonly string[]): boolean;
|
|
25
|
+
export {};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One close/reopen of a head that was missing required checks.
|
|
3
|
+
*
|
|
4
|
+
* `$PR_SHEPHERD_STATE_DIR/<owner>/<repo>/<pr>/ci-retrigger.json`
|
|
5
|
+
* Reopening does not change the head SHA, so the next tick must not close the PR again.
|
|
6
|
+
*/
|
|
7
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
8
|
+
import { dirname } from "node:path";
|
|
9
|
+
import { resolvePrStatePath } from "./base.mjs";
|
|
10
|
+
/** The stored head and context set, or undefined when no usable marker exists. */
|
|
11
|
+
export async function readCiRetrigger(key) {
|
|
12
|
+
return readRetrigger(resolvePrStatePath(key, "ci-retrigger.json"));
|
|
13
|
+
}
|
|
14
|
+
/** Remember that this head was already closed and reopened for these contexts. */
|
|
15
|
+
export async function writeCiRetrigger(key, record) {
|
|
16
|
+
const path = resolvePrStatePath(key, "ci-retrigger.json");
|
|
17
|
+
await mkdir(dirname(path), { recursive: true });
|
|
18
|
+
const next = {
|
|
19
|
+
headSha: record.headSha,
|
|
20
|
+
contexts: [...record.contexts].sort(),
|
|
21
|
+
};
|
|
22
|
+
await writeFile(path, JSON.stringify(next));
|
|
23
|
+
}
|
|
24
|
+
/** True when this head was already retriggered for the same required contexts. */
|
|
25
|
+
export function sameCiRetrigger(record, headSha, contexts) {
|
|
26
|
+
if (!record || record.headSha !== headSha)
|
|
27
|
+
return false;
|
|
28
|
+
const stored = [...record.contexts].sort();
|
|
29
|
+
const current = [...contexts].sort();
|
|
30
|
+
return stored.length === current.length && stored.every((name, index) => name === current[index]);
|
|
31
|
+
}
|
|
32
|
+
async function readRetrigger(path) {
|
|
33
|
+
try {
|
|
34
|
+
const parsed = JSON.parse(await readFile(path, "utf8"));
|
|
35
|
+
if (parsed === null || typeof parsed !== "object")
|
|
36
|
+
return undefined;
|
|
37
|
+
const headSha = parsed.headSha;
|
|
38
|
+
const contexts = parsed.contexts;
|
|
39
|
+
if (typeof headSha !== "string" || !Array.isArray(contexts))
|
|
40
|
+
return undefined;
|
|
41
|
+
if (!contexts.every((name) => typeof name === "string"))
|
|
42
|
+
return undefined;
|
|
43
|
+
return { headSha, contexts };
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return undefined;
|
|
47
|
+
}
|
|
48
|
+
}
|
package/bin/types/escalate.d.mts
CHANGED
|
@@ -2,7 +2,7 @@ import type { AgentCheck, AgentComment, AgentThread } from "./report.mts";
|
|
|
2
2
|
import type { ResolveCommand } from "./iterate.mts";
|
|
3
3
|
import type { CheckStatus, Review } from "./github.mts";
|
|
4
4
|
import type { MergeQueueRemovalStatus } from "./merge-requirements.mts";
|
|
5
|
-
export type EscalateTrigger = "fix-thrash" | "base-branch-unknown" | "stall-timeout" | "stall-state-unavailable" | "check-follow-up-unavailable" | "authorization-required" | "merge-queue-removed";
|
|
5
|
+
export type EscalateTrigger = "fix-thrash" | "base-branch-unknown" | "stall-timeout" | "required-checks-unreported" | "stall-state-unavailable" | "check-follow-up-unavailable" | "authorization-required" | "merge-queue-removed" | "merge-method-unavailable";
|
|
6
6
|
export interface AgentStalledCheck {
|
|
7
7
|
name: string;
|
|
8
8
|
status: CheckStatus;
|
package/bin/types/github.d.mts
CHANGED
|
@@ -108,6 +108,8 @@ export interface Review {
|
|
|
108
108
|
staleBotCr?: boolean;
|
|
109
109
|
/** Commit OID the review was made against, when available from GraphQL. */
|
|
110
110
|
commitOid?: string;
|
|
111
|
+
/** Review HTML URL, when the batch query selected it. */
|
|
112
|
+
url?: string;
|
|
111
113
|
/** True when commitOid !== headRefOid AND all associated threads are resolved/outdated. Distinct from `staleBotCr` (time-based). Reviews with no threads are not marked stale. */
|
|
112
114
|
staleReview?: boolean;
|
|
113
115
|
}
|
|
@@ -139,10 +141,17 @@ export interface BatchPrData extends BatchPrMergeFields {
|
|
|
139
141
|
mergeStateStatus: MergeStateStatus;
|
|
140
142
|
reviewDecision: ReviewDecision;
|
|
141
143
|
headRefOid: string;
|
|
144
|
+
/**
|
|
145
|
+
* Earliest pull_request check-suite time on the head commit. Omitted when
|
|
146
|
+
* that signal is unavailable; queue-removal freshness then uses committer time.
|
|
147
|
+
*/
|
|
148
|
+
headPushedAtUnix?: number;
|
|
142
149
|
headRefName: string;
|
|
143
150
|
/** `"owner/name"` of the head repository; null when the fork has been deleted. */
|
|
144
151
|
headRepoWithOwner: string | null;
|
|
145
152
|
viewerAuthorization?: ViewerAuthorization;
|
|
153
|
+
/** GitHub `viewer.login` for the token that fetched this batch. */
|
|
154
|
+
viewerLogin?: string;
|
|
146
155
|
baseRefName: string;
|
|
147
156
|
/** Base commit GitHub recorded for this PR (`PullRequest.baseRefOid`), not the branch's live tip. */
|
|
148
157
|
baseRefOid?: string;
|
|
@@ -164,6 +173,8 @@ export interface BatchPrData extends BatchPrMergeFields {
|
|
|
164
173
|
removedMergeQueueChecks?: CheckRun[];
|
|
165
174
|
removedMergeQueueChecksIncomplete?: true;
|
|
166
175
|
branchProtection: BranchProtection | null;
|
|
176
|
+
/** Repository merge methods. Omitted when the batch did not select them. Empty when none are enabled. */
|
|
177
|
+
allowedMergeMethods?: import("../config/merge-method.mts").MergeMethod[];
|
|
167
178
|
activity?: PrActivitySummary;
|
|
168
179
|
}
|
|
169
180
|
export {};
|
package/bin/types/iterate.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AgentThread, AgentComment, AgentCheck, GlobalOptions, RelevantCheck, ShepherdStatus, FirstLookThread, FirstLookComment } from "./report.mts";
|
|
1
|
+
import type { AgentThread, AgentComment, AgentCheck, GlobalOptions, RelevantCheck, ShepherdStatus, FirstLookThread, FirstLookComment, RuleAutoResolveReport } from "./report.mts";
|
|
2
2
|
import type { ActiveCheck, PrActivitySummary } from "./activity.mts";
|
|
3
3
|
import type { BranchProtection, MergeStateStatus, Review, ReviewDecision, ReviewThread, ShepherdMergeStatus } from "./github.mts";
|
|
4
4
|
import type { MergeRequirements, StackDraftHold } from "./merge-requirements.mts";
|
|
@@ -6,7 +6,7 @@ import type { EscalateDetails } from "./escalate.mts";
|
|
|
6
6
|
import type { MergeCommandPlan } from "./merge-action.mts";
|
|
7
7
|
import type { ProtectedRun } from "./protected-run.mts";
|
|
8
8
|
import type { ApiUsage, GraphqlQuotaWarning } from "./api-usage.mts";
|
|
9
|
-
export type ShepherdAction = "wait" | "fix_code" | "mark_ready" | "merge" | "cancel" | "escalate";
|
|
9
|
+
export type ShepherdAction = "wait" | "ready" | "fix_code" | "mark_ready" | "merge" | "cancel" | "escalate";
|
|
10
10
|
export interface IterateResultSummary {
|
|
11
11
|
passing: number;
|
|
12
12
|
skipped: number;
|
|
@@ -45,11 +45,19 @@ export interface IterateResultBase {
|
|
|
45
45
|
inProgressChecks?: ActiveCheck[];
|
|
46
46
|
ignoredNames?: string[];
|
|
47
47
|
supersededNames?: string[];
|
|
48
|
+
/** Required merge-target contexts with no check run and no status context. Omitted when empty. */
|
|
49
|
+
unreportedRequiredChecks?: string[];
|
|
50
|
+
/** Commits on the stack trunk that the bottom open layer does not contain. Omitted when zero. */
|
|
51
|
+
trunkBehindBy?: number;
|
|
52
|
+
/** Commits on the PR base that this head does not contain. Omitted when zero. */
|
|
53
|
+
baseBehindBy?: number;
|
|
48
54
|
activity?: PrActivitySummary;
|
|
49
55
|
mergeQueue?: import("./merge-queue.mts").MergeQueueReport;
|
|
50
56
|
apiUsage?: ApiUsage;
|
|
51
57
|
quotaWarning?: GraphqlQuotaWarning;
|
|
52
58
|
fingerprintReused?: true;
|
|
59
|
+
/** Classification-rule resolve/minimize applied during this fetch. Omitted when nothing happened. */
|
|
60
|
+
ruleAutoResolve?: RuleAutoResolveReport;
|
|
53
61
|
}
|
|
54
62
|
interface IterateResultWait extends IterateResultBase {
|
|
55
63
|
action: "wait";
|
|
@@ -57,6 +65,11 @@ interface IterateResultWait extends IterateResultBase {
|
|
|
57
65
|
deferredWork?: import("./merge-queue.mts").IterateDeferredWork;
|
|
58
66
|
stackDraftHold?: StackDraftHold;
|
|
59
67
|
}
|
|
68
|
+
/** Clean PR whose ready-delay is still counting. `--until-terminal` returns this instead of sleeping. */
|
|
69
|
+
interface IterateResultReady extends IterateResultBase {
|
|
70
|
+
action: "ready";
|
|
71
|
+
log: string;
|
|
72
|
+
}
|
|
60
73
|
export type CancelReason = "merged" | "closed" | "ready-delay-elapsed";
|
|
61
74
|
interface IterateResultCancel extends IterateResultBase {
|
|
62
75
|
action: "cancel";
|
|
@@ -134,7 +147,7 @@ interface IterateResultEscalate extends IterateResultBase {
|
|
|
134
147
|
action: "escalate";
|
|
135
148
|
escalate: EscalateDetails;
|
|
136
149
|
}
|
|
137
|
-
export type IterateResult = IterateResultWait | IterateResultCancel | IterateResultFixCode | IterateResultMarkReady | IterateResultMerge | IterateResultEscalate;
|
|
150
|
+
export type IterateResult = IterateResultWait | IterateResultReady | IterateResultCancel | IterateResultFixCode | IterateResultMarkReady | IterateResultMerge | IterateResultEscalate;
|
|
138
151
|
export interface IterateCommandOptions extends GlobalOptions {
|
|
139
152
|
readyDelaySeconds?: number;
|
|
140
153
|
noAutoMarkReady?: boolean;
|
|
@@ -11,6 +11,10 @@ export interface PollSummaryChecks {
|
|
|
11
11
|
ignored?: number;
|
|
12
12
|
superseded?: number;
|
|
13
13
|
incomplete?: true;
|
|
14
|
+
/** Required contexts with no check run and no status context. Omitted when empty. */
|
|
15
|
+
unreportedRequired?: string[];
|
|
16
|
+
/** A relevant Actions workflow suite has not completed. */
|
|
17
|
+
actionsWorkflowInProgress?: true;
|
|
14
18
|
}
|
|
15
19
|
export interface PollSummaryReview {
|
|
16
20
|
comments?: number;
|
|
@@ -39,6 +43,10 @@ export interface PollSummaryItem {
|
|
|
39
43
|
repo: string;
|
|
40
44
|
title: string;
|
|
41
45
|
url: string;
|
|
46
|
+
/** GitHub author login, when the summary query returned one. */
|
|
47
|
+
authorLogin?: string;
|
|
48
|
+
/** Author login matches the authenticated viewer. */
|
|
49
|
+
owned?: true;
|
|
42
50
|
/** Conservative routing hint; the selected one-PR poll makes the authoritative decision. */
|
|
43
51
|
action: ShepherdAction;
|
|
44
52
|
reasons: string[];
|
|
@@ -89,6 +97,11 @@ export interface PollSummaryResult {
|
|
|
89
97
|
nextAction?: StackNextAction;
|
|
90
98
|
/** Whether every open layer is independently ready and stack ancestry is linear. */
|
|
91
99
|
stackMergeable?: boolean;
|
|
100
|
+
/**
|
|
101
|
+
* Repository merge methods for stack merge commands. Omitted from the lean
|
|
102
|
+
* stack overview. Empty when the repository enables none.
|
|
103
|
+
*/
|
|
104
|
+
allowedMergeMethods?: import("../config/merge-method.mts").MergeMethod[];
|
|
92
105
|
instructions?: string[];
|
|
93
106
|
apiUsage?: ApiUsage;
|
|
94
107
|
quotaWarning?: GraphqlQuotaWarning;
|
package/bin/types/report.d.mts
CHANGED
|
@@ -4,6 +4,21 @@ import type { AgentThreadComment } from "./agent-thread.mts";
|
|
|
4
4
|
import type { CheckAnnotation } from "./check-annotations.mts";
|
|
5
5
|
import type { PrActivitySummary } from "./activity.mts";
|
|
6
6
|
import type { MergeQueueReport } from "./merge-queue.mts";
|
|
7
|
+
export interface AutoMinimizedItem {
|
|
8
|
+
id: string;
|
|
9
|
+
url?: string;
|
|
10
|
+
kind: "pr-comment" | "review-summary";
|
|
11
|
+
ruleReason?: string;
|
|
12
|
+
}
|
|
13
|
+
export type AutoResolvedThread = ReviewThread & {
|
|
14
|
+
ruleReason?: string;
|
|
15
|
+
};
|
|
16
|
+
export interface RuleAutoResolveReport {
|
|
17
|
+
summary: string;
|
|
18
|
+
threads?: AutoResolvedThread[];
|
|
19
|
+
minimized?: AutoMinimizedItem[];
|
|
20
|
+
errors?: string[];
|
|
21
|
+
}
|
|
7
22
|
export interface FirstLookThread extends ReviewThread {
|
|
8
23
|
firstLookStatus: "outdated" | "resolved" | "minimized";
|
|
9
24
|
autoResolved?: boolean;
|
|
@@ -23,6 +38,8 @@ export interface ShepherdReport {
|
|
|
23
38
|
nodeId: string;
|
|
24
39
|
/** GitHub PR head OID from the same batch used to decide the action. */
|
|
25
40
|
headSha?: string;
|
|
41
|
+
/** PR head branch name. Used to compare a native stack against its trunk. */
|
|
42
|
+
headRefName?: string;
|
|
26
43
|
/** Internal. True when this report was reused from the fingerprint cache. */
|
|
27
44
|
fingerprintReused?: true;
|
|
28
45
|
repo: string;
|
|
@@ -54,8 +71,10 @@ export interface ShepherdReport {
|
|
|
54
71
|
actionable: ReviewThread[];
|
|
55
72
|
/** Unresolved threads that need a GitHub resolve mutation but do not require code edits. */
|
|
56
73
|
resolutionOnly: ReviewThread[];
|
|
57
|
-
autoResolved:
|
|
74
|
+
autoResolved: AutoResolvedThread[];
|
|
58
75
|
autoResolveErrors: string[];
|
|
76
|
+
/** Rule reasons for this fetch's auto-resolve errors. Omitted when empty. */
|
|
77
|
+
autoResolveErrorReasons?: string[];
|
|
59
78
|
/** First-look items — outdated/resolved/minimized threads not yet seen by the agent. */
|
|
60
79
|
firstLook: FirstLookThread[];
|
|
61
80
|
/** Thread IDs matched by user classification rules with autoResolve:true — routed to resolveThreadIds. */
|
|
@@ -67,6 +86,8 @@ export interface ShepherdReport {
|
|
|
67
86
|
minimizeIds?: string[];
|
|
68
87
|
/** First-look items — minimized comments not yet seen by the agent. */
|
|
69
88
|
firstLook: FirstLookComment[];
|
|
89
|
+
/** PR comments and review summaries minimized by a suppress+autoResolve rule this fetch. */
|
|
90
|
+
autoMinimized?: AutoMinimizedItem[];
|
|
70
91
|
};
|
|
71
92
|
changesRequestedReviews: Review[];
|
|
72
93
|
/** COMMENTED reviews already seen — eligible for `--minimize-comment-ids` without re-rendering. */
|
|
@@ -81,8 +102,20 @@ export interface ShepherdReport {
|
|
|
81
102
|
ruleAutoResolveReviewSummaryIds?: string[];
|
|
82
103
|
/** Branch protection rule for the PR's base branch. Null when no rule exists or the base ref is unavailable. */
|
|
83
104
|
branchProtection: import("./github.mts").BranchProtection | null;
|
|
105
|
+
/** Repository merge methods from the same batch. Omitted when that query did not select them. */
|
|
106
|
+
allowedMergeMethods?: import("../config/merge-method.mts").MergeMethod[];
|
|
84
107
|
activity?: PrActivitySummary;
|
|
85
108
|
mergeQueue?: MergeQueueReport;
|
|
109
|
+
/** Required merge-target contexts with no check run and no status context. Omitted when empty. */
|
|
110
|
+
unreportedRequiredChecks?: string[];
|
|
111
|
+
/** Commits on the stack trunk that the bottom open layer does not contain. Omitted when zero. */
|
|
112
|
+
trunkBehindBy?: number;
|
|
113
|
+
/** Commits on the PR base that this head does not contain. Omitted when zero. */
|
|
114
|
+
baseBehindBy?: number;
|
|
115
|
+
/** A relevant Actions workflow suite on the head has not completed. */
|
|
116
|
+
actionsWorkflowInProgress?: true;
|
|
117
|
+
/** Bottom open layer of this PR's native stack. Starts a trunk rebase. */
|
|
118
|
+
stackBottomPr?: number;
|
|
86
119
|
}
|
|
87
120
|
export interface ResolveOptions {
|
|
88
121
|
resolveThreadIds?: string[];
|
package/package.json
CHANGED
|
@@ -18,13 +18,13 @@ If the requested PR does not exist yet, review and commit the in-scope changes,
|
|
|
18
18
|
|
|
19
19
|
## Arguments: $ARGUMENTS
|
|
20
20
|
|
|
21
|
-
1. Parse optional PR numbers, repository-qualified `owner/repo#N` references, or GitHub PR URLs and an optional `--merge` flag from `$ARGUMENTS`; alternatively parse one `--stack PR` selector. A clear request to merge, land, or enqueue the selected PR or stack also opts into `--merge` without a literal flag; a request only to create or open a PR does not. When the user asks to shepherd or merge a native stack and supplies an anchor PR without a literal `--stack`, use that PR as the `--stack` selector. Otherwise let pr-shepherd infer the current branch PR. Reject any remaining argument. Follow the target repository's local `AGENTS.md`
|
|
21
|
+
1. Parse optional PR numbers, repository-qualified `owner/repo#N` references, or GitHub PR URLs and an optional `--merge` flag from `$ARGUMENTS`; alternatively parse one `--stack PR` selector. A clear request to merge, land, or enqueue the selected PR or stack also opts into `--merge` without a literal flag; a request only to create or open a PR does not. When the user asks to shepherd or merge a native stack and supplies an anchor PR without a literal `--stack`, use that PR as the `--stack` selector. Otherwise let pr-shepherd infer the current branch PR. Reject any remaining argument. Follow the target repository's local `AGENTS.md` standards while making changes.
|
|
22
22
|
|
|
23
23
|
2. For the CLI, convert supplied `owner/repo#N` references to `https://github.com/owner/repo/pull/N`; otherwise pass supplied URLs or bare numbers unchanged, then run `pr-shepherd [PR ...] --until-terminal`, or `pr-shepherd --stack PR --until-terminal` for a stack, omitting `[PR ...]` when none was supplied and appending `--merge` when requested. This command keeps ordinary `[WAIT]` and `[MARK_READY]` ticks inside the same invocation; aggregate selectors return their next stack action or terminal result. A qualified reference may name a fork or upstream repository: it is the GitHub target, while the current checkout continues to supply local git/config/rules context. Do not run `pr-shepherd iterate`. If the CLI is unavailable and the `iterate` MCP tool is available, first repository-qualify every supplied reference with its GitHub URL or `owner/repo#N`; resolve bare numbers through `gh pr view <number> --json url --jq .url`, and resolve an omitted target with `gh pr view --json url --jq .url`. If that does not produce the required qualified selector, stop and report that MCP cannot safely determine it. Otherwise call `iterate` with `pr`, `prs`, or `stack` as selected, plus `merge: true` when merge intent was requested, and print its full result.
|
|
24
24
|
|
|
25
|
-
3. Print the full result and follow every returned `## Instructions` step exactly. For CLI output, run each printed mutation command when instructed. For MCP output, use MCP `apply` and `build_suggestion_patches` with the same qualified PR reference; do not run a shell `pr-shepherd apply` command.
|
|
25
|
+
3. Print the full result and follow every returned `## Instructions` step exactly. For CLI output, run each printed mutation command when instructed. For MCP output, use MCP `apply` and `build_suggestion_patches` with the same qualified PR reference; do not run a shell `pr-shepherd apply` command. On a stack overview, run one-PR shepherd, mark-ready, and push steps only for rows marked `owned`. Leave every other author's layer listed and untouched. If every session belongs to someone else, report the overview and stop. If at least one owned layer needs a session, shepherd those, then rerun the same `--stack` command.
|
|
26
26
|
|
|
27
|
-
4. After completing the returned instructions, immediately repeat step 2 with the same target and canonical options unless the action is `[CANCEL]` or `[ESCALATE]`, or the human directs you to stop. Preserve `--until-terminal` and any requested `--merge`; apply any polling-cadence adjustment printed by the CLI. Every other action is non-terminal: complete its instructions and rerun without asking whether to continue. `[FIX_CODE]` is always non-terminal, as is stack-level `[SHEPHERD]`; only `[ESCALATE]` hands work to a human. After a push or `rerun:`, do not wait for CI to finish first — you may pull check logs, but do not poll with `gh pr checks`, `gh pr watch`, `gh run watch`, or equivalent GitHub MCP check waiters.
|
|
27
|
+
4. After completing the returned instructions, immediately repeat step 2 with the same target and canonical options unless the action is `[CANCEL]` or `[ESCALATE]`, or the human directs you to stop. A stack overview heading includes those same tokens when `nextAction` is `cancel` or `escalate`. On a stack overview, if no row marked `owned` needs a session, stop instead of rerunning. Preserve `--until-terminal` and any requested `--merge`; apply any polling-cadence adjustment printed by the CLI. Every other action is non-terminal: complete its instructions and rerun without asking whether to continue. `[FIX_CODE]` is always non-terminal, as is stack-level `[SHEPHERD]`; only `[ESCALATE]` hands work to a human. `[READY]` is also non-terminal: wait out its `remainingSeconds`, then rerun the same command. Do not start other work during that countdown. After a push or `rerun:`, do not wait for CI to finish first — you may pull check logs, but do not poll with `gh pr checks`, `gh pr watch`, `gh run watch`, or equivalent GitHub MCP check waiters.
|
|
28
28
|
|
|
29
29
|
## Playbooks
|
|
30
30
|
|
|
@@ -19,6 +19,6 @@ const rule: ClassifyRule = (item) => {
|
|
|
19
19
|
export default rule;
|
|
20
20
|
```
|
|
21
21
|
|
|
22
|
-
`suppress: true` removes a matched item from agent output. Add `autoResolve: true` only when the requested policy also calls for resolving its thread or minimizing its comment or review summary. It is unsupported for `changes-requested` reviews, whose dismissal needs a message. With both flags, `actions.autoMinimizeSuppressed: true` lets Shepherd perform the authorized mutation
|
|
22
|
+
`suppress: true` removes a matched item from agent output. Add `autoResolve: true` only when the requested policy also calls for resolving its thread or minimizing its comment or review summary. It is unsupported for `changes-requested` reviews, whose dismissal needs a message. Optional `reason` is the note printed, reported, and journaled when the rule fires. With both flags, `actions.autoMinimizeSuppressed: true` (the default) lets Shepherd perform the authorized mutation, then print a `## Classification auto-resolve` line, record `threads.autoResolved` / `comments.autoMinimized`, and append one Shepherd Journal item for the token login. Failed IDs stay on the generated `apply review` command and the failure is listed under that line. Set `actions.autoMinimizeSuppressed: false` to keep the handoff without mutating, journaling, or printing the line. When GitHub does not confirm capability, the item returns to normal first-look visibility. Matching rules combine their flags and keep every non-empty reason, so inspect existing rules before adding one.
|
|
23
23
|
|
|
24
24
|
Exercise the exported rule against the observed item and negative examples: a different author, kind, and substantive message from the same bot. Confirm only the intended item matches before enabling automatic resolution. After editing a rule, restart a persistent MCP server or long-running poll process; it caches loaded rule modules. A new CLI process loads the change. A classifier does not retroactively remove already displayed output.
|
package/src/classify/types.mts
CHANGED
|
@@ -53,7 +53,7 @@ export interface ClassifyAction {
|
|
|
53
53
|
readonly autoResolve?: boolean;
|
|
54
54
|
/** When true, hides the item from agent output (seen marker is still written). */
|
|
55
55
|
readonly suppress?: boolean;
|
|
56
|
-
/**
|
|
56
|
+
/** Note included in the auto-resolve report, tick line, and Shepherd Journal when this rule fires. */
|
|
57
57
|
readonly reason?: string;
|
|
58
58
|
}
|
|
59
59
|
|