pr-shepherd 0.60.1 → 1.0.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 (197) 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 +2 -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/runner.d.mts +1 -1
  50. package/bin/cli/runner.mjs +2 -2
  51. package/bin/cli/stack-overview.d.mts +0 -1
  52. package/bin/cli/stack-overview.mjs +1 -2
  53. package/bin/cli/{fix-formatter-extra.d.mts → triage-formatter-extra.d.mts} +1 -2
  54. package/bin/cli/{fix-formatter-extra.mjs → triage-formatter-extra.mjs} +0 -6
  55. package/bin/cli/triage-formatter.d.mts +4 -0
  56. package/bin/cli/{fix-formatter.mjs → triage-formatter.mjs} +31 -42
  57. package/bin/cli/unknown-flags.d.mts +6 -0
  58. package/bin/cli/unknown-flags.mjs +29 -0
  59. package/bin/cli-parser.mjs +41 -62
  60. package/bin/commands/check-annotations.d.mts +1 -1
  61. package/bin/commands/check-annotations.mjs +1 -1
  62. package/bin/commands/check-review-budget.d.mts +1 -1
  63. package/bin/commands/check-review-budget.mjs +1 -1
  64. package/bin/commands/check-wait-detectors.d.mts +1 -1
  65. package/bin/commands/check-wait-detectors.mjs +1 -1
  66. package/bin/commands/check.d.mts +1 -1
  67. package/bin/commands/check.mjs +7 -7
  68. package/bin/commands/commit-suggestion-instruction.d.mts +2 -2
  69. package/bin/commands/commit-suggestion-instruction.mjs +3 -3
  70. package/bin/commands/iterate/api-usage.mjs +8 -8
  71. package/bin/commands/iterate/check-instructions.d.mts +4 -4
  72. package/bin/commands/iterate/check-instructions.mjs +8 -8
  73. package/bin/commands/iterate/classify.mjs +2 -2
  74. package/bin/commands/iterate/escalate.mjs +6 -6
  75. package/bin/commands/iterate/index.mjs +20 -23
  76. package/bin/commands/iterate/merge-plan.mjs +3 -3
  77. package/bin/commands/iterate/merge-state.mjs +4 -7
  78. package/bin/commands/iterate/native-stack-rebase.mjs +1 -1
  79. package/bin/commands/iterate/render.d.mts +1 -1
  80. package/bin/commands/iterate/render.mjs +2 -2
  81. package/bin/commands/iterate/stall.mjs +11 -9
  82. package/bin/commands/iterate/{fix-loop-instruction.mjs → triage-loop-instruction.mjs} +7 -3
  83. package/bin/commands/iterate/{fix-code.d.mts → triage.d.mts} +2 -2
  84. package/bin/commands/iterate/{fix-code.mjs → triage.mjs} +14 -23
  85. package/bin/commands/iterate/unreported-required.mjs +2 -5
  86. package/bin/commands/journal/index.d.mts +1 -3
  87. package/bin/commands/journal/index.mjs +1 -1
  88. package/bin/commands/mark-files-as-viewed.d.mts +1 -3
  89. package/bin/commands/mark-files-as-viewed.mjs +1 -1
  90. package/bin/commands/next-check.d.mts +2 -2
  91. package/bin/commands/next-check.mjs +4 -2
  92. package/bin/commands/poll-progress.mjs +1 -1
  93. package/bin/commands/poll-summary-explicit-instructions.mjs +1 -1
  94. package/bin/commands/poll-summary-instructions.mjs +7 -7
  95. package/bin/commands/poll-summary.mjs +4 -4
  96. package/bin/commands/poll.d.mts +1 -1
  97. package/bin/commands/poll.mjs +4 -4
  98. package/bin/commands/resolve-mutate.d.mts +1 -1
  99. package/bin/commands/resolve-mutate.mjs +1 -1
  100. package/bin/commands/rest-stack-merge-readiness.mjs +1 -1
  101. package/bin/commands/single-tick.d.mts +5 -0
  102. package/bin/commands/single-tick.mjs +7 -0
  103. package/bin/commands/stack-drain.mjs +1 -1
  104. package/bin/commands/stack-merge-flag.mjs +1 -1
  105. package/bin/commands/stack-stall.d.mts +2 -2
  106. package/bin/commands/stack-stall.mjs +2 -2
  107. package/bin/commands/stack-work.d.mts +2 -2
  108. package/bin/commands/stack-work.mjs +2 -2
  109. package/bin/commands/suggestion-patch-item.d.mts +0 -1
  110. package/bin/commands/suggestion-patch-item.mjs +0 -12
  111. package/bin/commands/suggestion-patches.d.mts +2 -2
  112. package/bin/commands/suggestion-patches.mjs +1 -1
  113. package/bin/commands/tick-instructions.d.mts +9 -0
  114. package/bin/commands/tick-instructions.mjs +23 -0
  115. package/bin/commands/tick.d.mts +15 -0
  116. package/bin/commands/{event-mode.mjs → tick.mjs} +39 -55
  117. package/bin/comments/minimize-policy.mjs +1 -3
  118. package/bin/comments/resolve.d.mts +0 -23
  119. package/bin/comments/resolve.mjs +0 -4
  120. package/bin/comments/review-output-budget.d.mts +1 -1
  121. package/bin/comments/review-output-budget.mjs +1 -1
  122. package/bin/comments/sha-poll.mjs +3 -1
  123. package/bin/config/default-bot-usernames.d.mts +2 -0
  124. package/bin/config/default-bot-usernames.mjs +15 -0
  125. package/bin/config/load.d.mts +4 -138
  126. package/bin/config/load.mjs +88 -443
  127. package/bin/config/merge-command-args.mjs +2 -2
  128. package/bin/config/merge-method.d.mts +1 -2
  129. package/bin/config/merge-method.mjs +1 -8
  130. package/bin/config/renames.d.mts +8 -0
  131. package/bin/config/renames.mjs +87 -0
  132. package/bin/config/resolve.d.mts +31 -0
  133. package/bin/config/resolve.mjs +89 -0
  134. package/bin/config/schema.d.mts +161 -0
  135. package/bin/config/schema.mjs +168 -0
  136. package/bin/exit-codes.d.mts +1 -1
  137. package/bin/exit-codes.mjs +3 -3
  138. package/bin/github/poll-summary-check-blockers.mjs +1 -1
  139. package/bin/github/poll-summary-command.mjs +8 -6
  140. package/bin/github/poll-summary-projector.mjs +2 -2
  141. package/bin/github/poll-summary-review.mjs +1 -1
  142. package/bin/github/poll-summary-route.mjs +9 -9
  143. package/bin/github/poll-summary-unreported.mjs +1 -1
  144. package/bin/github/poll-summary.mjs +1 -1
  145. package/bin/github/queries.d.mts +1 -1
  146. package/bin/github/queries.mjs +1 -1
  147. package/bin/mcp/server.mjs +48 -54
  148. package/bin/merge-status/derive.mjs +1 -1
  149. package/bin/state/durable-state.d.mts +1 -3
  150. package/bin/state/durable-state.mjs +2 -8
  151. package/bin/state/fix-attempts.d.mts +2 -2
  152. package/bin/state/fix-attempts.mjs +1 -1
  153. package/bin/state/merge-request.mjs +1 -1
  154. package/bin/state/pr-fingerprint.mjs +4 -11
  155. package/bin/state/seen-comments.d.mts +4 -5
  156. package/bin/state/seen-comments.mjs +8 -14
  157. package/bin/state/stack-stall.d.mts +1 -1
  158. package/bin/state/stack-stall.mjs +1 -1
  159. package/bin/state/stall-state-store.d.mts +1 -1
  160. package/bin/state/stall-state-store.mjs +1 -1
  161. package/bin/types/escalate.d.mts +2 -2
  162. package/bin/types/iterate.d.mts +12 -26
  163. package/bin/types/merge-queue.d.mts +2 -2
  164. package/bin/types/next-check.d.mts +1 -1
  165. package/bin/types/poll-summary.d.mts +3 -6
  166. package/bin/types/report.d.mts +2 -2
  167. package/bin/types/suggestion-patch.d.mts +1 -8
  168. package/package.json +2 -1
  169. package/plugins/pr-shepherd/.claude-plugin/plugin.json +1 -1
  170. package/plugins/pr-shepherd/.codex-plugin/plugin.json +1 -1
  171. package/plugins/pr-shepherd/.codex.mcp.json +1 -1
  172. package/plugins/pr-shepherd/.mcp.json +1 -1
  173. package/plugins/pr-shepherd/skills/pr-shepherd/SKILL.md +6 -6
  174. package/plugins/pr-shepherd/skills/pr-shepherd/references/ci-failure-triage.md +1 -1
  175. package/plugins/pr-shepherd/skills/pr-shepherd/references/{cloud-event-loop.md → event-loop.md} +5 -5
  176. package/plugins/pr-shepherd/skills/pr-shepherd/references/mcp-fallback.md +3 -3
  177. package/plugins/pr-shepherd/skills/pr-shepherd/references/merge-queue-ejection.md +1 -1
  178. package/plugins/pr-shepherd/skills/pr-shepherd/references/suggestion-patches.md +1 -1
  179. package/plugins/pr-shepherd/skills/pr-shepherd/references/{fix-code-loop.md → triage-loop.md} +3 -3
  180. package/plugins/pr-shepherd/skills/reduce-pr-noise/SKILL.md +1 -1
  181. package/plugins/pr-shepherd/skills/reduce-pr-noise/references/classifiers.md +2 -2
  182. package/plugins/pr-shepherd/skills/reduce-pr-noise/references/settings.md +11 -11
  183. package/pr-shepherd.schema.json +361 -0
  184. package/bin/cli/event-state-scope.d.mts +0 -19
  185. package/bin/cli/event-state-scope.mjs +0 -60
  186. package/bin/cli/fix-formatter.d.mts +0 -4
  187. package/bin/commands/commit-suggestion.d.mts +0 -8
  188. package/bin/commands/commit-suggestion.mjs +0 -26
  189. package/bin/commands/event-instructions.d.mts +0 -11
  190. package/bin/commands/event-instructions.mjs +0 -27
  191. package/bin/commands/event-mode.d.mts +0 -14
  192. package/bin/commands/poll-mode.d.mts +0 -8
  193. package/bin/commands/poll-mode.mjs +0 -14
  194. package/bin/config.json +0 -68
  195. package/bin/types/protected-run.d.mts +0 -6
  196. package/bin/types/protected-run.mjs +0 -1
  197. /package/bin/commands/iterate/{fix-loop-instruction.d.mts → triage-loop-instruction.d.mts} +0 -0
