pr-shepherd 0.60.1 → 1.1.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.
Files changed (245) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/README.md +7 -5
  3. package/bin/api.d.mts +35 -24
  4. package/bin/api.mjs +68 -48
  5. package/bin/checks/classify.d.mts +1 -1
  6. package/bin/checks/classify.mjs +4 -4
  7. package/bin/checks/log-excerpt.mjs +1 -1
  8. package/bin/cli/arg-flags.mjs +0 -3
  9. package/bin/cli/clean-handler.d.mts +1 -1
  10. package/bin/cli/clean-handler.mjs +5 -15
  11. package/bin/cli/default-poll.d.mts +2 -0
  12. package/bin/cli/default-poll.mjs +9 -6
  13. package/bin/cli/formatters.d.mts +2 -3
  14. package/bin/cli/formatters.mjs +0 -26
  15. package/bin/cli/handlers.d.mts +3 -3
  16. package/bin/cli/handlers.mjs +45 -35
  17. package/bin/cli/help-command-pages.d.mts +13 -158
  18. package/bin/cli/help-command-pages.mjs +12 -157
  19. package/bin/cli/help-iterate-poll-pages.d.mts +4 -3
  20. package/bin/cli/help-iterate-poll-pages.mjs +76 -36
  21. package/bin/cli/help-log-file-page.d.mts +1 -1
  22. package/bin/cli/help-log-file-page.mjs +3 -5
  23. package/bin/cli/help-top-page.d.mts +1 -1
  24. package/bin/cli/help-top-page.mjs +19 -20
  25. package/bin/cli/help.d.mts +14 -159
  26. package/bin/cli/iterate-checks-formatter.mjs +1 -1
  27. package/bin/cli/iterate-flags.d.mts +2 -4
  28. package/bin/cli/iterate-flags.mjs +4 -20
  29. package/bin/cli/iterate-formatter.d.mts +1 -1
  30. package/bin/cli/iterate-formatter.mjs +6 -6
  31. package/bin/cli/iterate-instructions.d.mts +1 -1
  32. package/bin/cli/iterate-instructions.mjs +5 -6
  33. package/bin/cli/iterate-lean.mjs +32 -40
  34. package/bin/cli/iterate-verbose.mjs +1 -1
  35. package/bin/cli/journal-formatter.mjs +0 -3
  36. package/bin/cli/journal-handler.d.mts +1 -1
  37. package/bin/cli/journal-handler.mjs +2 -1
  38. package/bin/cli/mutate-formatter.mjs +0 -9
  39. package/bin/cli/next-check-format.d.mts +0 -4
  40. package/bin/cli/next-check-format.mjs +0 -4
  41. package/bin/cli/poll-handler.d.mts +3 -0
  42. package/bin/cli/poll-handler.mjs +88 -47
  43. package/bin/cli/poll-summary-emitter.mjs +2 -2
  44. package/bin/cli/poll-summary-formatter.mjs +5 -2
  45. package/bin/cli/poll-targets.d.mts +2 -2
  46. package/bin/cli/poll-targets.mjs +15 -35
  47. package/bin/cli/removed-flags.d.mts +3 -0
  48. package/bin/cli/removed-flags.mjs +24 -0
  49. package/bin/cli/rule-auto-resolve-lines.d.mts +3 -0
  50. package/bin/cli/rule-auto-resolve-lines.mjs +12 -0
  51. package/bin/cli/runner.d.mts +1 -1
  52. package/bin/cli/runner.mjs +2 -2
  53. package/bin/cli/stack-layer-view.d.mts +2 -1
  54. package/bin/cli/stack-overview.d.mts +0 -1
  55. package/bin/cli/stack-overview.mjs +4 -2
  56. package/bin/cli/{fix-formatter-extra.d.mts → triage-formatter-extra.d.mts} +1 -2
  57. package/bin/cli/{fix-formatter-extra.mjs → triage-formatter-extra.mjs} +0 -6
  58. package/bin/cli/triage-formatter.d.mts +4 -0
  59. package/bin/cli/{fix-formatter.mjs → triage-formatter.mjs} +31 -42
  60. package/bin/cli/unknown-flags.d.mts +6 -0
  61. package/bin/cli/unknown-flags.mjs +29 -0
  62. package/bin/cli-parser.mjs +41 -62
  63. package/bin/commands/check-activity.d.mts +8 -0
  64. package/bin/commands/check-activity.mjs +26 -0
  65. package/bin/commands/check-annotations.d.mts +1 -1
  66. package/bin/commands/check-annotations.mjs +3 -2
  67. package/bin/commands/check-review-budget.d.mts +1 -1
  68. package/bin/commands/check-review-budget.mjs +1 -1
  69. package/bin/commands/check-wait-detectors.d.mts +1 -1
  70. package/bin/commands/check-wait-detectors.mjs +12 -1
  71. package/bin/commands/check.d.mts +1 -1
  72. package/bin/commands/check.mjs +13 -8
  73. package/bin/commands/commit-suggestion-instruction.d.mts +2 -2
  74. package/bin/commands/commit-suggestion-instruction.mjs +3 -3
  75. package/bin/commands/iterate/api-usage.mjs +8 -8
  76. package/bin/commands/iterate/check-instructions.d.mts +4 -4
  77. package/bin/commands/iterate/check-instructions.mjs +8 -8
  78. package/bin/commands/iterate/classify.mjs +2 -2
  79. package/bin/commands/iterate/escalate.mjs +6 -6
  80. package/bin/commands/iterate/index.mjs +20 -23
  81. package/bin/commands/iterate/merge-plan.mjs +3 -3
  82. package/bin/commands/iterate/merge-state.mjs +4 -7
  83. package/bin/commands/iterate/native-stack-rebase.mjs +1 -1
  84. package/bin/commands/iterate/render.d.mts +1 -1
  85. package/bin/commands/iterate/render.mjs +2 -2
  86. package/bin/commands/iterate/stall.mjs +11 -9
  87. package/bin/commands/iterate/{fix-loop-instruction.mjs → triage-loop-instruction.mjs} +7 -3
  88. package/bin/commands/iterate/{fix-code.d.mts → triage.d.mts} +2 -2
  89. package/bin/commands/iterate/{fix-code.mjs → triage.mjs} +14 -23
  90. package/bin/commands/iterate/unreported-required.mjs +2 -5
  91. package/bin/commands/journal/index.d.mts +1 -3
  92. package/bin/commands/journal/index.mjs +1 -1
  93. package/bin/commands/mark-files-as-viewed.d.mts +1 -3
  94. package/bin/commands/mark-files-as-viewed.mjs +1 -1
  95. package/bin/commands/next-check.d.mts +2 -2
  96. package/bin/commands/next-check.mjs +4 -2
  97. package/bin/commands/poll-progress.mjs +1 -1
  98. package/bin/commands/poll-summary-explicit-instructions.mjs +1 -1
  99. package/bin/commands/poll-summary-instructions.mjs +7 -7
  100. package/bin/commands/poll-summary-signature.d.mts +6 -0
  101. package/bin/commands/poll-summary-signature.mjs +19 -2
  102. package/bin/commands/poll-summary.mjs +11 -4
  103. package/bin/commands/poll.d.mts +1 -1
  104. package/bin/commands/poll.mjs +4 -4
  105. package/bin/commands/ready-delay.d.mts +1 -0
  106. package/bin/commands/ready-delay.mjs +8 -3
  107. package/bin/commands/resolve-mutate.d.mts +1 -1
  108. package/bin/commands/resolve-mutate.mjs +1 -1
  109. package/bin/commands/rest-stack-merge-readiness.mjs +1 -1
  110. package/bin/commands/rule-auto-resolve-format.d.mts +7 -0
  111. package/bin/commands/rule-auto-resolve-format.mjs +11 -4
  112. package/bin/commands/rule-auto-resolve.d.mts +14 -2
  113. package/bin/commands/single-tick.d.mts +5 -0
  114. package/bin/commands/single-tick.mjs +7 -0
  115. package/bin/commands/stack-drain.mjs +1 -1
  116. package/bin/commands/stack-merge-flag.mjs +1 -1
  117. package/bin/commands/stack-stall.d.mts +2 -2
  118. package/bin/commands/stack-stall.mjs +2 -2
  119. package/bin/commands/stack-work.d.mts +2 -2
  120. package/bin/commands/stack-work.mjs +2 -2
  121. package/bin/commands/suggestion-patch-item.d.mts +0 -1
  122. package/bin/commands/suggestion-patch-item.mjs +0 -12
  123. package/bin/commands/suggestion-patches.d.mts +2 -2
  124. package/bin/commands/suggestion-patches.mjs +1 -1
  125. package/bin/commands/tick-instructions.d.mts +9 -0
  126. package/bin/commands/tick-instructions.mjs +23 -0
  127. package/bin/commands/tick.d.mts +15 -0
  128. package/bin/commands/{event-mode.mjs → tick.mjs} +39 -55
  129. package/bin/comments/minimize-policy.mjs +1 -3
  130. package/bin/comments/resolve.d.mts +0 -23
  131. package/bin/comments/resolve.mjs +0 -4
  132. package/bin/comments/review-output-budget.d.mts +1 -1
  133. package/bin/comments/review-output-budget.mjs +1 -1
  134. package/bin/comments/sha-poll.mjs +3 -1
  135. package/bin/comments/thread-visibility.d.mts +6 -0
  136. package/bin/comments/thread-visibility.mjs +30 -15
  137. package/bin/config/default-bot-usernames.d.mts +2 -0
  138. package/bin/config/default-bot-usernames.mjs +15 -0
  139. package/bin/config/load.d.mts +4 -138
  140. package/bin/config/load.mjs +88 -443
  141. package/bin/config/merge-command-args.mjs +2 -2
  142. package/bin/config/merge-method.d.mts +1 -2
  143. package/bin/config/merge-method.mjs +1 -8
  144. package/bin/config/renames.d.mts +8 -0
  145. package/bin/config/renames.mjs +87 -0
  146. package/bin/config/resolve.d.mts +31 -0
  147. package/bin/config/resolve.mjs +89 -0
  148. package/bin/config/schema.d.mts +161 -0
  149. package/bin/config/schema.mjs +168 -0
  150. package/bin/exit-codes.d.mts +1 -1
  151. package/bin/exit-codes.mjs +3 -3
  152. package/bin/github/batch-parse-suites.d.mts +14 -0
  153. package/bin/github/batch-parse-suites.mjs +4 -1
  154. package/bin/github/batch-parser-helpers.mjs +3 -0
  155. package/bin/github/check-annotation-cache.d.mts +5 -0
  156. package/bin/github/check-annotation-cache.mjs +6 -3
  157. package/bin/github/fingerprint.mjs +4 -0
  158. package/bin/github/poll-summary-annotation-probe.d.mts +5 -0
  159. package/bin/github/poll-summary-annotation-probe.mjs +17 -3
  160. package/bin/github/poll-summary-annotations.d.mts +14 -0
  161. package/bin/github/poll-summary-annotations.mjs +75 -0
  162. package/bin/github/poll-summary-blocking-reviewer.d.mts +2 -0
  163. package/bin/github/poll-summary-blocking-reviewer.mjs +9 -0
  164. package/bin/github/poll-summary-check-blockers.mjs +1 -1
  165. package/bin/github/poll-summary-checks.d.mts +1 -0
  166. package/bin/github/poll-summary-checks.mjs +20 -2
  167. package/bin/github/poll-summary-command.mjs +8 -6
  168. package/bin/github/poll-summary-fingerprint.d.mts +7 -0
  169. package/bin/github/poll-summary-fingerprint.mjs +7 -0
  170. package/bin/github/poll-summary-projector.d.mts +3 -1
  171. package/bin/github/poll-summary-projector.mjs +14 -25
  172. package/bin/github/poll-summary-queue-removal.d.mts +2 -0
  173. package/bin/github/poll-summary-queue-removal.mjs +11 -0
  174. package/bin/github/poll-summary-readiness.mjs +1 -0
  175. package/bin/github/poll-summary-review-parity.d.mts +24 -0
  176. package/bin/github/poll-summary-review-parity.mjs +82 -0
  177. package/bin/github/poll-summary-review.d.mts +11 -2
  178. package/bin/github/poll-summary-review.mjs +88 -60
  179. package/bin/github/poll-summary-route.mjs +9 -9
  180. package/bin/github/poll-summary-row-error.d.mts +16 -0
  181. package/bin/github/poll-summary-row-error.mjs +74 -0
  182. package/bin/github/poll-summary-rule-auto-resolve.d.mts +32 -0
  183. package/bin/github/poll-summary-rule-auto-resolve.mjs +119 -0
  184. package/bin/github/poll-summary-rule-handoff.d.mts +7 -0
  185. package/bin/github/poll-summary-rule-handoff.mjs +20 -0
  186. package/bin/github/poll-summary-rule-items.d.mts +20 -0
  187. package/bin/github/poll-summary-rule-items.mjs +28 -0
  188. package/bin/github/poll-summary-unreported.mjs +1 -1
  189. package/bin/github/poll-summary.mjs +16 -8
  190. package/bin/github/queries.d.mts +1 -1
  191. package/bin/github/queries.mjs +1 -1
  192. package/bin/github/rest-reader-core.mjs +13 -2
  193. package/bin/github/rest-summary-read.mjs +12 -1
  194. package/bin/mcp/server.mjs +48 -54
  195. package/bin/merge-status/derive.mjs +1 -1
  196. package/bin/state/durable-state.d.mts +1 -3
  197. package/bin/state/durable-state.mjs +2 -8
  198. package/bin/state/fix-attempts.d.mts +2 -2
  199. package/bin/state/fix-attempts.mjs +1 -1
  200. package/bin/state/merge-request.mjs +1 -1
  201. package/bin/state/pr-fingerprint.mjs +4 -11
  202. package/bin/state/seen-comments.d.mts +4 -5
  203. package/bin/state/seen-comments.mjs +8 -14
  204. package/bin/state/stack-stall.d.mts +1 -1
  205. package/bin/state/stack-stall.mjs +1 -1
  206. package/bin/state/stall-state-store.d.mts +1 -1
  207. package/bin/state/stall-state-store.mjs +1 -1
  208. package/bin/types/escalate.d.mts +2 -2
  209. package/bin/types/github.d.mts +2 -0
  210. package/bin/types/iterate.d.mts +12 -26
  211. package/bin/types/merge-queue.d.mts +2 -2
  212. package/bin/types/next-check.d.mts +1 -1
  213. package/bin/types/poll-summary.d.mts +26 -6
  214. package/bin/types/report.d.mts +2 -2
  215. package/bin/types/suggestion-patch.d.mts +1 -8
  216. package/package.json +3 -2
  217. package/plugins/pr-shepherd/.claude-plugin/plugin.json +1 -1
  218. package/plugins/pr-shepherd/.codex-plugin/plugin.json +1 -1
  219. package/plugins/pr-shepherd/.codex.mcp.json +1 -1
  220. package/plugins/pr-shepherd/.mcp.json +1 -1
  221. package/plugins/pr-shepherd/skills/pr-shepherd/SKILL.md +6 -6
  222. package/plugins/pr-shepherd/skills/pr-shepherd/references/ci-failure-triage.md +1 -1
  223. package/plugins/pr-shepherd/skills/pr-shepherd/references/{cloud-event-loop.md → event-loop.md} +5 -5
  224. package/plugins/pr-shepherd/skills/pr-shepherd/references/mcp-fallback.md +3 -3
  225. package/plugins/pr-shepherd/skills/pr-shepherd/references/merge-queue-ejection.md +1 -1
  226. package/plugins/pr-shepherd/skills/pr-shepherd/references/suggestion-patches.md +1 -1
  227. package/plugins/pr-shepherd/skills/pr-shepherd/references/{fix-code-loop.md → triage-loop.md} +3 -3
  228. package/plugins/pr-shepherd/skills/reduce-pr-noise/SKILL.md +1 -1
  229. package/plugins/pr-shepherd/skills/reduce-pr-noise/references/classifiers.md +2 -2
  230. package/plugins/pr-shepherd/skills/reduce-pr-noise/references/settings.md +11 -11
  231. package/pr-shepherd.schema.json +361 -0
  232. package/bin/cli/event-state-scope.d.mts +0 -19
  233. package/bin/cli/event-state-scope.mjs +0 -60
  234. package/bin/cli/fix-formatter.d.mts +0 -4
  235. package/bin/commands/commit-suggestion.d.mts +0 -8
  236. package/bin/commands/commit-suggestion.mjs +0 -26
  237. package/bin/commands/event-instructions.d.mts +0 -11
  238. package/bin/commands/event-instructions.mjs +0 -27
  239. package/bin/commands/event-mode.d.mts +0 -14
  240. package/bin/commands/poll-mode.d.mts +0 -8
  241. package/bin/commands/poll-mode.mjs +0 -14
  242. package/bin/config.json +0 -68
  243. package/bin/types/protected-run.d.mts +0 -6
  244. package/bin/types/protected-run.mjs +0 -1
  245. /package/bin/commands/iterate/{fix-loop-instruction.d.mts → triage-loop-instruction.d.mts} +0 -0
