pr-shepherd 0.42.0 → 0.44.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 +24 -18
- package/bin/api.d.mts +3 -2
- package/bin/api.mjs +13 -18
- package/bin/checks/classify.d.mts +3 -1
- package/bin/checks/classify.mjs +5 -2
- package/bin/cli/args.mjs +14 -9
- package/bin/cli/default-poll.mjs +1 -0
- package/bin/cli/fix-formatter.mjs +20 -8
- package/bin/cli/handlers.mjs +1 -0
- package/bin/cli/help-command-pages.d.mts +9 -6
- package/bin/cli/help-command-pages.mjs +7 -4
- package/bin/cli/help-iterate-poll-pages.d.mts +2 -2
- package/bin/cli/help-iterate-poll-pages.mjs +9 -4
- 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 +10 -7
- package/bin/cli/iterate-flags.d.mts +1 -0
- package/bin/cli/iterate-flags.mjs +2 -0
- package/bin/cli/iterate-formatter.d.mts +1 -1
- package/bin/cli/iterate-formatter.mjs +9 -6
- package/bin/cli/iterate-instructions.mjs +15 -0
- package/bin/cli/iterate-lean.d.mts +1 -2
- package/bin/cli/iterate-lean.mjs +16 -17
- package/bin/cli/iterate-merge-formatter.d.mts +3 -0
- package/bin/cli/iterate-merge-formatter.mjs +52 -0
- package/bin/cli/iterate-verbose.d.mts +6 -0
- package/bin/cli/iterate-verbose.mjs +14 -0
- package/bin/cli/journal-formatter.mjs +3 -0
- package/bin/cli/journal-handler.mjs +11 -7
- package/bin/cli/list-formatters.d.mts +3 -1
- package/bin/cli/list-formatters.mjs +9 -7
- package/bin/cli/mark-files-as-viewed-formatter.mjs +7 -1
- package/bin/cli/mutate-formatter.mjs +4 -0
- package/bin/cli/poll-handler.mjs +1 -0
- package/bin/cli/runner.mjs +4 -3
- package/bin/commands/check-terminal-report.mjs +1 -0
- package/bin/commands/check.mjs +64 -7
- package/bin/commands/commit-suggestion-instruction.d.mts +1 -1
- package/bin/commands/commit-suggestion-instruction.mjs +2 -2
- package/bin/commands/commit-suggestion.mjs +3 -1
- package/bin/commands/iterate/base.d.mts +5 -0
- package/bin/commands/iterate/base.mjs +25 -0
- package/bin/commands/iterate/check-instructions.d.mts +5 -19
- package/bin/commands/iterate/check-instructions.mjs +24 -25
- package/bin/commands/iterate/classify.d.mts +2 -2
- package/bin/commands/iterate/classify.mjs +43 -25
- package/bin/commands/iterate/escalate.d.mts +3 -1
- package/bin/commands/iterate/escalate.mjs +29 -2
- package/bin/commands/iterate/fix-code.mjs +81 -26
- package/bin/commands/iterate/helpers.d.mts +0 -2
- package/bin/commands/iterate/helpers.mjs +6 -17
- package/bin/commands/iterate/index.mjs +31 -43
- package/bin/commands/iterate/mark-ready.d.mts +2 -0
- package/bin/commands/iterate/mark-ready.mjs +38 -0
- package/bin/commands/iterate/merge-state.d.mts +15 -0
- package/bin/commands/iterate/merge-state.mjs +82 -0
- package/bin/commands/iterate/merge.d.mts +13 -0
- package/bin/commands/iterate/merge.mjs +45 -0
- package/bin/commands/iterate/render.d.mts +2 -2
- package/bin/commands/iterate/render.mjs +19 -20
- package/bin/commands/iterate/stall.mjs +4 -2
- package/bin/commands/iterate/thread-mutation-routing.d.mts +9 -0
- package/bin/commands/iterate/thread-mutation-routing.mjs +29 -0
- package/bin/commands/journal/index.d.mts +5 -0
- package/bin/commands/journal/index.mjs +11 -2
- package/bin/commands/mark-files-as-viewed.d.mts +2 -1
- package/bin/commands/mark-files-as-viewed.mjs +5 -92
- package/bin/commands/poll.mjs +3 -1
- package/bin/commands/resolve-mutate.mjs +51 -9
- package/bin/commands/shepherd-journal.d.mts +1 -1
- package/bin/commands/shepherd-journal.mjs +2 -2
- package/bin/commands/suggestion-patch-item.d.mts +1 -1
- package/bin/commands/suggestion-patch-item.mjs +3 -11
- package/bin/commands/suggestion-patches.mjs +3 -3
- package/bin/comments/authors.d.mts +6 -0
- package/bin/comments/authors.mjs +5 -0
- package/bin/comments/marker.d.mts +6 -1
- package/bin/comments/marker.mjs +8 -1
- package/bin/comments/resolve.d.mts +4 -0
- package/bin/comments/thread-visibility.mjs +10 -10
- package/bin/comments/visible-comments.mjs +2 -1
- package/bin/config/load.d.mts +5 -1
- package/bin/config/load.mjs +34 -0
- package/bin/config/merge-command-args.d.mts +2 -0
- package/bin/config/merge-command-args.mjs +44 -0
- package/bin/config.json +3 -0
- package/bin/exit-codes.d.mts +2 -0
- package/bin/exit-codes.mjs +4 -0
- package/bin/github/batch-parse-checks.d.mts +3 -0
- package/bin/github/batch-parse-checks.mjs +29 -0
- package/bin/github/batch-parsers-rules.d.mts +3 -1
- package/bin/github/batch-parsers-rules.mjs +33 -0
- package/bin/github/batch-parsers.d.mts +2 -2
- package/bin/github/batch-parsers.mjs +40 -27
- package/bin/github/batch-raw-rules.d.mts +48 -0
- package/bin/github/batch-raw-types.d.mts +12 -0
- package/bin/github/batch-raw-types.mjs +0 -1
- package/bin/github/batch.mjs +3 -1
- package/bin/github/client.d.mts +1 -0
- package/bin/github/client.mjs +8 -1
- package/bin/github/gql/batch-pr-page.gql +6 -0
- package/bin/github/gql/batch-pr.gql +105 -0
- package/bin/github/gql/commit-check-contexts.gql +58 -0
- package/bin/github/gql/get-pr-body.gql +1 -0
- package/bin/github/gql/review-thread-comments.gql +1 -0
- package/bin/github/gql/suggestion-threads.gql +1 -0
- package/bin/github/merge-queue-checks.d.mts +4 -0
- package/bin/github/merge-queue-checks.mjs +48 -0
- package/bin/github/queries.d.mts +2 -0
- package/bin/github/queries.mjs +2 -0
- package/bin/github/suggestion-thread.mjs +1 -0
- package/bin/mcp/server.mjs +13 -6
- package/bin/pr-reference.d.mts +13 -0
- package/bin/pr-reference.mjs +23 -1
- package/bin/reporters/agent.mjs +11 -3
- package/bin/threads/transcript.d.mts +2 -0
- package/bin/threads/transcript.mjs +2 -0
- package/bin/types/activity.d.mts +2 -0
- package/bin/types/agent-thread.d.mts +1 -0
- package/bin/types/escalate.d.mts +35 -0
- package/bin/types/escalate.mjs +1 -0
- package/bin/types/github.d.mts +27 -0
- package/bin/types/github.mjs +0 -3
- package/bin/types/iterate.d.mts +23 -39
- package/bin/types/merge-action.d.mts +12 -0
- package/bin/types/merge-action.mjs +1 -0
- package/bin/types/merge-queue.d.mts +13 -0
- package/bin/types/merge-queue.mjs +1 -0
- package/bin/types/merge-requirements.d.mts +17 -0
- package/bin/types/report.d.mts +22 -1
- package/bin/types/review-thread.d.mts +1 -0
- package/bin/types/suggestion-patch.d.mts +1 -1
- package/bin/types.d.mts +3 -0
- package/bin/types.mjs +3 -0
- package/bin/util/markdown.d.mts +2 -0
- package/bin/util/markdown.mjs +7 -0
- package/package.json +1 -1
- package/plugins/pr-shepherd/.codex-plugin/plugin.json +1 -1
- package/plugins/pr-shepherd/.codex.mcp.json +1 -1
- package/plugins/pr-shepherd/.mcp.json +1 -1
- package/plugins/pr-shepherd/skills/mark-files-as-viewed/SKILL.md +3 -3
- package/plugins/pr-shepherd/skills/pr-shepherd/SKILL.md +17 -15
- package/bin/commands/iterate/reruns.d.mts +0 -20
- package/bin/commands/iterate/reruns.mjs +0 -105
package/bin/types/github.mjs
CHANGED
package/bin/types/iterate.d.mts
CHANGED
|
@@ -1,37 +1,11 @@
|
|
|
1
1
|
import type { AgentThread, AgentComment, AgentCheck, GlobalOptions, RelevantCheck, ShepherdStatus, FirstLookThread, FirstLookComment } from "./report.mts";
|
|
2
2
|
import type { ActiveCheck, PrActivitySummary } from "./activity.mts";
|
|
3
|
-
import type { BranchProtection,
|
|
3
|
+
import type { BranchProtection, MergeStateStatus, Review, ReviewDecision, ReviewThread, ShepherdMergeStatus } from "./github.mts";
|
|
4
4
|
import type { MergeRequirements } from "./merge-requirements.mts";
|
|
5
|
+
import type { EscalateDetails } from "./escalate.mts";
|
|
6
|
+
import type { MergeCommandPlan } from "./merge-action.mts";
|
|
5
7
|
import type { ProtectedRun } from "./protected-run.mts";
|
|
6
|
-
export type ShepherdAction = "wait" | "fix_code" | "mark_ready" | "cancel" | "escalate";
|
|
7
|
-
export type EscalateTrigger = "fix-thrash" | "base-branch-unknown" | "stall-timeout" | "thread-missing-location" | "bot-cr-not-dismissed";
|
|
8
|
-
export interface AgentStalledCheck {
|
|
9
|
-
name: string;
|
|
10
|
-
status: CheckStatus;
|
|
11
|
-
source: "check_run" | "status_context" | "startup_failure";
|
|
12
|
-
runId: string | null;
|
|
13
|
-
detailsUrl: string | null;
|
|
14
|
-
createdAtUnix?: number;
|
|
15
|
-
startedAtUnix?: number;
|
|
16
|
-
updatedAtUnix?: number;
|
|
17
|
-
ageSeconds: number;
|
|
18
|
-
summary?: string;
|
|
19
|
-
}
|
|
20
|
-
export interface EscalateDetails {
|
|
21
|
-
triggers: EscalateTrigger[];
|
|
22
|
-
unresolvedThreads: AgentThread[];
|
|
23
|
-
ambiguousComments: AgentComment[];
|
|
24
|
-
changesRequestedReviews: Review[];
|
|
25
|
-
/** Pending/unstarted CI checks that exceeded the stall timeout. */
|
|
26
|
-
stalledChecks?: AgentStalledCheck[];
|
|
27
|
-
/** Populated when fix-thrash triggered — threads that have been attempted too many times. */
|
|
28
|
-
thrashHistory?: Array<{
|
|
29
|
-
threadId: string;
|
|
30
|
-
attempts: number;
|
|
31
|
-
}>;
|
|
32
|
-
suggestion: string;
|
|
33
|
-
humanMessage: string;
|
|
34
|
-
}
|
|
8
|
+
export type ShepherdAction = "wait" | "fix_code" | "mark_ready" | "merge" | "cancel" | "escalate";
|
|
35
9
|
export interface IterateResultSummary {
|
|
36
10
|
passing: number;
|
|
37
11
|
skipped: number;
|
|
@@ -66,6 +40,7 @@ export interface IterateResultBase {
|
|
|
66
40
|
ignoredNames?: string[];
|
|
67
41
|
supersededNames?: string[];
|
|
68
42
|
activity?: PrActivitySummary;
|
|
43
|
+
mergeQueue?: import("./merge-queue.mts").MergeQueueReport;
|
|
69
44
|
}
|
|
70
45
|
interface IterateResultWait extends IterateResultBase {
|
|
71
46
|
action: "wait";
|
|
@@ -84,9 +59,9 @@ export interface ResolveCommand {
|
|
|
84
59
|
requiresHeadSha: boolean;
|
|
85
60
|
/** Whether the model must substitute $DISMISS_MESSAGE with a specific description of the fix. */
|
|
86
61
|
requiresDismissMessage: boolean;
|
|
87
|
-
/** Thread IDs that should receive a reply
|
|
62
|
+
/** Thread IDs that should receive a reply. Viewer-authored human IDs may also appear in resolveThreadIds. */
|
|
88
63
|
replyThreadIds?: string[];
|
|
89
|
-
/** Thread IDs that should be resolved on GitHub. Human
|
|
64
|
+
/** Thread IDs that should be resolved on GitHub. Human IDs are allowed only for authenticated-viewer reply+resolve pairs or marker-ended retries. */
|
|
90
65
|
resolveThreadIds?: string[];
|
|
91
66
|
/** Bot/non-human CHANGES_REQUESTED review IDs to dismiss. Human-authored IDs must not appear here. */
|
|
92
67
|
dismissReviewIds?: string[];
|
|
@@ -94,8 +69,8 @@ export interface ResolveCommand {
|
|
|
94
69
|
hasMutations: boolean;
|
|
95
70
|
}
|
|
96
71
|
/**
|
|
97
|
-
* Default fix_code variant: agent applies edits locally, commits
|
|
98
|
-
* then runs the pre-built apply command. Emitted under `## Post-fix
|
|
72
|
+
* Default fix_code variant: agent applies edits locally, commits when needed,
|
|
73
|
+
* then runs the pre-built apply command. Emitted under `## Post-fix actions`.
|
|
99
74
|
*/
|
|
100
75
|
interface FixRebaseAndPush {
|
|
101
76
|
threads: AgentThread[];
|
|
@@ -115,14 +90,16 @@ interface FixRebaseAndPush {
|
|
|
115
90
|
changesRequestedReviews: Review[];
|
|
116
91
|
/** Pre-built apply command. Run after committing and pushing. */
|
|
117
92
|
resolveCommand: ResolveCommand;
|
|
118
|
-
/** When present, run this command first (no SHA substitution needed)
|
|
93
|
+
/** When present, run this command first (no SHA substitution needed) for standalone thread resolves and comment minimization, independent of any push. */
|
|
119
94
|
resolveOnlyCommand?: ResolveCommand;
|
|
120
95
|
/** Ordered steps for the model to follow. */
|
|
121
96
|
instructions: string[];
|
|
122
|
-
/**
|
|
97
|
+
/** Reserved compatibility field. Always empty because Shepherd cannot verify workflow-cancellation authorization. */
|
|
123
98
|
inProgressRunIds: string[];
|
|
124
|
-
/**
|
|
99
|
+
/** Reserved compatibility field. Always empty because Shepherd never recommends workflow cancellation. */
|
|
125
100
|
protectedRuns: ProtectedRun[];
|
|
101
|
+
/** Requeue command emitted after merge-group remediation. */
|
|
102
|
+
requeue?: MergeCommandPlan;
|
|
126
103
|
/** First-look threads — previously hidden, surfaced for acknowledgment only. */
|
|
127
104
|
firstLookThreads: FirstLookThread[];
|
|
128
105
|
/** First-look comments — previously hidden, surfaced for acknowledgment only. */
|
|
@@ -138,19 +115,26 @@ interface IterateResultMarkReady extends IterateResultBase {
|
|
|
138
115
|
markedReady: boolean;
|
|
139
116
|
log: string;
|
|
140
117
|
}
|
|
118
|
+
export interface IterateResultMerge extends IterateResultBase {
|
|
119
|
+
action: "merge";
|
|
120
|
+
merge: MergeCommandPlan;
|
|
121
|
+
}
|
|
141
122
|
interface IterateResultEscalate extends IterateResultBase {
|
|
142
123
|
action: "escalate";
|
|
143
124
|
escalate: EscalateDetails;
|
|
144
125
|
}
|
|
145
|
-
export type IterateResult = IterateResultWait | IterateResultCancel | IterateResultFixCode | IterateResultMarkReady | IterateResultEscalate;
|
|
126
|
+
export type IterateResult = IterateResultWait | IterateResultCancel | IterateResultFixCode | IterateResultMarkReady | IterateResultMerge | IterateResultEscalate;
|
|
146
127
|
export interface IterateCommandOptions extends GlobalOptions {
|
|
147
128
|
readyDelaySeconds?: number;
|
|
148
129
|
noAutoMarkReady?: boolean;
|
|
130
|
+
/** Legacy no-op retained for API compatibility; workflow runs are never cancelled. */
|
|
149
131
|
noAutoCancelActionable?: boolean;
|
|
150
132
|
/** Override stall timeout seconds. Defaults to config.iterate.stallTimeoutMinutes * 60. */
|
|
151
133
|
stallTimeoutSeconds?: number;
|
|
152
|
-
/**
|
|
134
|
+
/** Legacy per-invocation no-op retained for API compatibility. */
|
|
153
135
|
neverCancelRuns?: string[];
|
|
154
136
|
persistSeen?: boolean;
|
|
137
|
+
/** Shepherd through readiness and emit the exact merge/queue command when ready. */
|
|
138
|
+
merge?: boolean;
|
|
155
139
|
}
|
|
156
140
|
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
interface ShellCommand {
|
|
2
|
+
argv: string[];
|
|
3
|
+
}
|
|
4
|
+
export interface MergeCommandPlan {
|
|
5
|
+
mode: "auto" | "queue";
|
|
6
|
+
command: ShellCommand;
|
|
7
|
+
/** Ordinary merge retry without `--auto`, used only when auto-merge is unavailable. */
|
|
8
|
+
fallbackCommand?: ShellCommand;
|
|
9
|
+
/** Direct enqueuePullRequest fallback for the known gh CLI queue limitation. */
|
|
10
|
+
queueApiFallbackCommand?: ShellCommand;
|
|
11
|
+
}
|
|
12
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { AutoMergeRequestStatus, MergeQueueEntryStatus, MergeQueueRemovalStatus } from "./merge-requirements.mts";
|
|
2
|
+
export interface MergeQueueReport {
|
|
3
|
+
enabled: boolean;
|
|
4
|
+
inQueue: boolean;
|
|
5
|
+
autoMergeRequest?: AutoMergeRequestStatus;
|
|
6
|
+
entry?: MergeQueueEntryStatus;
|
|
7
|
+
latestRemoval?: MergeQueueRemovalStatus;
|
|
8
|
+
checkCommitOid?: string;
|
|
9
|
+
/** GitHub reported more than the first 100 contexts on the queue commit. */
|
|
10
|
+
checksIncomplete?: true;
|
|
11
|
+
/** The current PR head is not a parent of the removed synthetic queue commit. */
|
|
12
|
+
headUpdatedAfterRemoval?: true;
|
|
13
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -17,6 +17,21 @@ export interface MergeQueueEntryStatus {
|
|
|
17
17
|
position: number;
|
|
18
18
|
state: string;
|
|
19
19
|
estimatedTimeToMerge: number | null;
|
|
20
|
+
headCommitOid?: string;
|
|
21
|
+
enqueuedAtUnix?: number;
|
|
22
|
+
enqueuer?: string;
|
|
23
|
+
}
|
|
24
|
+
export interface AutoMergeRequestStatus {
|
|
25
|
+
enabledAtUnix: number;
|
|
26
|
+
mergeMethod: string;
|
|
27
|
+
enabledBy?: string;
|
|
28
|
+
}
|
|
29
|
+
export interface MergeQueueRemovalStatus {
|
|
30
|
+
reason: string | null;
|
|
31
|
+
actor?: string;
|
|
32
|
+
createdAtUnix: number;
|
|
33
|
+
beforeCommitOid?: string;
|
|
34
|
+
beforeCommitParentOids?: string[];
|
|
20
35
|
}
|
|
21
36
|
export interface StackStatus {
|
|
22
37
|
number: number;
|
|
@@ -30,6 +45,8 @@ export interface BatchPrMergeFields {
|
|
|
30
45
|
isInMergeQueue?: boolean;
|
|
31
46
|
isMergeQueueEnabled?: boolean;
|
|
32
47
|
mergeQueueEntry?: MergeQueueEntryStatus | null;
|
|
48
|
+
autoMergeRequest?: AutoMergeRequestStatus | null;
|
|
49
|
+
latestMergeQueueRemoval?: MergeQueueRemovalStatus | null;
|
|
33
50
|
stack?: StackStatus | null;
|
|
34
51
|
}
|
|
35
52
|
/** Snapshot of "why can't I merge" requirements vs current PR state. */
|
package/bin/types/report.d.mts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import type { AuthorType, ReviewThread, PrComment, Review, MergeStatusResult, CheckConclusion, SuggestionBlock } from "./github.mts";
|
|
1
|
+
import type { AuthorType, ReviewThread, PrComment, Review, MergeStatusResult, ViewerAuthorization, CheckConclusion, SuggestionBlock } from "./github.mts";
|
|
2
2
|
import type { ClassifiedCheck, TriagedCheck } from "./check-classification.mts";
|
|
3
3
|
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
|
+
import type { MergeQueueReport } from "./merge-queue.mts";
|
|
6
7
|
export interface FirstLookThread extends ReviewThread {
|
|
7
8
|
firstLookStatus: "outdated" | "resolved" | "minimized";
|
|
8
9
|
autoResolved?: boolean;
|
|
@@ -20,7 +21,11 @@ export interface ShepherdReport {
|
|
|
20
21
|
pr: number;
|
|
21
22
|
/** GitHub node ID of the PR — used for mutations (e.g. markPullRequestReadyForReview). */
|
|
22
23
|
nodeId: string;
|
|
24
|
+
/** GitHub PR head OID from the same batch used to decide the action. */
|
|
25
|
+
headSha?: string;
|
|
23
26
|
repo: string;
|
|
27
|
+
/** Raw GitHub viewer fields used to decide which remote actions may be offered. */
|
|
28
|
+
viewerAuthorization?: ViewerAuthorization;
|
|
24
29
|
status: ShepherdStatus;
|
|
25
30
|
/** PR base branch from the GraphQL batch. */
|
|
26
31
|
baseBranch: string;
|
|
@@ -71,6 +76,7 @@ export interface ShepherdReport {
|
|
|
71
76
|
/** Branch protection rule for the PR's base branch. Null when no rule exists or the base ref is unavailable. */
|
|
72
77
|
branchProtection: import("./github.mts").BranchProtection | null;
|
|
73
78
|
activity?: PrActivitySummary;
|
|
79
|
+
mergeQueue?: MergeQueueReport;
|
|
74
80
|
}
|
|
75
81
|
export interface ResolveOptions {
|
|
76
82
|
resolveThreadIds?: string[];
|
|
@@ -83,6 +89,10 @@ export interface ResolveOptions {
|
|
|
83
89
|
}
|
|
84
90
|
export interface AgentThread {
|
|
85
91
|
id: string;
|
|
92
|
+
/** Raw GitHub capability; omitted only in legacy/incomplete snapshots. */
|
|
93
|
+
viewerCanReply?: boolean;
|
|
94
|
+
/** Raw GitHub capability; omitted only in legacy/incomplete snapshots. */
|
|
95
|
+
viewerCanResolve?: boolean;
|
|
86
96
|
reviewId?: string;
|
|
87
97
|
path: string | null;
|
|
88
98
|
line: number | null;
|
|
@@ -90,6 +100,7 @@ export interface AgentThread {
|
|
|
90
100
|
author: string;
|
|
91
101
|
authorType?: AuthorType;
|
|
92
102
|
authorAssociation?: import("./github.mts").CommentAuthorAssociation;
|
|
103
|
+
viewerDidAuthor?: true;
|
|
93
104
|
body: string;
|
|
94
105
|
url: string;
|
|
95
106
|
comments?: AgentThreadComment[];
|
|
@@ -99,6 +110,8 @@ export interface AgentThread {
|
|
|
99
110
|
/** Comment shape emitted to the iterate agent — stripped of always-false flags. */
|
|
100
111
|
export interface AgentComment {
|
|
101
112
|
id: string;
|
|
113
|
+
/** Raw GitHub capability; omitted only in legacy/incomplete snapshots. */
|
|
114
|
+
viewerCanMinimize?: boolean;
|
|
102
115
|
author: string;
|
|
103
116
|
authorType?: AuthorType;
|
|
104
117
|
authorAssociation?: import("./github.mts").CommentAuthorAssociation;
|
|
@@ -125,6 +138,8 @@ export interface AgentCheck {
|
|
|
125
138
|
logExcerpt?: string;
|
|
126
139
|
annotations?: CheckAnnotation[];
|
|
127
140
|
annotationOnly?: true;
|
|
141
|
+
scope?: "merge_group";
|
|
142
|
+
commitOid?: string;
|
|
128
143
|
}
|
|
129
144
|
/**
|
|
130
145
|
* A single CI check that is relevant to PR readiness — triggered by a PR event
|
|
@@ -149,9 +164,15 @@ export interface RelevantCheck {
|
|
|
149
164
|
logExcerpt?: string;
|
|
150
165
|
/** Marker-gated inline annotations from this check. */
|
|
151
166
|
annotations?: CheckAnnotation[];
|
|
167
|
+
scope?: "merge_group";
|
|
168
|
+
commitOid?: string;
|
|
152
169
|
}
|
|
153
170
|
export interface GlobalOptions {
|
|
154
171
|
prNumber?: number;
|
|
172
|
+
targetRepository?: {
|
|
173
|
+
owner: string;
|
|
174
|
+
name: string;
|
|
175
|
+
};
|
|
155
176
|
format: "text" | "json";
|
|
156
177
|
verbose?: boolean;
|
|
157
178
|
}
|
|
@@ -18,7 +18,7 @@ export interface BuildSuggestionPatchesResult {
|
|
|
18
18
|
repo: string;
|
|
19
19
|
/** Suggestion patches in caller-supplied application order. */
|
|
20
20
|
patches: SuggestionPatchResult[];
|
|
21
|
-
/** Steps for applying and committing every patch
|
|
21
|
+
/** Steps for applying and committing every patch; branch updates require separate authorization. */
|
|
22
22
|
postActionInstructions: string[];
|
|
23
23
|
}
|
|
24
24
|
/** Compatibility result for the singular suggestion-patch adapter. */
|
package/bin/types.d.mts
CHANGED
|
@@ -9,3 +9,6 @@ export * from "./types/report.mts";
|
|
|
9
9
|
export * from "./types/suggestion-patch.mts";
|
|
10
10
|
export * from "./types/iterate.mts";
|
|
11
11
|
export * from "./types/merge-requirements.mts";
|
|
12
|
+
export * from "./types/merge-action.mts";
|
|
13
|
+
export * from "./types/escalate.mts";
|
|
14
|
+
export * from "./types/merge-queue.mts";
|
package/bin/types.mjs
CHANGED
|
@@ -9,3 +9,6 @@ export * from "./types/report.mjs";
|
|
|
9
9
|
export * from "./types/suggestion-patch.mjs";
|
|
10
10
|
export * from "./types/iterate.mjs";
|
|
11
11
|
export * from "./types/merge-requirements.mjs";
|
|
12
|
+
export * from "./types/merge-action.mjs";
|
|
13
|
+
export * from "./types/escalate.mjs";
|
|
14
|
+
export * from "./types/merge-queue.mjs";
|
package/bin/util/markdown.d.mts
CHANGED
package/bin/util/markdown.mjs
CHANGED
|
@@ -5,3 +5,10 @@ export function joinSections(sections) {
|
|
|
5
5
|
.filter((s) => s !== "")
|
|
6
6
|
.join("\n\n");
|
|
7
7
|
}
|
|
8
|
+
/** Wrap arbitrary text in a CommonMark code span without colliding with embedded backticks. */
|
|
9
|
+
export function inlineCode(value) {
|
|
10
|
+
const longestRun = Math.max(0, ...Array.from(value.matchAll(/`+/g), (match) => match[0].length));
|
|
11
|
+
const delimiter = "`".repeat(longestRun + 1);
|
|
12
|
+
const padding = value.startsWith("`") || value.endsWith("`") ? " " : "";
|
|
13
|
+
return `${delimiter}${padding}${value}${padding}${delimiter}`;
|
|
14
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: mark-files-as-viewed
|
|
3
|
-
description: "
|
|
3
|
+
description: "Select changed pull-request files and report viewed-state authorization diagnostics with pr-shepherd (MCP or CLI)."
|
|
4
4
|
user-invocable: true
|
|
5
5
|
argument-hint: "[PR number or URL] [files|tests|--tests|--match REGEX]"
|
|
6
6
|
allowed-tools: ["MCP", "Bash", "Read", "Grep", "Glob"]
|
|
@@ -8,10 +8,10 @@ allowed-tools: ["MCP", "Bash", "Read", "Grep", "Glob"]
|
|
|
8
8
|
|
|
9
9
|
# mark-files-as-viewed
|
|
10
10
|
|
|
11
|
-
Thin dispatcher for marking PR
|
|
11
|
+
Thin dispatcher for selection-only file-view authorization diagnostics. GitHub exposes no exact viewer capability for marking a PR file viewed, so this operation never recommends or attempts that mutation. Use the MCP server when it is available; otherwise use the CLI.
|
|
12
12
|
|
|
13
13
|
## Arguments: $ARGUMENTS
|
|
14
14
|
|
|
15
15
|
1. Parse an optional PR number, repository-qualified `owner/repo#N`, or GitHub PR URL. Treat standalone `tests` as `--tests`; preserve explicit paths and `--match <regex>` selectors.
|
|
16
16
|
|
|
17
|
-
2. If the `apply` MCP tool is available, first obtain a repository-qualified reference: use a supplied GitHub PR URL or `owner/repo#N` unchanged; for a bare number, run `gh pr view <number> --json url --jq .url`; when omitted, run `gh pr view --json url --jq .url`. If that does not produce one qualified PR reference, stop and report that MCP cannot safely determine the PR. Otherwise call `apply` with that qualified reference and one `mark_files_viewed` operation, then print the full result. If MCP is unavailable
|
|
17
|
+
2. If the `apply` MCP tool is available, first obtain a repository-qualified reference: use a supplied GitHub PR URL or `owner/repo#N` unchanged; for a bare number, run `gh pr view <number> --json url --jq .url`; when omitted, run `gh pr view --json url --jq .url`. If that does not produce one qualified PR reference, stop and report that MCP cannot safely determine the PR. Otherwise call `apply` with that qualified reference and one `mark_files_viewed` operation, then print the full result. If MCP is unavailable, convert a supplied `owner/repo#N` to `https://github.com/owner/repo/pull/N` and otherwise pass the parsed PR unchanged to `pr-shepherd apply files` with the selectors, then print the full result. A qualified reference may target a fork or upstream repository; the current checkout remains the local git/config/rules context.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: pr-shepherd
|
|
3
3
|
description: 'Iterate a GitHub pull request with pr-shepherd (MCP or CLI). Use for requests like "use pr-shepherd", "iterate PR #123", or "run pr-shepherd until this PR is ready".'
|
|
4
4
|
user-invocable: true
|
|
5
|
-
argument-hint: "[PR number or URL]"
|
|
5
|
+
argument-hint: "[PR number or URL] [--merge]"
|
|
6
6
|
allowed-tools: ["MCP", "Bash", "Read", "Grep", "Glob", "Edit", "Write"]
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -12,9 +12,9 @@ Thin dispatcher for iterating a PR. Poll with the CLI; use MCP `iterate` only wh
|
|
|
12
12
|
|
|
13
13
|
## Arguments: $ARGUMENTS
|
|
14
14
|
|
|
15
|
-
1. Parse an optional PR number, repository-qualified `owner/repo#N`, or GitHub PR URL from `$ARGUMENTS`; otherwise let pr-shepherd infer the current branch PR.
|
|
15
|
+
1. Parse an optional PR number, repository-qualified `owner/repo#N`, or GitHub PR URL and an optional `--merge` flag from `$ARGUMENTS`; otherwise let pr-shepherd infer the current branch PR. Reject any remaining argument. Follow the target repository's local `AGENTS.md` and `CLAUDE.md` standards while making changes.
|
|
16
16
|
|
|
17
|
-
2.
|
|
17
|
+
2. For the CLI, convert supplied `owner/repo#N` to `https://github.com/owner/repo/pull/N`; otherwise pass the supplied URL or bare number unchanged, then run the poll command `pr-shepherd` with the optional PR argument and forward `--merge` when supplied. 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 obtain a repository-qualified reference: use a supplied GitHub PR URL or `owner/repo#N` unchanged; for a bare number, run `gh pr view <number> --json url --jq .url`; when omitted, run `gh pr view --json url --jq .url`. If that does not produce one qualified PR reference, stop and report that MCP cannot safely determine the PR. Otherwise call `iterate` with that qualified reference, plus `merge: true` when `--merge` was supplied, and print its full result.
|
|
18
18
|
|
|
19
19
|
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.
|
|
20
20
|
|
|
@@ -28,11 +28,11 @@ mechanics every tick. Apply the referenced playbook in full whenever a step poin
|
|
|
28
28
|
### Suggestion patches
|
|
29
29
|
|
|
30
30
|
- Run one plural `build-suggestion-patches` command with a repeated `--thread-id … --message … [--description …]` group for every marked thread in displayed order.
|
|
31
|
-
- The CLI only builds patches. Apply, stage, and commit the returned patches in order
|
|
31
|
+
- The CLI only builds patches. Apply, stage, and commit the returned patches in order. Push only when authorization has been established outside Shepherd; GitHub viewer fields cannot verify the local Git credential.
|
|
32
32
|
- The command builds from the fetched PR head and accepts a clean local descendant only when the complete ordered patch stream passes `git apply --check`.
|
|
33
33
|
- If the command refuses because a suggestion is unsafe or no longer applies, inspect the current source, the displayed replacement block, and reviewer intent before editing manually. Do not apply a stale numeric range blindly or retry unchanged input.
|
|
34
34
|
- A returned patch was checked against the then-current worktree. If it later fails, re-inspect the worktree because it changed after validation.
|
|
35
|
-
- Keep
|
|
35
|
+
- Keep the generated thread IDs and flag placement unchanged. Viewer-authored human feedback may intentionally appear in both reply and resolve flags; unmarked other-human feedback remains reply-only. Marker-ended other-human feedback is already acknowledged and has no generated mutation.
|
|
36
36
|
|
|
37
37
|
### CI failure triage
|
|
38
38
|
|
|
@@ -40,18 +40,20 @@ Match each failure's `[conclusion: …]` tag under `## Failing checks` to a rule
|
|
|
40
40
|
|
|
41
41
|
More specific rows win over the general "GitHub Actions failure" row — check conclusion first.
|
|
42
42
|
|
|
43
|
-
| Tag / kind | Do
|
|
44
|
-
| ------------------------------------------------------------------------ |
|
|
45
|
-
| GitHub Actions failure (has a run ID, not `CANCELLED`/`STARTUP_FAILURE`) | Read the included log excerpt if one is rendered. If missing or insufficient,
|
|
46
|
-
| Transient infrastructure failure |
|
|
47
|
-
| Real test or build failure | Apply a code fix — do not rerun.
|
|
48
|
-
| `[conclusion: CANCELLED]` | No log excerpt is rendered
|
|
49
|
-
| `[conclusion: STARTUP_FAILURE]` | No log excerpt is rendered
|
|
50
|
-
| `external` (no run ID, has a URL) |
|
|
43
|
+
| Tag / kind | Do |
|
|
44
|
+
| ------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
45
|
+
| GitHub Actions failure (has a run ID, not `CANCELLED`/`STARTUP_FAILURE`) | Read the included log excerpt if one is rendered. If it is missing or insufficient, hand off the displayed run ID/URL; Shepherd cannot verify authorization for another Actions read or mutation. |
|
|
46
|
+
| Transient infrastructure failure | Record the diagnosis. Shepherd does not recommend a rerun because GitHub exposes no exact viewer capability for that workflow-run action. |
|
|
47
|
+
| Real test or build failure | Apply a code fix — do not rerun. |
|
|
48
|
+
| `[conclusion: CANCELLED]` | No log excerpt is rendered. Hand off the displayed metadata; Shepherd cannot verify authorization for another Actions read or mutation. |
|
|
49
|
+
| `[conclusion: STARTUP_FAILURE]` | No log excerpt is rendered. Hand off the displayed metadata; Shepherd cannot verify authorization for another Actions read or mutation. |
|
|
50
|
+
| `external` (no run ID, has a URL) | Preserve the URL in the handoff. Shepherd does not recommend opening it because it cannot verify the current viewer's access to the external system. |
|
|
51
51
|
|
|
52
52
|
### Review-mutation mechanics
|
|
53
53
|
|
|
54
|
-
Applies to every `apply review:` / `resolve-only:` command the CLI prints. Covers only what stays safe if you run the printed command **unmodified** — `$HEAD_SHA`/`$DISMISS_MESSAGE` substitution
|
|
54
|
+
Applies to every `apply review:` / `resolve-only:` command the CLI prints. Covers only what stays safe if you run the printed command **unmodified** — `$HEAD_SHA`/`$DISMISS_MESSAGE` substitution remains a separate CLI-printed step because the command is unsafe by default without those placeholders.
|
|
55
|
+
|
|
56
|
+
The CLI only includes IDs whose per-object GitHub viewer capability authorizes the corresponding action, and `apply review` repeats that authorization check immediately before mutating.
|
|
55
57
|
|
|
56
58
|
- Run every generated `apply review:` / `resolve-only:` command even when no code change is warranted. The command records the agent's disposition of the included review items; skipping it leaves bot threads active and can eventually trigger `fix-thrash`.
|
|
57
59
|
- Never add first-look-only or check-annotation IDs to `--reply-thread-ids`, `--resolve-thread-ids`, `--dismiss-review-ids`, or `--minimize-comment-ids` — those flags are pre-populated by the CLI.
|
|
@@ -59,7 +61,7 @@ Applies to every `apply review:` / `resolve-only:` command the CLI prints. Cover
|
|
|
59
61
|
|
|
60
62
|
### Review-mutation routing
|
|
61
63
|
|
|
62
|
-
For threads under both `## Review threads` and `## Review threads to resolve`, evaluate every thread before running mutations. Keep bot and non-human IDs in `--resolve-thread-ids`, including when the feedback is advisory, already satisfied, or otherwise warrants no code change.
|
|
64
|
+
For threads under both `## Review threads` and `## Review threads to resolve`, evaluate every thread before running mutations. Keep bot and non-human IDs in `--resolve-thread-ids`, including when the feedback is advisory, already satisfied, or otherwise warrants no code change. Unmarked other-human inline-thread IDs use `--reply-thread-ids` only. When the original human inline comment has `viewerDidAuthor: true` and its latest comment is unmarked, keep that same ID in both `--reply-thread-ids` and `--resolve-thread-ids`: the reply runs before the resolve. When the latest comment begins `<!-- pr-shepherd -->`, it is an established Shepherd reply—not merely a same-account comment. A marker-ended viewer-authored thread may be resolve-only for retry; a marker-ended other-human thread is already acknowledged and has no generated mutation. Do not add an unmarked human ID to `--resolve-thread-ids` without its paired generated reply, and do not move IDs between flags.
|
|
63
65
|
|
|
64
66
|
### Shepherd Journal
|
|
65
67
|
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import type { ShepherdReport } from "../../types.mts";
|
|
2
|
-
import type { ProtectedRun } from "../../types/protected-run.mts";
|
|
3
|
-
type FailingCheck = ShepherdReport["checks"]["failing"][number];
|
|
4
|
-
type InProgressCheck = ShepherdReport["checks"]["inProgress"][number];
|
|
5
|
-
type CancellableCheck = FailingCheck | InProgressCheck;
|
|
6
|
-
interface RunProtection {
|
|
7
|
-
protectedRunIds: Set<string>;
|
|
8
|
-
protectedRuns: ProtectedRun[];
|
|
9
|
-
}
|
|
10
|
-
interface BuildRunIdOptions {
|
|
11
|
-
protectedRunIds?: Set<string>;
|
|
12
|
-
}
|
|
13
|
-
export declare function buildAutoCancelRunIdsWithOptions(report: ShepherdReport, opts?: BuildRunIdOptions): string[];
|
|
14
|
-
interface BuildInProgressRunIdOptions {
|
|
15
|
-
suppressProtectedFreshReruns?: boolean;
|
|
16
|
-
protectedRunIds?: Set<string>;
|
|
17
|
-
}
|
|
18
|
-
export declare function buildInProgressRunIds(report: ShepherdReport, cancelledSet: Set<string>, opts?: BuildInProgressRunIdOptions): string[];
|
|
19
|
-
export declare function buildRunProtection(checks: CancellableCheck[], patterns?: string[]): RunProtection;
|
|
20
|
-
export {};
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
import picomatch from "picomatch";
|
|
2
|
-
function matchesRerunCheck(failure, check) {
|
|
3
|
-
if (failure.runId !== null && check.runId !== null) {
|
|
4
|
-
return failure.runId === check.runId && failure.name === check.name;
|
|
5
|
-
}
|
|
6
|
-
return failure.runId === null && check.runId === null && failure.name === check.name;
|
|
7
|
-
}
|
|
8
|
-
function isProtectedByFreshRerun(failure, check) {
|
|
9
|
-
const attemptStartedAt = check.startedAtUnix ?? check.updatedAtUnix ?? check.createdAtUnix;
|
|
10
|
-
return (attemptStartedAt !== undefined &&
|
|
11
|
-
matchesRerunCheck(failure, check) &&
|
|
12
|
-
failure.completedAtUnix !== undefined &&
|
|
13
|
-
attemptStartedAt >= failure.completedAtUnix &&
|
|
14
|
-
(failure.startedAtUnix === undefined || failure.startedAtUnix < attemptStartedAt));
|
|
15
|
-
}
|
|
16
|
-
function hasProtectedFreshRerun(failure, checks) {
|
|
17
|
-
return checks.some((check) => isProtectedByFreshRerun(failure, check));
|
|
18
|
-
}
|
|
19
|
-
function isProtectedFreshRerun(check, failures) {
|
|
20
|
-
const matchingFailures = failures.filter((failure) => matchesRerunCheck(failure, check));
|
|
21
|
-
return (matchingFailures.length > 0 &&
|
|
22
|
-
matchingFailures.every((failure) => isProtectedByFreshRerun(failure, check)));
|
|
23
|
-
}
|
|
24
|
-
function protectedFreshRerunIds(report) {
|
|
25
|
-
return new Set(report.checks.inProgress
|
|
26
|
-
.filter((check) => isProtectedFreshRerun(check, report.checks.failing))
|
|
27
|
-
.map((check) => check.runId)
|
|
28
|
-
.filter((id) => id !== null));
|
|
29
|
-
}
|
|
30
|
-
export function buildAutoCancelRunIdsWithOptions(report, opts = {}) {
|
|
31
|
-
return [
|
|
32
|
-
...new Set(report.checks.failing
|
|
33
|
-
.filter((check) => !hasProtectedFreshRerun(check, report.checks.inProgress))
|
|
34
|
-
.map((check) => check.runId)
|
|
35
|
-
.filter((id) => id !== null && !(opts.protectedRunIds?.has(id) ?? false))),
|
|
36
|
-
];
|
|
37
|
-
}
|
|
38
|
-
export function buildInProgressRunIds(report, cancelledSet, opts = {}) {
|
|
39
|
-
const protectedRunIds = opts.suppressProtectedFreshReruns === false ? new Set() : protectedFreshRerunIds(report);
|
|
40
|
-
return [
|
|
41
|
-
...new Set(report.checks.inProgress
|
|
42
|
-
.map((check) => check.runId)
|
|
43
|
-
.filter((id) => id !== null &&
|
|
44
|
-
!cancelledSet.has(id) &&
|
|
45
|
-
!protectedRunIds.has(id) &&
|
|
46
|
-
!(opts.protectedRunIds?.has(id) ?? false))),
|
|
47
|
-
];
|
|
48
|
-
}
|
|
49
|
-
export function buildRunProtection(checks, patterns = []) {
|
|
50
|
-
if (patterns.length === 0)
|
|
51
|
-
return { protectedRunIds: new Set(), protectedRuns: [] };
|
|
52
|
-
const matchers = patterns.map((pattern) => ({
|
|
53
|
-
pattern,
|
|
54
|
-
isMatch: picomatch(pattern, { nocase: true }),
|
|
55
|
-
}));
|
|
56
|
-
const byRunId = new Map();
|
|
57
|
-
for (const check of checks) {
|
|
58
|
-
if (check.runId === null)
|
|
59
|
-
continue;
|
|
60
|
-
const match = findProtectionMatch(check, matchers);
|
|
61
|
-
if (match === null)
|
|
62
|
-
continue;
|
|
63
|
-
addProtectedRun(byRunId, check.runId, check, match);
|
|
64
|
-
}
|
|
65
|
-
const protectedRuns = [...byRunId.values()];
|
|
66
|
-
return {
|
|
67
|
-
protectedRunIds: new Set(protectedRuns.map((run) => run.runId)),
|
|
68
|
-
protectedRuns,
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
function addProtectedRun(byRunId, runId, check, matchedPattern) {
|
|
72
|
-
const existing = byRunId.get(runId);
|
|
73
|
-
if (existing) {
|
|
74
|
-
updateProtectedRun(existing, check);
|
|
75
|
-
return;
|
|
76
|
-
}
|
|
77
|
-
byRunId.set(runId, createProtectedRun(runId, check, matchedPattern));
|
|
78
|
-
}
|
|
79
|
-
function updateProtectedRun(run, check) {
|
|
80
|
-
if (!run.checkNames.includes(check.name))
|
|
81
|
-
run.checkNames.push(check.name);
|
|
82
|
-
if (run.workflowName === undefined && check.workflowName !== undefined) {
|
|
83
|
-
run.workflowName = check.workflowName;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
function createProtectedRun(runId, check, matchedPattern) {
|
|
87
|
-
return {
|
|
88
|
-
runId,
|
|
89
|
-
matchedPattern,
|
|
90
|
-
checkNames: [check.name],
|
|
91
|
-
...(check.workflowName !== undefined && { workflowName: check.workflowName }),
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
function findProtectionMatch(check, matchers) {
|
|
95
|
-
const candidates = [
|
|
96
|
-
check.workflowName,
|
|
97
|
-
"jobName" in check ? check.jobName : undefined,
|
|
98
|
-
check.name,
|
|
99
|
-
].filter((value) => value !== undefined && value.trim() !== "");
|
|
100
|
-
for (const matcher of matchers) {
|
|
101
|
-
if (candidates.some((candidate) => matcher.isMatch(candidate)))
|
|
102
|
-
return matcher.pattern;
|
|
103
|
-
}
|
|
104
|
-
return null;
|
|
105
|
-
}
|