@@ -23,7 +23,7 @@ export interface ReviewOutputBuckets {
23
23
  editedComments: EditedComment[];
24
24
  }
25
25
  /**
26
- * Applies `iterate.reviewOutputMaxChars` to one tick's review buckets. Priority: changes-requested
26
+ * Applies `iterate.review-output-max-chars` to one tick's review buckets. Priority: changes-requested
27
27
  * reviews, active threads and comments, first-look items, review summaries, edited comments.
28
28
  * Approved reviews are opt-in minimize targets, not review work, and are never held.
29
29
  * Held items leave every list — the report, the generated mutation IDs, and the seen-marker
@@ -10,7 +10,7 @@ const threadItem = (thread) => ({
10
10
  cost: threadTranscriptBody(thread).length,
11
11
  });
12
12
  /**
13
- * Applies `iterate.reviewOutputMaxChars` to one tick's review buckets. Priority: changes-requested
13
+ * Applies `iterate.review-output-max-chars` to one tick's review buckets. Priority: changes-requested
14
14
  * reviews, active threads and comments, first-look items, review summaries, edited comments.
15
15
  * Approved reviews are opt-in minimize targets, not review work, and are never held.
16
16
  * Held items leave every list — the report, the generated mutation IDs, and the seen-marker
@@ -14,7 +14,7 @@ type StateKey = {
14
14
  * when this read differs from the digest stored beside the report, or no digest is stored yet
15
15
  * (the seeding tick): the stored report may predate what the detectors saw, so the tick must
16
16
  * not reuse it through the GraphQL fingerprint either. A same-digest read past
17
- * `poll.reconcileSeconds` leaves `changed` unset.
17
+ * `poll.reconcile-seconds` leaves `changed` unset.
18
18
  */