@@ -9,11 +9,9 @@ export function shouldMinimizeAuthor(authorType, policy, author, botUsernames =
9
9
  return authorType !== "User" || isConfiguredBot;
10
10
  case "bots":
11
11
  return isConfiguredBot;
12
- case "users":
13
- return false;
14
12
  case "none":
15
13
  return false;
16
14
  default:
17
- throw new Error(`Invalid minimizeComments policy: ${String(policy)}`);
15
+ throw new Error(`Invalid iterate.minimize-comments policy: ${String(policy)}`);
18
16
  }
19
17
  }
@@ -8,24 +8,6 @@ export interface ResolveResult {
8
8
  minimizedComments: string[];
9
9
  dismissedReviews: string[];
10
10
  errors: string[];
11
- /** @deprecated Direct apply forwards every supplied dismissal ID to GitHub. */
12
- skippedDismissals?: string[];
13
- /** @deprecated Direct apply no longer applies author policy. */
14
- skippedHumanResolves?: string[];
15
- /** @deprecated Direct apply no longer applies author policy. */
16
- skippedHumanMinimizes?: string[];
17
- /** @deprecated Direct apply no longer applies author policy. */
18
- skippedHumanDismissals?: string[];
19
- /** @deprecated Direct apply forwards every supplied reply ID to GitHub. */
20
- skippedNonHumanReplies?: string[];
21
- /** @deprecated Direct apply requests now rely on GitHub's mutation response. */
22
- skippedUnauthorizedReplies?: string[];
23
- /** @deprecated Direct apply requests now rely on GitHub's mutation response. */
24
- skippedUnauthorizedResolves?: string[];
25
- /** @deprecated Direct apply requests now rely on GitHub's mutation response. */
26
- skippedUnauthorizedMinimizes?: string[];
27
- /** @deprecated Direct apply requests now rely on GitHub's mutation response. */
28
- skippedUnauthorizedDismissals?: string[];
29
11
  rateLimit?: ResolveRateLimitStop;
30
12
  sessionRefusal?: string;
31
13
  instructions?: string[];
@@ -38,11 +20,6 @@ export declare function applyResolveOptions(pr: number, repo: RepoInfo, opts: Re
38
20
  headSha?: string;
39
21
  evidence: Map<string, ReplyEvidence>;
40
22
  }): Promise<ResolveResult>;
41
- /** @deprecated Compatibility alias; use `autoResolveThreads`. */
42
- export declare function autoResolveOutdated(threadIds: string[]): Promise<{
43
- resolved: string[];
44
- errors: string[];
45
- }>;
46
23
  export declare function autoResolveThreads(threadIds: string[]): Promise<{
47
24
  resolved: string[];
48
25
  errors: string[];
@@ -88,10 +88,6 @@ export async function applyResolveOptions(pr, repo, opts, preflight) {
88
88
  ];
89
89
  return result;
90
90
  }
91
- /** @deprecated Compatibility alias; use `autoResolveThreads`. */
92
- export async function autoResolveOutdated(threadIds) {
93
- return autoResolveThreads(threadIds);
94
- }
95
91
  export async function autoResolveThreads(threadIds) {
96
92
  if (threadIds.length === 0)
97
93
  return { resolved: [], errors: [] };
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Per-tick output budget for review items (see `iterate.reviewOutputMaxChars`).
2
+ * Per-tick output budget for review items (see `iterate.review-output-max-chars`).
3
3
  *
4
4
  * Fetching is complete; only the rendered volume is capped. When the bodies of every surfaced
5
5
  * review item fit the budget, nothing changes. Otherwise items are taken in a fixed priority
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Per-tick output budget for review items (see `iterate.reviewOutputMaxChars`).
2
+ * Per-tick output budget for review items (see `iterate.review-output-max-chars`).
3
3
  *
4
4
  * Fetching is complete; only the rendered volume is capped. When the bodies of every surfaced
5
5
  * review item fit the budget, nothing changes. Otherwise items are taken in a fixed priority
@@ -2,7 +2,9 @@ import { getPrHeadSha } from "../github/client.mjs";
2
2
  import { loadConfig } from "../config/load.mjs";
3
3
  import { sleep } from "../util/sleep.mjs";
4
4
  export async function waitForSha(pr, repo, expectedSha) {
5
- const { intervalMs: SHA_POLL_INTERVAL_MS, maxAttempts: SHA_POLL_MAX_ATTEMPTS } = loadConfig().resolve.shaPoll;
5
+ const apply = loadConfig().apply;
6
+ const SHA_POLL_INTERVAL_MS = apply["sha-poll-interval-seconds"] * 1000;
7
+ const SHA_POLL_MAX_ATTEMPTS = apply["sha-poll-max-attempts"];
6
8
  let lastSha;
7
9
  for (let attempt = 0; attempt < SHA_POLL_MAX_ATTEMPTS; attempt++) {
8
10
  try {
@@ -8,5 +8,11 @@ interface ThreadVisibility {
8
8
  firstLookThreads: FirstLookThread[];
9
9
  toMarkSeen: ReviewThread[];
10
10
  }
11
+ /**
12
+ * Whether an unresolved thread with a known outdated state keeps returning every tick once seen,
13
+ * given an authorized mutation. The compact summary calls this so its count cannot drift from
14
+ * `classifyThreadVisibility`.
15
+ */
16
+ export declare function unresolvedThreadRepeats(thread: ReviewThread, ended: boolean, botUsernames: NormalizedBotUsernames, policy: ResolveOtherHumanThreads): boolean;
11
17
  export declare function classifyThreadVisibility(threads: ReviewThread[], seenMap: Map<string, SeenMarker>, botUsernames?: NormalizedBotUsernames, repeatableThreadIds?: ReadonlySet<string>, resolveOtherHumanThreads?: ResolveOtherHumanThreads): ThreadVisibility;
12
18
  export {};
@@ -3,6 +3,9 @@ import { threadTranscriptBody } from "../threads/transcript.mjs";
3
3
  import { isConfiguredBotAuthor, isHumanAuthor, isViewerAuthoredHuman, } from "./authors.mjs";
4
4
  import { threadEndedByShepherd } from "./marker.mjs";
5
5
  import { shouldResolveOtherHumanThread } from "./thread-resolve-policy.mjs";
6
+ function isOrdinaryHuman(thread, botUsernames) {
7
+ return isHumanAuthor(thread) && !isConfiguredBotAuthor(thread, botUsernames);
8
+ }
6
9
  function withEdited(thread, edited) {
7
10
  return edited ? { ...thread, edited: true } : thread;
8
11
  }
@@ -20,9 +23,33 @@ function classifyFirstLookThread(thread, seenMap, firstLookStatus) {
20
23
  return null;
21
24
  return { ...visible, firstLookStatus };
22
25
  }
26
+ /** An unresolved, current thread whose author class makes it repeat while a mutation is authorized. */
27
+ function repeatsAsActive(thread, ended, botUsernames, policy) {
28
+ if (thread.isOutdated !== false || thread.isMinimized === true || ended)
29
+ return false;
30
+ return (isConfiguredBotAuthor(thread, botUsernames) ||
31
+ isViewerAuthoredHuman(thread, botUsernames) ||
32
+ (isOrdinaryHuman(thread, botUsernames) && policy === "always"));
33
+ }
34
+ /** An unresolved thread that is resolution-only work: outdated, minimized or ended by Shepherd. */
35
+ function isResolutionOnlyCandidate(thread, ended, botUsernames, policy) {
36
+ if (!ended)
37
+ return thread.isOutdated === true || thread.isMinimized === true;
38
+ if (!isOrdinaryHuman(thread, botUsernames))
39
+ return true;
40
+ return (isViewerAuthoredHuman(thread, botUsernames) || shouldResolveOtherHumanThread(thread, policy));
41
+ }
42
+ /**
43
+ * Whether an unresolved thread with a known outdated state keeps returning every tick once seen,
44
+ * given an authorized mutation. The compact summary calls this so its count cannot drift from
45
+ * `classifyThreadVisibility`.
46
+ */
47
+ export function unresolvedThreadRepeats(thread, ended, botUsernames, policy) {
48
+ return (repeatsAsActive(thread, ended, botUsernames, policy) ||
49
+ isResolutionOnlyCandidate(thread, ended, botUsernames, policy));
50
+ }
23
51
  export function classifyThreadVisibility(threads, seenMap, botUsernames = new Set(), repeatableThreadIds, resolveOtherHumanThreads = "none") {
24
52
  const shouldRepeat = (thread) => repeatableThreadIds?.has(thread.id) ?? true;
25
- const isOrdinaryHuman = (thread) => isHumanAuthor(thread) && !isConfiguredBotAuthor(thread, botUsernames);
26
53
  const unknownStatusThreads = threads.filter((thread) => thread.isResolved === undefined || thread.isOutdated === undefined);
27
54
  const unresolvedThreads = threads.filter((thread) => thread.isResolved === false && thread.isOutdated !== undefined);
28
55
  const activeThreads = unresolvedThreads
@@ -30,25 +57,13 @@ export function classifyThreadVisibility(threads, seenMap, botUsernames = new Se
30
57
  .flatMap((t) => {
31
58
  if (threadEndedByShepherd(t))
32
59
  return [];
33
- const repeatAuthor = isConfiguredBotAuthor(t, botUsernames) ||
34
- isViewerAuthoredHuman(t, botUsernames) ||
35
- (isOrdinaryHuman(t) && resolveOtherHumanThreads === "always");
36
- if (repeatAuthor && shouldRepeat(t))
60
+ if (repeatsAsActive(t, false, botUsernames, resolveOtherHumanThreads) && shouldRepeat(t))
37
61
  return [t];
38
62
  const visible = classifyVisibleThread(t, seenMap);
39
63
  return visible ? [visible] : [];
40
64
  });
41
65
  const resolutionOnlyThreads = unresolvedThreads
42
- .filter((t) => {
43
- const endedByShepherd = threadEndedByShepherd(t);
44
- if (endedByShepherd) {
45
- if (!isOrdinaryHuman(t))
46
- return true;
47
- return (isViewerAuthoredHuman(t, botUsernames) ||
48
- shouldResolveOtherHumanThread(t, resolveOtherHumanThreads));
49
- }
50
- return t.isOutdated || t.isMinimized;
51
- })
66
+ .filter((t) => isResolutionOnlyCandidate(t, threadEndedByShepherd(t), botUsernames, resolveOtherHumanThreads))
52
67
  .flatMap((t) => {
53
68
  const visible = classifyVisibleThread(t, seenMap);
54
69
  if (visible)
@@ -0,0 +1,2 @@
1
+ /** Built-in `bot-usernames`: known code-review bot logins treated as bots. */
2
+ export declare const DEFAULT_BOT_USERNAMES: string[];
@@ -0,0 +1,15 @@
1
+ /** Built-in `bot-usernames`: known code-review bot logins treated as bots. */
2
+ export const DEFAULT_BOT_USERNAMES = [
3
+ "chatgpt-connector",
4
+ "openai-codex",
5
+ "codex",
6
+ "claude",
7
+ "copilot-pull-request-reviewer",
8
+ "gemini-code-assist",
9
+ "coderabbitai",
10
+ "greptile-apps",
11
+ "qodo-merge-pro",
12
+ "deepsource-io",
13
+ "sonarqubecloud",
14
+ "what-the-diff",
15
+ ];
@@ -1,143 +1,9 @@
1
- import { type MergeMethod } from "./merge-method.mts";
2
- import { type GithubTransport } from "../github/transport-mode.mts";
3
- declare const MINIMIZE_COMMENTS_POLICIES: readonly ["all", "bots", "users", "none"];
4
- export type MinimizeCommentsPolicy = (typeof MINIMIZE_COMMENTS_POLICIES)[number];
5
- declare const RESOLVE_OTHER_HUMAN_THREADS: readonly ["none", "outdated", "always"];
6
- export type ResolveOtherHumanThreads = (typeof RESOLVE_OTHER_HUMAN_THREADS)[number];
7
- export declare const INSTRUCTION_STYLES: readonly ["playbook", "inline"];
1
+ import { type PrShepherdConfig } from "./resolve.mts";
2
+ export type { GraphqlQuotaWarningBand, InstructionStyle, MinimizeCommentsPolicy, PrShepherdConfig, ResolveOtherHumanThreads, } from "./resolve.mts";
8
3
  /**
9
- * How `fix_code` `## Instructions` render invariant procedure text. `inline` (default)
10
- * prints every step each tick; `playbook` points at the shipped "Fix-code loop" playbook.
4
+ * Load the config for the effective cwd: built-in defaults, then `$HOME`, then each ancestor
5
+ * down to cwd, closest file winning. Any invalid file throws a `ShepherdError` (exit 78).
11
6
  */
12
- export type InstructionStyle = (typeof INSTRUCTION_STYLES)[number];
13
- export declare function isInstructionStyle(value: unknown): value is InstructionStyle;
14
- export declare const POLL_MODES: readonly ["auto", "poll", "event"];
15
- /**
16
- * `poll` blocks and loops. `event` runs one tick and reports `nextCheck`. `auto` resolves to
17
- * `event` when `CLAUDE_CODE_REMOTE=true` and to `poll` everywhere else.
18
- */
19
- export type PollMode = (typeof POLL_MODES)[number];
20
- export declare function isPollMode(value: unknown): value is PollMode;
21
- export interface GraphqlQuotaWarningBand {
22
- remainingPercent: number;
23
- pollIntervalMinutes: number;
24
- }
25
- interface PollConfig {
26
- intervalSeconds: number;
27
- /** Multiplier for aggregate polls when `--interval` is omitted. Finite and at least 1. */
28
- stackIntervalFactor: number;
29
- timeoutSeconds: number;
30
- debounceSeconds: number;
31
- quietStatus: boolean;
32
- mode: PollMode;
33
- /**
34
- * Longest gap between GraphQL snapshots while conditional REST reads report an idle PR
35
- * unchanged. `0` disables the REST change detectors on the GraphQL transport.
36
- */
37
- reconcileSeconds: number;
38
- }
39
- export interface PrShepherdConfig {
40
- /** GitHub API settings; auto prefers GraphQL outside Claude Code cloud sessions. */
41
- github?: {
42
- transport?: GithubTransport;
43
- };
44
- /**
45
- * Optional user classification configuration; preserved for rule consumers. Shepherd reads
46
- * only `classify.standard`, a map of bundled rule name (or `all`) to boolean.
47
- */
48
- classify?: unknown;
49
- /** Bundled classification rules enabled by `classify.standard`, resolved and sorted by name. */
50
- standardRules: string[];
51
- /** Argv prefix for every pr-shepherd command Shepherd emits, e.g. `["pnpm", "exec", "pr-shepherd"]`. */
52
- cliCommand: string[];
53
- /** GitHub logins that should be treated as bots even when GitHub reports User/Unknown. */
54
- botUsernames: string[];
55
- /** Case-insensitive glob patterns for check/status context names Shepherd should ignore. */
56
- ignoreChecks: string[];
57
- iterate: {
58
- fixAttemptsPerThread: number;
59
- stallTimeoutMinutes: number;
60
- /**
61
- * When `true`, APPROVED-state reviews are also eligible for minimization — defaults to `false`
62
- * so approvals stay visible. `minimizeComments` still filters by GitHub author type.
63
- */
64
- minimizeApprovals: boolean;
65
- /**
66
- * Which GitHub author classes should be auto-minimized for minimizable PR comments and review
67
- * summaries. Items excluded by this policy are still surfaced once (and after edits) via seen
68
- * markers so they do not repeat forever.
69
- */
70
- minimizeComments: MinimizeCommentsPolicy;
71
- /**
72
- * One-liner hint appended to the `fix_code` push instruction when the branch is behind its
73
- * base — e.g. "rebase --force-with-lease" or "see .agents/skills/git-and-prs.md". Empty
74
- * (default) omits the hint entirely; the CLI never prescribes rebase/merge mechanics itself.
75
- */
76
- behindBaseHint: string;
77
- /**
78
- * Per-tick budget for review-item bodies in `fix_code` output, in characters. Over budget,
79
- * iterate shows a priority-ordered subset and holds the rest (unmarked) for later ticks.
80
- * `0` disables the cap.
81
- */
82
- reviewOutputMaxChars: number;
83
- /**
84
- * When to resolve other-human inline threads after Shepherd replies. Own and bot threads
85
- * always reply-and-resolve. `none` (default) keeps other humans reply-only; `outdated`
86
- * also resolves when GitHub reports `isOutdated`; `always` pairs reply-and-resolve.
87
- */
88
- resolveOtherHumanThreads: ResolveOtherHumanThreads;
89
- /**
90
- * `inline` (default) prints the commit/push step of `fix_code` instructions
91
- * every tick; `playbook` folds it into one `Playbook: "Fix-code loop"` pointer. The
92
- * default is inline because the token bench measured playbook as a net cost: it adds a read. The `--instructions` flag and MCP `instructions` input override per call.
93
- */
94
- instructions: InstructionStyle;
95
- };
96
- poll: PollConfig;
97
- watch: {
98
- readyDelayMinutes: number;
99
- graphqlQuotaWarnings: GraphqlQuotaWarningBand[];
100
- };
101
- resolve: {
102
- shaPoll: {
103
- intervalMs: number;
104
- maxAttempts: number;
105
- };
106
- };
107
- checks: {
108
- ciTriggerEvents: string[];
109
- /** Regex patterns matched against each raw log line; matching lines are dropped from log excerpts. Empty by default — no lines are stripped unless configured. */
110
- ignoreLogLines: string[];
111
- };
112
- mergeStatus: {
113
- blockingReviewerLogins: string[];
114
- };
115
- merge?: {
116
- /** Preferred merge method. Used only when the repository allows it. */
117
- method?: MergeMethod;
118
- /** Options added to ordinary `gh pr merge` commands. Queue commands never use these. */
119
- commandArgs: string[];
120
- };
121
- actions: {
122
- autoMinimizeSuppressed: boolean;
123
- autoMarkReady: boolean;
124
- /** Legacy-named patterns that keep matching Actions checks visible despite ignoreChecks. */
125
- neverCancelRuns: string[];
126
- /**
127
- * When `false` (default), `iterate --merge` defers non-CI actionable work
128
- * (review threads, comments, changes-requested reviews, review summaries)
129
- * while the PR sits in the merge queue, since a Shepherd-initiated push
130
- * would eject it. When `true`, restores pre-existing behavior: actionable
131
- * work is handled immediately regardless of queue membership.
132
- */
133
- workWhileQueued: boolean;
134
- /** @deprecated Accepted for compatibility, ignored by the loader. */
135
- autoResolveOutdated?: boolean;
136
- /** @deprecated Accepted for compatibility, ignored by the loader. */
137
- commitSuggestions?: boolean;
138
- };
139
- }
140
7
  export declare function loadConfig(): PrShepherdConfig;
141
8
  /** Reset the config cache — for use in tests that change directories. */
142
9
  export declare function _resetConfigCache(): void;
143
- export {};