19
19
  export type WaitDetectorResult = {
20
20
  reused: ShepherdReport;
@@ -51,7 +51,7 @@ async function readDetectors(prNumber, repo, report) {
51
51
  * is rethrown so the tick aborts and polling backs off.
52
52
  */
53
53
  export async function readWaitDetectors(prNumber, repo, stateKey, config, now = Date.now()) {
54
- const reconcileMs = config.poll.reconcileSeconds * 1000;
54
+ const reconcileMs = config.poll["reconcile-seconds"] * 1000;
55
55
  if (reconcileMs === 0 || getGithubTransport() === "rest")
56
56
  return undefined;
57
57
  const stored = await loadPrFingerprint(stateKey);
@@ -7,7 +7,7 @@ type CheckOptions = GlobalOptions & {
7
7
  persistSeen?: boolean;
8
8
  fingerprintCache?: boolean;
9
9
  merge?: boolean;
10
- /** Per-tick review-item body budget (`iterate.reviewOutputMaxChars`). Omitted or 0: no cap. */
10
+ /** Per-tick review-item body budget (`iterate.review-output-max-chars`). Omitted or 0: no cap. */
11
11
  reviewOutputMaxChars?: number;
12
12
  };
13
13
  export declare function runCheck(opts: CheckOptions, context?: CheckExecutionContext): Promise<ShepherdReport>;
@@ -60,7 +60,7 @@ export async function runCheck(opts, context) {
60
60
  async function runScopedCheck(opts, context, repo, prNumber, stateKey) {
61
61
  const config = loadConfig();
62
62
  const reuseFingerprint = opts.fingerprintCache === true;
63
- const paginateApprovedReviews = config.iterate.minimizeApprovals;
63
+ const paginateApprovedReviews = config.iterate["minimize-approvals"];
64
64
  const includeReceiptSummary = (await context?.wantsReceiptSummary(prNumber, repo)) ?? false;
65
65
  // GraphQL transport: conditional REST change detectors can replay an idle report for free.
66
66
  // Changed trunk rules invalidate a cached report; check again without reuse.
@@ -125,7 +125,7 @@ async function runScopedCheck(opts, context, repo, prNumber, stateKey) {
125
125
  owner: repo.owner,
126
126
  name: repo.name,
127
127
  pr: prNumber,
128
- relevantEvents: config.checks.ciTriggerEvents,
128
+ relevantEvents: config.checks["ci-trigger-events"],
129
129
  }, context);
130
130
  const classifiedPrChecks = classifyChecks(allChecks, {
131
131
  requiredContexts: unreported.requiredContexts,
@@ -194,7 +194,7 @@ async function runScopedCheck(opts, context, repo, prNumber, stateKey) {
194
194
  const seenMap = await loadSeenMap(stateKey);
195
195
  await aliasThreadSeenMarkers(repo, prNumber, batchData.reviewThreads.map((thread) => thread.id), seenMap);
196
196
  const canGenerateItemMutation = (id, body, capability, operation) => !mutationWasDenied(id, body, seenMap) && canGenerateGithubMutation(capability, operation);
197
- const botUsernames = normalizeBotUsernames(config.botUsernames);
197
+ const botUsernames = normalizeBotUsernames(config["bot-usernames"]);
198
198
  const ruleSet = await loadClassifyRules(getEffectiveCwd(), config.standardRules);
199
199
  const classifyIndex = buildClassifyIndex(ruleSet, batchData);
200
200
  const partition = partitionBatch(classifyIndex, batchData);
@@ -202,7 +202,7 @@ async function runScopedCheck(opts, context, repo, prNumber, stateKey) {
202
202
  const ignoredAnnotated = merged.ignored.filter((c) => (c.annotations?.length ?? 0) > 0);
203
203
  const minimizedCommentCandidates = batchData.comments.filter((c) => c.isMinimized && !partition.suppressedCommentIds.has(c.id));
204
204
  const deniedRuleAutoResolveCommentIds = new Set(partition.ruleAutoResolveCommentIds.filter((id) => !canGenerateItemMutation(id, batchData.comments.find((comment) => comment.id === id)?.body ?? "", batchData.comments.find((comment) => comment.id === id)?.viewerCanMinimize, "minimize")));
205
- const visibleCommentClassification = classifyVisibleComments(batchData.comments.filter((c) => !partition.suppressedCommentIds.has(c.id) || deniedRuleAutoResolveCommentIds.has(c.id)), seenMap, config.iterate.minimizeComments, botUsernames, new Set(batchData.comments
205
+ const visibleCommentClassification = classifyVisibleComments(batchData.comments.filter((c) => !partition.suppressedCommentIds.has(c.id) || deniedRuleAutoResolveCommentIds.has(c.id)), seenMap, config.iterate["minimize-comments"], botUsernames, new Set(batchData.comments
206
206
  .filter((comment) => mutationWasDenied(comment.id, comment.body, seenMap))
207
207
  .map((comment) => comment.id)));
208
208
  const deniedRuleAutoResolveThreadIds = new Set(partition.ruleAutoResolveThreadIds.filter((id) => {
@@ -211,7 +211,7 @@ async function runScopedCheck(opts, context, repo, prNumber, stateKey) {
211
211
  !canGenerateItemMutation(thread.id, threadTranscriptBody(thread), thread.viewerCanResolve, "resolve"));
212
212
  }));
213
213
  const visibleThreadCandidates = batchData.reviewThreads.filter((t) => !partition.suppressedThreadIds.has(t.id) || deniedRuleAutoResolveThreadIds.has(t.id));
214
- const resolveOtherHumanThreads = config.iterate.resolveOtherHumanThreads ?? "none";
214
+ const resolveOtherHumanThreads = config.iterate["resolve-other-human-threads"] ?? "none";
215
215
  const threadMutationRouting = buildThreadMutationRouting(visibleThreadCandidates, botUsernames, partition.ruleAutoResolveThreadIds, resolveOtherHumanThreads);
216
216
  const replyThreadIds = new Set(threadMutationRouting.replyThreadIds);
217
217
  const resolveThreadIds = new Set(threadMutationRouting.resolveThreadIds);
@@ -288,11 +288,11 @@ async function runScopedCheck(opts, context, repo, prNumber, stateKey) {
288
288
  // persisting seen markers for it now would make it silently vanish from every later tick
289
289
  // once it's no longer "new" or "edited", even after the PR leaves the queue. A queued PR
290
290
  // that also has check-driven work (failing checks, actionable annotations, conflicts) is
291
- // NOT deferred — index.mts still renders these items via fix_code — so this must stay false
291
+ // NOT deferred — index.mts still renders these items via triage — so this must stay false
292
292
  // in that case too, or their seen markers would be suppressed while actually being shown.
293
293
  const deferWhileQueued = opts.merge === true &&
294
294
  batchData.isInMergeQueue === true &&
295
- config.actions.workWhileQueued !== true &&
295
+ config.actions["work-while-queued"] !== true &&
296
296
  !hasCheckDrivenActionableWork({
297
297
  failing: merged.failing,
298
298
  passing: merged.passing,
@@ -1,6 +1,6 @@
1
1
  /**
2
- * Build the `build-suggestion-patches` instruction step for agent consumers.
3
- * Currently emitted by iterate `fix_code` for suggestion review threads. The CLI keeps
2
+ * Build the `suggest` instruction step for agent consumers.
3
+ * Currently emitted by iterate `triage` for suggestion review threads. The CLI keeps
4
4
  * only the trigger and the concrete command; refusal/drift handling is invariant across
5
5
  * every invocation, so it lives in the pr-shepherd skill's "Suggestion patches" playbook
6
6
  * instead of being re-emitted every tick (see AGENTS.md "Keep skills and loop prompts
@@ -1,8 +1,8 @@
1
1
  import { buildPrShepherdCommand } from "../cli/runner.mjs";
2
2
  import { playbookPointer } from "./playbook-pointer.mjs";
3
3
  /**
4
- * Build the `build-suggestion-patches` instruction step for agent consumers.
5
- * Currently emitted by iterate `fix_code` for suggestion review threads. The CLI keeps
4
+ * Build the `suggest` instruction step for agent consumers.
5
+ * Currently emitted by iterate `triage` for suggestion review threads. The CLI keeps
6
6
  * only the trigger and the concrete command; refusal/drift handling is invariant across
7
7
  * every invocation, so it lives in the pr-shepherd skill's "Suggestion patches" playbook
8
8
  * instead of being re-emitted every tick (see AGENTS.md "Keep skills and loop prompts
@@ -12,7 +12,7 @@ import { playbookPointer } from "./playbook-pointer.mjs";
12
12
  */
13
13
  export function buildCommitSuggestionInstruction(prReference, sectionName) {
14
14
  const command = buildPrShepherdCommand([
15
- "build-suggestion-patches",
15
+ "suggest",
16
16
  String(prReference),
17
17
  "--thread-id",
18
18
  "<id>",
@@ -3,9 +3,9 @@ import { summarizeApiTelemetry } from "../../github/api-telemetry.mjs";
3
3
  import { selectQuotaWarning } from "../quota-selection.mjs";
4
4
  import { buildQuotaAwareContinuation } from "../../quota-warning.mjs";
5
5
  import { getGithubTransport } from "../../github/transport.mjs";
6
- import { isFixCodeContinuation } from "./check-instructions.mjs";
6
+ import { isTriageContinuation } from "./check-instructions.mjs";
7
7
  function shouldWarn(result) {
8
- return ["wait", "mark_ready", "merge", "fix_code"].includes(result.action);
8
+ return ["wait", "mark_ready", "merge", "triage"].includes(result.action);
9
9
  }
10
10
  export async function attachApiUsage(result, persistWarning, preservePersistedWarning = false, minimumPollIntervalMinutes = 0) {
11
11
  const apiUsage = summarizeApiTelemetry();
@@ -16,7 +16,7 @@ export async function attachApiUsage(result, persistWarning, preservePersistedWa
16
16
  if (quotaWarning === undefined && shouldWarn(result) && (apiUsage.graphql || core)) {
17
17
  const [owner, repo] = result.repo.split("/");
18
18
  if (owner && repo) {
19
- const bands = loadConfig().watch.graphqlQuotaWarnings.map((band) => ({
19
+ const bands = loadConfig().quotaWarningBands.map((band) => ({
20
20
  ...band,
21
21
  pollIntervalMinutes: Math.max(band.pollIntervalMinutes, minimumPollIntervalMinutes),
22
22
  }));
@@ -29,14 +29,14 @@ export async function attachApiUsage(result, persistWarning, preservePersistedWa
29
29
  apiUsage,
30
30
  ...(quotaWarning !== undefined && { quotaWarning }),
31
31
  };
32
- if (quotaWarning === undefined || withWarning.action !== "fix_code")
32
+ if (quotaWarning === undefined || withWarning.action !== "triage")
33
33
  return withWarning;
34
- const instructions = [...withWarning.fix.instructions];
34
+ const instructions = [...withWarning.triage.instructions];
35
35
  const completion = instructions.at(-1);
36
36
  if (completion !== undefined) {
37
- if (isFixCodeContinuation(completion)) {
38
- instructions[instructions.length - 1] = buildQuotaAwareContinuation(quotaWarning, "`[FIX_CODE]` is non-terminal. After completing these steps,");
37
+ if (isTriageContinuation(completion)) {
38
+ instructions[instructions.length - 1] = buildQuotaAwareContinuation(quotaWarning, "`[TRIAGE]` is non-terminal. After completing these steps,");
39
39
  }
40
40
  }
41
- return { ...withWarning, fix: { ...withWarning.fix, instructions } };
41
+ return { ...withWarning, triage: { ...withWarning.triage, instructions } };
42
42
  }
@@ -1,11 +1,11 @@
1
1
  import type { AgentCheck, ResolveCommand, Review } from "../../types.mts";
2
- /** The `[FIX_CODE]` recurrence step, whether plain or rewritten by the quota warning. */
3
- export declare function isFixCodeContinuation(step: string): boolean;
2
+ /** The `[TRIAGE]` recurrence step, whether plain or rewritten by the quota warning. */
3
+ export declare function isTriageContinuation(step: string): boolean;
4
4
  /** Build the stale-CR step for `## Changes-requested reviews`. Empty when no human CR is stale. */
5
5
  export declare function buildCrStaleClause(reviews: Review[]): string;
6
6
  /**
7
7
  * Build the optional branch-update hint. Empty unless the branch is behind or conflicts with its
8
- * base and the user configured a non-blank `iterate.behindBaseHint` — the CLI never prescribes
8
+ * base and the user configured a non-blank `iterate.behind-base-hint` — the CLI never prescribes
9
9
  * rebase/merge mechanics itself (see "Keep skills and loop prompts minimal" in AGENTS.md); this
10
10
  * only echoes back the caller's own configured pointer. `hint` is trimmed and type-checked at the
11
11
  * point of use (rather than at config load) so a malformed rc file value (non-string, or
@@ -37,7 +37,7 @@ export declare function buildResolveCommandInstruction(resolveCommand: ResolveCo
37
37
  export declare function buildFailingCheckInstructions(checks: AgentCheck[]): string[];
38
38
  /** Update the PR branch after an external blocker merges or closes. Never rerun that job. */
39
39
  export declare function buildReleasedBlockerInstruction(prNumber: number): string;
40
- /** `iterate.reviewOutputMaxChars` held review items back; the rerun step that follows shows them. */
40
+ /** `iterate.review-output-max-chars` held review items back; the rerun step that follows shows them. */
41
41
  export declare function buildReviewSubsetInstruction(reviewItems: {
42
42
  shown: number;
43
43
  total: number;
@@ -1,9 +1,9 @@
1
1
  import { playbookPointer } from "../playbook-pointer.mjs";
2
- // The `[FIX_CODE]` heading and the skill already say the action is non-terminal.
3
- const FIX_CODE_CONTINUATION = "Rerun Shepherd now.";
4
- /** The `[FIX_CODE]` recurrence step, whether plain or rewritten by the quota warning. */
5
- export function isFixCodeContinuation(step) {
6
- return step === FIX_CODE_CONTINUATION || /\[FIX_CODE\].*non-terminal/i.test(step);
2
+ // The `[TRIAGE]` heading and the skill already say the action is non-terminal.
3
+ const TRIAGE_CONTINUATION = "Rerun Shepherd now.";
4
+ /** The `[TRIAGE]` recurrence step, whether plain or rewritten by the quota warning. */
5
+ export function isTriageContinuation(step) {
6
+ return step === TRIAGE_CONTINUATION || /\[TRIAGE\].*non-terminal/i.test(step);
7
7
  }
8
8
  /** Build the stale-CR step for `## Changes-requested reviews`. Empty when no human CR is stale. */
9
9
  export function buildCrStaleClause(reviews) {
@@ -13,7 +13,7 @@ export function buildCrStaleClause(reviews) {
13
13
  }
14
14
  /**
15
15
  * Build the optional branch-update hint. Empty unless the branch is behind or conflicts with its
16
- * base and the user configured a non-blank `iterate.behindBaseHint` — the CLI never prescribes
16
+ * base and the user configured a non-blank `iterate.behind-base-hint` — the CLI never prescribes
17
17
  * rebase/merge mechanics itself (see "Keep skills and loop prompts minimal" in AGENTS.md); this
18
18
  * only echoes back the caller's own configured pointer. `hint` is trimmed and type-checked at the
19
19
  * point of use (rather than at config load) so a malformed rc file value (non-string, or
@@ -74,12 +74,12 @@ export function buildReleasedBlockerInstruction(prNumber) {
74
74
  ? "Update this PR branch from its base using the repository's branch-update procedure. Do not rerun the job; a rerun retests the old merge ref."
75
75
  : `Update this PR branch from its base with \`gh pr update-branch ${prNumber} --rebase\`. Do not rerun the job; a rerun retests the old merge ref.`;
76
76
  }
77
- /** `iterate.reviewOutputMaxChars` held review items back; the rerun step that follows shows them. */
77
+ /** `iterate.review-output-max-chars` held review items back; the rerun step that follows shows them. */
78
78
  export function buildReviewSubsetInstruction(reviewItems) {
79
79
  return `This is a subset: ${reviewItems.shown} of ${reviewItems.total} review items are shown, and only their IDs are in the commands above. After handling these items, rerun Shepherd for the next batch; do not fetch the held items yourself.`;
80
80
  }
81
81
  /** Recurrence only. Commit, push, rerun, and SHA steps are earlier instructions. */
82
82
  export function buildFixCompletionInstruction() {
83
- return FIX_CODE_CONTINUATION;
83
+ return TRIAGE_CONTINUATION;
84
84
  }
85
85
  import { getGithubTransport } from "../../github/transport.mjs";
@@ -24,7 +24,7 @@ export function classifyReviewSummaries(summaries, approvals, minimizeApprovals,
24
24
  // so their minimize IDs ride in the agent-facing apply command. Seen summaries
25
25
  // (already surfaced in a prior tick) have no new content to show — the CLI
26
26
  // self-minimizes them in-process (selfMinimizeIds) instead of routing a
27
- // cosmetic-only mutation through fix_code (issue #313). Edited summaries are
27
+ // cosmetic-only mutation through triage (issue #313). Edited summaries are
28
28
  // excluded entirely: they are already minimized server-side (body changed after
29
29
  // minimize was applied).
30
30
  const minimizeIds = summaries.firstLook.filter(eligible).map((r) => r.id);
@@ -61,7 +61,7 @@ export function classifyReviewSummaries(summaries, approvals, minimizeApprovals,
61
61
  };
62
62
  }
63
63
  /**
64
- * A durable-state session (event mode or a cloud session) can lose its uncertain-reply records
64
+ * A durable-state (cloud) session can lose its uncertain-reply records
65
65
  * between ticks. Its generated reply command opts in to adopting a reply GitHub already shows,
66
66
  * so rerunning the same printed command cannot double-post. Direct apply requests never do.
67
67
  */
@@ -64,11 +64,11 @@ function renderEscalateCheck(check) {
64
64
  }
65
65
  export function checkEscalateTriggers(actionableThreads, threadAttempts) {
66
66
  const triggers = [];
67
- const maxAttempts = loadConfig().iterate.fixAttemptsPerThread;
68
- // Trigger 1: fix thrash — same thread dispatched too many times without resolving.
67
+ const maxAttempts = loadConfig().iterate["triage-attempts-per-thread"];
68
+ // Trigger 1: triage thrash — same thread dispatched too many times without resolving.
69
69
  const thrashThreads = actionableThreads.filter((t) => (threadAttempts[t.id] ?? 0) >= maxAttempts);
70
70
  if (thrashThreads.length > 0) {
71
- triggers.push("fix-thrash");
71
+ triggers.push("triage-thrash");
72
72
  }
73
73
  return {
74
74
  triggers,
@@ -265,9 +265,9 @@ export function buildEscalateSuggestion(triggers, detail) {
265
265
  const reason = detail ? ` (${detail})` : "";
266
266
  return `Could not determine the PR's base branch${reason} — automated rebases are paused because branch safety is unclear. Run the rebase manually against the PR's real target branch.`;
267
267
  }
268
- if (triggers.includes("fix-thrash")) {
269
- const attempts = loadConfig().iterate.fixAttemptsPerThread;
270
- return `The same thread(s) remain unresolved after their pending review commands were returned for ${attempts} FIX_CODE ticks. Automated iteration is paused for a manual decision.`;
268
+ if (triggers.includes("triage-thrash")) {
269
+ const attempts = loadConfig().iterate["triage-attempts-per-thread"];
270
+ return `The same thread(s) remain unresolved after their pending review commands were returned for ${attempts} TRIAGE ticks. Automated iteration is paused for a manual decision.`;
271
271
  }
272
272
  return "Ambiguous state — automated handling cannot proceed safely. Inspect the PR and act manually.";
273
273
  }
@@ -8,7 +8,7 @@ import { buildWaitLog, buildTerminalCancelResult, blockedCancelNote } from "./he
8
8
  import { classifyReviewSummaries } from "./classify.mjs";
9
9
  import { applyStallGuard } from "./stall.mjs";
10
10
  import { clearStallState } from "../../state/iterate-stall.mjs";
11
- import { handleFixCode } from "./fix-code.mjs";
11
+ import { handleTriage } from "./triage.mjs";
12
12
  import { normalizeBotUsernames } from "../../comments/authors.mjs";
13
13
  import { autoMinimizeComments } from "../../comments/resolve.mjs";
14
14
  import { hasCheckDrivenActionableWork } from "../check-annotations.mjs";
@@ -60,24 +60,21 @@ async function attachEditedComments(result, tick, opts) {
60
60
  }
61
61
  async function runIterateCore(opts, tick) {
62
62
  const config = loadConfig();
63
- const botUsernames = normalizeBotUsernames(config.botUsernames);
64
- const readyDelaySeconds = opts.readyDelaySeconds ?? config.watch.readyDelayMinutes * 60;
65
- const stallTimeoutSeconds = opts.stallTimeoutSeconds ?? config.iterate.stallTimeoutMinutes * 60;
63
+ const botUsernames = normalizeBotUsernames(config["bot-usernames"]);
64
+ const readyDelaySeconds = opts.readyDelaySeconds ?? config.iterate["ready-delay-minutes"] * 60;
65
+ const stallTimeoutSeconds = opts.stallTimeoutSeconds ?? config.iterate["stall-timeout-minutes"] * 60;
66
66
  const prNumber = opts.prNumber ?? (await getCurrentPrNumber());
67
67
  if (prNumber === null) {
68
68
  throw new ShepherdError("No open PR found for current branch. Pass a PR number explicitly.", EXIT.UNAVAILABLE);
69
69
  }
70
- const neverCancelRuns = opts.neverCancelRuns ?? config.actions.neverCancelRuns;
71
70
  const checkContext = createCheckExecutionContext(readyDelaySeconds);
72
71
  const report = await runCheck({
73
72
  ...opts,
74
73
  prNumber,
75
- // Outdated Shepherd-visible threads are always resolved by iterate. The
76
- // old actions.autoResolveOutdated switch is retained only as an ignored
77
- // compatibility key in the config loader.
74
+ // Outdated Shepherd-visible threads are always resolved by iterate.
78
75
  autoResolve: true,
79
- autoMinimizeSuppressed: config.actions.autoMinimizeSuppressed,
80
- reviewOutputMaxChars: config.iterate.reviewOutputMaxChars,
76
+ autoMinimizeSuppressed: config.actions["auto-minimize-suppressed"],
77
+ reviewOutputMaxChars: config.iterate["review-output-max-chars"],
81
78
  }, checkContext);
82
79
  tick.report = report;
83
80
  const [repoOwner, repoName] = report.repo.split("/");
@@ -107,7 +104,7 @@ async function runIterateCore(opts, tick) {
107
104
  firstLook: report.firstLookSummaries,
108
105
  seen: report.reviewSummaries,
109
106
  edited: report.editedSummaries,
110
- }, report.approvedReviews, config.iterate.minimizeApprovals, config.iterate.minimizeComments, botUsernames, [
107
+ }, report.approvedReviews, config.iterate["minimize-approvals"], config.iterate["minimize-comments"], botUsernames, [
111
108
  ...report.threads.actionable,
112
109
  ...report.threads.resolutionOnly,
113
110
  ...(report.heldThreadReviewIds ?? []).map((reviewId) => ({ reviewId })),
@@ -128,7 +125,7 @@ async function runIterateCore(opts, tick) {
128
125
  }
129
126
  // A first look at an already-minimized comment is only an acknowledgment. Edited PR comments
130
127
  // (report.comments.edited) are neither: they never block readiness or restart the ready delay.
131
- // Review items held back by iterate.reviewOutputMaxChars keep the PR out of ready/merge: a
128
+ // Review items held back by iterate.review-output-max-chars keep the PR out of ready/merge: a
132
129
  // capped tick that shows only first-look comments still counts, since held work follows.
133
130
  const hasReadinessWork = (report.reviewItems !== undefined && report.comments.firstLook.length > 0) ||
134
131
  report.threads.actionable.length > 0 ||
@@ -142,7 +139,7 @@ async function runIterateCore(opts, tick) {
142
139
  reviewSummaryIds.length > 0 ||
143
140
  firstLookSummaries.length > 0 ||
144
141
  editedSummaries.length > 0 ||
145
- (config.iterate.minimizeApprovals && surfacedApprovals.length > 0);
142
+ (config.iterate["minimize-approvals"] && surfacedApprovals.length > 0);
146
143
  const hasActionableWork = hasReadinessWork || report.comments.firstLook.length > 0;
147
144
  const activeMerge = Boolean(opts.merge &&
148
145
  (report.mergeQueue?.inQueue ||
@@ -183,12 +180,12 @@ async function runIterateCore(opts, tick) {
183
180
  const checkDrivenActionableWork = hasCheckDrivenActionableWork(reportForWork.checks, report.mergeStatus.status);
184
181
  const deferWhileQueued = opts.merge === true &&
185
182
  report.mergeQueue?.inQueue === true &&
186
- config.actions.workWhileQueued !== true;
183
+ config.actions["work-while-queued"] !== true;
187
184
  if (hasActionableWork && !(deferWhileQueued && !checkDrivenActionableWork)) {
188
- return handleFixCode({
185
+ return handleTriage({
189
186
  base,
190
187
  report: reportForWork,
191
- opts: { ...opts, prNumber, neverCancelRuns },
188
+ opts: { ...opts, prNumber },
192
189
  headSha,
193
190
  stallKey,
194
191
  prNumber,
@@ -208,10 +205,10 @@ async function runIterateCore(opts, tick) {
208
205
  });
209
206
  }
210
207
  if (unreportedRepair.length > 0 && staleAncestry) {
211
- return handleFixCode({
208
+ return handleTriage({
212
209
  base,
213
210
  report: reportForWork,
214
- opts: { ...opts, prNumber, neverCancelRuns },
211
+ opts: { ...opts, prNumber },
215
212
  headSha,
216
213
  stallKey,
217
214
  prNumber,
@@ -241,15 +238,15 @@ async function runIterateCore(opts, tick) {
241
238
  firstLookSummaries,
242
239
  editedSummaries,
243
240
  surfacedApprovals,
244
- minimizeApprovals: config.iterate.minimizeApprovals,
241
+ minimizeApprovals: config.iterate["minimize-approvals"],
245
242
  });
246
243
  if (mergeStateResult)
247
244
  return annotateBlockedWait(mergeStateResult, blockerGate);
248
245
  if (staleAncestry) {
249
- return handleFixCode({
246
+ return handleTriage({
250
247
  base,
251
248
  report: reportForWork,
252
- opts: { ...opts, prNumber, neverCancelRuns },
249
+ opts: { ...opts, prNumber },
253
250
  headSha,
254
251
  stallKey,
255
252
  prNumber,
@@ -287,7 +284,7 @@ async function runIterateCore(opts, tick) {
287
284
  escalate: { ...escalation, humanMessage: buildEscalateHumanMessage(escalation, report.pr) },
288
285
  };
289
286
  }
290
- const autoMarkReady = !opts.noAutoMarkReady && config.actions.autoMarkReady;
287
+ const autoMarkReady = !opts.noAutoMarkReady && config["mark-ready"].auto;
291
288
  if (canMarkReady && !autoMarkReady) {
292
289
  await clearReadyDelay(report.pr, repoOwner, repoName);
293
290
  await clearStallState(stallKey);
@@ -307,7 +304,7 @@ async function runIterateCore(opts, tick) {
307
304
  const receipt = receiptCurrent
308
305
  ? "written"
309
306
  : await recordReadyReceipt(receiptKey, report, checkContext);
310
- // Aggregate --stack routing trusts only a layer's receipt, so an unwritten
307
+ // Aggregate `stack` routing trusts only a layer's receipt, so an unwritten
311
308
  // one keeps the elapsed marker and retries next tick. A one-PR receipt
312
309
  // only lets a rerun skip the wait, so its failure never changes the action.
313
310
  // A layer GitHub reports BLOCKED gets no receipt, so aggregate routing
@@ -7,7 +7,7 @@ import { getGithubTransport } from "../../github/transport.mjs";
7
7
  const ENQUEUE_MUTATION = "mutation EnqueuePullRequest($pullRequestId: ID!, $expectedHeadOid: GitObjectID!) { enqueuePullRequest(input: { pullRequestId: $pullRequestId, expectedHeadOid: $expectedHeadOid }) { mergeQueueEntry { id } } }";
8
8
  export function buildMergeCommandPlan(input) {
9
9
  if (input.transport === "rest" || getGithubTransport() === "rest") {
10
- const configured = configuredMergeMethod(loadConfig().merge ?? {});
10
+ const configured = configuredMergeMethod(loadConfig().merge);
11
11
  if (!input.queue && input.queueKnown !== true && configured)
12
12
  return {
13
13
  unavailable: "REST cannot verify merge-queue policy and cannot apply a configured direct merge method to an automatic merge request. Refresh branch policy before merging.",
@@ -70,10 +70,10 @@ export function buildMergeCommandPlan(input) {
70
70
  };
71
71
  }
72
72
  const mergeConfig = loadConfig().merge;
73
- const configuredArgs = mergeConfig?.commandArgs ?? [];
73
+ const configuredArgs = mergeConfig["command-args"];
74
74
  const decision = chooseMergeMethod({
75
75
  allowed: input.allowedMergeMethods,
76
- configured: configuredMergeMethod(mergeConfig ?? {}),
76
+ configured: configuredMergeMethod(mergeConfig),
77
77
  fallback: "merge",
78
78
  });
79
79
  if ("unavailable" in decision)
@@ -6,14 +6,14 @@ import { buildPrShepherdCommand } from "../../cli/runner.mjs";
6
6
  import { inlineCode } from "../../util/markdown.mjs";
7
7
  /**
8
8
  * A one-PR poll cannot prove the layers below it merged or that its PR number is a safe merge
9
- * selector. Route it through the aggregate stack selector, which merges one bottom layer at a time.
9
+ * selector. Route it through the aggregate stack command, which merges one bottom layer at a time.
10
10
  */
11
11
  function buildStackedRouteResult(base, report, stack) {
12
12
  const prUrl = formatPrUrl(report.repo, report.pr);
13
13
  return {
14
14
  ...base,
15
- action: "fix_code",
16
- fix: {
15
+ action: "triage",
16
+ triage: {
17
17
  threads: [],
18
18
  resolutionOnlyThreads: [],
19
19
  actionableComments: [],
@@ -31,14 +31,11 @@ function buildStackedRouteResult(base, report, stack) {
31
31
  },
32
32
  instructions: [
33
33
  `PR #${report.pr} is layer ${stack.position} of ${stack.size} in native stack #${stack.number}; do not run \`gh pr merge\` for this layer.`,
34
- `Run ${inlineCode(buildPrShepherdCommand(["--stack", prUrl, "--until-terminal", "--merge"]).text)} to reconcile the stack and run each bottom-layer merge command it emits.`,
34
+ `Run ${inlineCode(buildPrShepherdCommand(["stack", prUrl, "--until-terminal", "--merge"]).text)} to reconcile the stack and run each bottom-layer merge command it emits.`,
35
35
  ],
36
- inProgressRunIds: [],
37
- protectedRuns: [],
38
36
  firstLookThreads: [],
39
37
  firstLookComments: [],
40
38
  },
41
- cancelled: [],
42
39
  };
43
40
  }
44
41
  export function buildReadyMergeOutcome(enabled, readyElapsed, base, report) {
@@ -15,7 +15,7 @@ export function buildNativeStackRebaseInstruction(repo, stackNumber, start) {
15
15
  : "trunk" in start
16
16
  ? `trunk \`${start.trunk}\``
17
17
  : `bottom open layer PR #${start.bottomPr}`;
18
- return `Use the repository's stack-update procedure for native stack #${stackNumber} in \`${repo}\`, starting at ${boundary} and preserving the ordered parent boundaries of every affected upper layer. Read membership with REST-backed Shepherd \`--stack\` output and update and push affected branches using the caller's git workflow. ${playbookPointer("Branch update")}`;
18
+ return `Use the repository's stack-update procedure for native stack #${stackNumber} in \`${repo}\`, starting at ${boundary} and preserving the ordered parent boundaries of every affected upper layer. Read membership with REST-backed Shepherd \`stack\` output and update and push affected branches using the caller's git workflow. ${playbookPointer("Branch update")}`;
19
19
  }
20
20
  const [checkout, command] = "parentBranch" in start
21
21
  ? [
@@ -7,7 +7,7 @@ import type { InstructionStyle } from "../../config/load.mts";
7
7
  * if it is not. `apply review` reads that HEAD itself with a read-only `git rev-parse HEAD`.
8
8
  */
9
9
  export declare function renderResolveCommand(rc: ResolveCommand): string;
10
- export declare function buildFixInstructions(threads: AgentThread[], actionableComments: AgentComment[], checks: AgentCheck[], changesRequestedReviews: Review[], baseBranch: string, resolveCommand: ResolveCommand, hasConflicts: boolean, prReference: string | number, _cancelledCount: number, firstLookThreads?: FirstLookThread[], firstLookComments?: FirstLookComment[], firstLookSummaries?: Review[], editedSummaries?: Review[], _inProgressRunIds?: string[], resolutionOnlyThreads?: ReviewThread[], resolveOnlyCommand?: ResolveCommand, behindBaseHint?: string, // iterate.behindBaseHint — see buildBehindBaseHintInstruction
10
+ export declare function buildFixInstructions(threads: AgentThread[], actionableComments: AgentComment[], checks: AgentCheck[], changesRequestedReviews: Review[], baseBranch: string, resolveCommand: ResolveCommand, hasConflicts: boolean, prReference: string | number, firstLookThreads?: FirstLookThread[], firstLookComments?: FirstLookComment[], firstLookSummaries?: Review[], editedSummaries?: Review[], resolutionOnlyThreads?: ReviewThread[], resolveOnlyCommand?: ResolveCommand, behindBaseHint?: string, // iterate.behind-base-hint — see buildBehindBaseHintInstruction
11
11
  isBehind?: boolean, _viewerCanUpdate?: boolean, hasExhaustedWorkflowRerun?: boolean, stackRebase?: string, // native stack layers rebase with gh-stack, not branch by branch
12
12
  queueEjection?: QueueEjectionRecovery, // current merge-queue removal with failing queue checks
13
13
  instructionStyle?: InstructionStyle): string[];
@@ -5,7 +5,7 @@ import { buildCommitSuggestionInstruction } from "../commit-suggestion-instructi
5
5
  import { partitionFixThreads } from "./fix-instruction-threads.mjs";
6
6
  import { buildBranchPushInstruction, buildConflictInstruction } from "./native-stack-rebase.mjs";
7
7
  import { queueEjectionSteps } from "./queue-recovery-instructions.mjs";
8
- import { buildPushSteps } from "./fix-loop-instruction.mjs";
8
+ import { buildPushSteps } from "./triage-loop-instruction.mjs";
9
9
  /**
10
10
  * Render a resolve command as a shell snippet. Appends `--require-sha HEAD` when set: run after
11
11
  * the push step, the local HEAD is the pushed PR head, and `apply review` rejects the mutations
@@ -16,7 +16,7 @@ export function renderResolveCommand(rc) {
16
16
  return rc.requiresHeadSha ? `${command} ${REQUIRE_HEAD_SHA}` : command;
17
17
  }
18
18
  const REQUIRE_HEAD_SHA = "--require-sha HEAD";
19
- export function buildFixInstructions(threads, actionableComments, checks, changesRequestedReviews, baseBranch, resolveCommand, hasConflicts, prReference, _cancelledCount, firstLookThreads = [], firstLookComments = [], firstLookSummaries = [], editedSummaries = [], _inProgressRunIds = [], resolutionOnlyThreads = [], resolveOnlyCommand, behindBaseHint = "", // iterate.behindBaseHint — see buildBehindBaseHintInstruction
19
+ export function buildFixInstructions(threads, actionableComments, checks, changesRequestedReviews, baseBranch, resolveCommand, hasConflicts, prReference, firstLookThreads = [], firstLookComments = [], firstLookSummaries = [], editedSummaries = [], resolutionOnlyThreads = [], resolveOnlyCommand, behindBaseHint = "", // iterate.behind-base-hint — see buildBehindBaseHintInstruction
20
20
  isBehind = false, _viewerCanUpdate = false, hasExhaustedWorkflowRerun = false, stackRebase, // native stack layers rebase with gh-stack, not branch by branch
21
21
  queueEjection, // current merge-queue removal with failing queue checks
22
22
  instructionStyle = "inline") {
@@ -5,25 +5,27 @@ import { buildEscalateSuggestion, buildEscalateHumanMessage, formatDurationAppro
5
5
  import { checksWithActionableAnnotations } from "../check-annotations.mjs";
6
6
  import { formatPrUrl } from "../../pr-reference.mjs";
7
7
  function pendingReviewCommandsFromResult(result) {
8
- if (result.action !== "fix_code")
8
+ if (result.action !== "triage")
9
9
  return undefined;
10
10
  const pending = {
11
- ...(result.fix.resolveOnlyCommand?.hasMutations && {
12
- resolveOnlyCommand: result.fix.resolveOnlyCommand,
11
+ ...(result.triage.resolveOnlyCommand?.hasMutations && {
12
+ resolveOnlyCommand: result.triage.resolveOnlyCommand,
13
+ }),
14
+ ...(result.triage.resolveCommand.hasMutations && {
15
+ resolveCommand: result.triage.resolveCommand,
13
16
  }),
14
- ...(result.fix.resolveCommand.hasMutations && { resolveCommand: result.fix.resolveCommand }),
15
17
  };
16
18
  return Object.keys(pending).length > 0 ? pending : undefined;
17
19
  }
18
20
  function surfacedSummariesFromResult(result) {
19
- if (result.action !== "fix_code")
21
+ if (result.action !== "triage")
20
22
  return {};
21
23
  return {
22
- ...(result.fix.firstLookSummaries.length > 0 && {
23
- firstLookSummaries: result.fix.firstLookSummaries,
24
+ ...(result.triage.firstLookSummaries.length > 0 && {
25
+ firstLookSummaries: result.triage.firstLookSummaries,
24
26
  }),
25
- ...(result.fix.editedSummaries.length > 0 && {
26
- editedSummaries: result.fix.editedSummaries,
27
+ ...(result.triage.editedSummaries.length > 0 && {
28
+ editedSummaries: result.triage.editedSummaries,
27
29
  }),
28
30
  };
29
31
  }
@@ -1,7 +1,7 @@
1
1
  import { renderShellCommand } from "../../cli/runner.mjs";
2
2
  import { loadConfig } from "../../config/load.mjs";
3
3
  import { playbookPointer } from "../playbook-pointer.mjs";
4
- const FIX_CODE_LOOP_PLAYBOOK = "Fix-code loop";
4
+ const TRIAGE_LOOP_PLAYBOOK = "Triage loop";
5
5
  /** The generic push stays separate from conflict and queue-recovery push instructions. */
6
6
  export function buildPushSteps(style, genericPush) {
7
7
  if (!genericPush)
@@ -9,6 +9,10 @@ export function buildPushSteps(style, genericPush) {
9
9
  const push = "Commit and push any changes.";
10
10
  if (style === "inline")
11
11
  return [push];
12
- const cli = renderShellCommand([...loadConfig().cliCommand, "playbook", FIX_CODE_LOOP_PLAYBOOK]);
13
- return [`${push} ${playbookPointer(FIX_CODE_LOOP_PLAYBOOK)} CLI: \`${cli}\`.`];
12
+ const cli = renderShellCommand([
13
+ ...loadConfig()["cli-command"],
14
+ "playbook",
15
+ TRIAGE_LOOP_PLAYBOOK,
16
+ ]);
17
+ return [`${push} ${playbookPointer(TRIAGE_LOOP_PLAYBOOK)} CLI: \`${cli}\`.`];
14
18
  }
@@ -1,6 +1,6 @@
1
1
  import type { IterateCommandOptions, IterateResult, IterateResultBase, Review, ShepherdReport } from "../../types.mts";
2
2
  import type { NormalizedBotUsernames } from "../../comments/authors.mts";
3
- interface HandleFixCodeContext {
3
+ interface HandleTriageContext {
4
4
  base: IterateResultBase;
5
5
  report: ShepherdReport;
6
6
  opts: IterateCommandOptions;
@@ -25,5 +25,5 @@ interface HandleFixCodeContext {
25
25
  /** Verified stack-repair guidance, when ancestry is stale. */
26
26
  repairInstructions?: string[];
27
27
  }
28
- export declare function handleFixCode(ctx: HandleFixCodeContext): Promise<IterateResult>;
28
+ export declare function handleTriage(ctx: HandleTriageContext): Promise<IterateResult>;
29
29
  export {};