@sideboard-ai/core 0.1.246 → 0.1.248

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 (48) hide show
  1. package/dist/{abletime-OI6FNSXX.js → abletime-GAPUN2LL.js} +4 -4
  2. package/dist/{abletime-CWIJ7INC.js → abletime-HTRIHTL5.js} +4 -4
  3. package/dist/{abletime-oauth-CHVTUZBR.js → abletime-oauth-G6ZPGVAE.js} +3 -3
  4. package/dist/{abletime-oauth-PUIPZTA4.js → abletime-oauth-ME7ZY2RS.js} +3 -3
  5. package/dist/{abletime-rest-32NIVXAY.js → abletime-rest-73EKIAZU.js} +3 -3
  6. package/dist/{abletime-rest-APJUKFKL.js → abletime-rest-M2D2NELV.js} +3 -3
  7. package/dist/{agents-G7F3BJNB.js → agents-3PQ2BWGB.js} +5 -5
  8. package/dist/{agents-47WI5IV2.js → agents-7SCJTTZN.js} +5 -5
  9. package/dist/{app-settings-VOPXJMGV.js → app-settings-2BHGANQH.js} +7 -1
  10. package/dist/{app-settings-652J57CX.js → app-settings-NKXH4PKM.js} +7 -1
  11. package/dist/{chunk-576S3HJ7.js → chunk-64NUGRZ3.js} +4 -4
  12. package/dist/{chunk-IMO7AZI4.js → chunk-6HIAYIXT.js} +2 -2
  13. package/dist/{chunk-WURF67ID.js → chunk-BEQE7VOE.js} +5 -5
  14. package/dist/{chunk-6I5YQTNK.js → chunk-CXTIOJRX.js} +12 -0
  15. package/dist/{chunk-RLNEKXXT.js → chunk-D3DYMGZS.js} +4 -4
  16. package/dist/{chunk-TLPJ44Y7.js → chunk-ERQYYL4I.js} +74 -23
  17. package/dist/{chunk-C64YQAA6.js → chunk-GFGSC4Z7.js} +3 -3
  18. package/dist/{chunk-43F44EKX.js → chunk-GVAR6R6R.js} +2 -2
  19. package/dist/{chunk-QFRX5S2E.js → chunk-KFXP4KSP.js} +143 -24
  20. package/dist/{chunk-G45QP2ZD.js → chunk-LPS6D346.js} +3 -3
  21. package/dist/{chunk-7HOKP4GR.js → chunk-PELMZRDB.js} +12 -0
  22. package/dist/{chunk-PPJ5JTWA.js → chunk-QVQPIFBV.js} +28 -2
  23. package/dist/{chunk-QNJXJIWJ.js → chunk-RF46WMSI.js} +5 -5
  24. package/dist/{chunk-GFRC6JQN.js → chunk-U2ZZMGPV.js} +4 -4
  25. package/dist/{chunk-HRWCW6LC.js → chunk-UVWIYSAA.js} +4 -4
  26. package/dist/{chunk-E6C5NR46.js → chunk-W4F7JKXF.js} +20 -6
  27. package/dist/{chunk-YLGBQVRK.js → chunk-XEBQRCDW.js} +28 -2
  28. package/dist/{chunk-5ZFULOTC.js → chunk-XM4UIFQU.js} +20 -6
  29. package/dist/{chunk-BL2UGKWU.js → chunk-Z7QWXE4W.js} +3 -3
  30. package/dist/{coordinator-prompt-ZBYRREHD.js → coordinator-prompt-BFO2TAVR.js} +4 -4
  31. package/dist/{coordinator-prompt-WQIICPT6.js → coordinator-prompt-IG676OSP.js} +4 -4
  32. package/dist/{global-workspace-3SQU4GL4.js → global-workspace-J6H7X5SM.js} +4 -4
  33. package/dist/{global-workspace-2N6KISDO.js → global-workspace-RLCICVQE.js} +4 -4
  34. package/dist/index.cjs +193 -14
  35. package/dist/index.d.cts +66 -2
  36. package/dist/index.d.ts +66 -2
  37. package/dist/index.js +27 -16
  38. package/dist/mcp/run-stdio.cjs +117 -14
  39. package/dist/mcp/run-stdio.js +17 -15
  40. package/dist/{orchestrator-DPMS5KMY.js → orchestrator-2NZUV4LI.js} +6 -6
  41. package/dist/{orchestrator-2QGJ7CW2.js → orchestrator-JCETTHVV.js} +6 -6
  42. package/dist/{thread-store-JQB7KZJR.js → thread-store-BEBZMOS7.js} +1 -1
  43. package/dist/{thread-store-SCV2IZYS.js → thread-store-S6PJADDM.js} +1 -1
  44. package/dist/{workspaces-QLKWW3O2.js → workspaces-NJF3GG5F.js} +4 -4
  45. package/dist/{workspaces-CFI7XVAE.js → workspaces-OLBW42V3.js} +4 -4
  46. package/dist/{worktree-PK3QETXO.js → worktree-2FYRYJTB.js} +3 -3
  47. package/dist/{worktree-4UAOZUJ4.js → worktree-UKLK7VHH.js} +3 -3
  48. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -20,7 +20,7 @@ import {
20
20
  parseAbleTimeOAuthCallbackUrl,
21
21
  resolveAbleTimeOAuthHost,
22
22
  startAbleTimeOAuth
23
- } from "./chunk-C64YQAA6.js";
23
+ } from "./chunk-GFGSC4Z7.js";
24
24
  import {
25
25
  ableTimeDependencyTarget,
26
26
  commentAbleTimeTask,
@@ -38,8 +38,8 @@ import {
38
38
  toAbleTimeIssueInfo,
39
39
  updateAbleTimeTask,
40
40
  verifyAbleTimeConnection
41
- } from "./chunk-G45QP2ZD.js";
42
- import "./chunk-43F44EKX.js";
41
+ } from "./chunk-LPS6D346.js";
42
+ import "./chunk-GVAR6R6R.js";
43
43
  import {
44
44
  ABLETIME_MCP_PATH,
45
45
  ABLETIME_MCP_PM_PATH,
@@ -60,7 +60,7 @@ import {
60
60
  normalizeAbleTimeCredential,
61
61
  normalizeAbleTimeHost,
62
62
  rewriteAbleTimeError
63
- } from "./chunk-QNJXJIWJ.js";
63
+ } from "./chunk-RF46WMSI.js";
64
64
  import {
65
65
  AGENT_GIT_ACTIONS,
66
66
  BOARD_COLUMN_DEFS,
@@ -125,6 +125,7 @@ import {
125
125
  captureTurnBaseline,
126
126
  claimDesktopHost,
127
127
  classifyWorktreeColumn,
128
+ classifyWorktreeListBadges,
128
129
  cleanupArchivedHistory,
129
130
  cleanupOrphanWorktrees,
130
131
  cloneRepoIntoSideboard,
@@ -294,6 +295,7 @@ import {
294
295
  resolveScheduleThreadId,
295
296
  resolveSendFollowUp,
296
297
  resolveSidebarGitPrompt,
298
+ reviewLabelForRepo,
297
299
  runArchiveScript,
298
300
  runConventionSetup,
299
301
  runSetupScript,
@@ -336,7 +338,7 @@ import {
336
338
  worktreeRunPortsPath,
337
339
  wrapReviewSkillMarkdown,
338
340
  writeWorktreeFile
339
- } from "./chunk-QFRX5S2E.js";
341
+ } from "./chunk-KFXP4KSP.js";
340
342
  import {
341
343
  LEGACY_PLAN_FILE_REL,
342
344
  PLAN_FILE_NAME,
@@ -474,7 +476,7 @@ import {
474
476
  withEventParentId,
475
477
  withEventsParentId,
476
478
  writeInjectedMcpConfig
477
- } from "./chunk-RLNEKXXT.js";
479
+ } from "./chunk-D3DYMGZS.js";
478
480
  import {
479
481
  CLOUD_COORDINATOR_BUSY_REPLY,
480
482
  CLOUD_COORDINATOR_CANCELED_REPLY,
@@ -520,7 +522,7 @@ import {
520
522
  stageBuffersAsAttachments,
521
523
  syncWorkspacesFromThreads,
522
524
  takenTeamSlugsForOrchestration
523
- } from "./chunk-GFRC6JQN.js";
525
+ } from "./chunk-U2ZZMGPV.js";
524
526
  import {
525
527
  FAMOUS_SOCCER_TEAMS,
526
528
  GITHUB_PR_BODY_MAX_CHARS,
@@ -619,7 +621,7 @@ import {
619
621
  worktreeDisplayLabelForGroup,
620
622
  worktreeNameFromPath,
621
623
  worktreeSlugForTicket
622
- } from "./chunk-E6C5NR46.js";
624
+ } from "./chunk-W4F7JKXF.js";
623
625
  import {
624
626
  ATTACHMENTS_DIR,
625
627
  CLI_DIR,
@@ -688,6 +690,7 @@ import {
688
690
  ISSUE_SOURCE_LABELS,
689
691
  ORCHESTRATOR_AGENT_KINDS,
690
692
  PROFILE_NOTES_MAX,
693
+ REVIEW_LABEL_MAX,
691
694
  USAGE_ON_LIMIT_VALUES,
692
695
  agentDoneSound,
693
696
  appSettingsPath,
@@ -755,6 +758,7 @@ import {
755
758
  loadAppSettings,
756
759
  maxConcurrentAgents,
757
760
  mergeUsage,
761
+ normalizeReviewLabel,
758
762
  orchestrationQuotaFallbackAgent,
759
763
  orchestrationQuotaOnLimit,
760
764
  persistVaultKeyInKeychain,
@@ -772,6 +776,7 @@ import {
772
776
  resolveNewOrchestratorOptions,
773
777
  resolveNewThreadOptions,
774
778
  resolveOrchestratorDefaults,
779
+ resolveProjectReviewLabel,
775
780
  resolveThreadDefaults,
776
781
  resolveUsageOnLimit,
777
782
  resolveVaultKey,
@@ -801,7 +806,7 @@ import {
801
806
  usageOnLimit,
802
807
  writeSecureJson,
803
808
  writeViewerContext
804
- } from "./chunk-PPJ5JTWA.js";
809
+ } from "./chunk-QVQPIFBV.js";
805
810
  import {
806
811
  examplePrefixedBranch,
807
812
  resolveGitBranchPrefix,
@@ -834,7 +839,7 @@ import {
834
839
  updateThread,
835
840
  withThreadLock,
836
841
  writeThread
837
- } from "./chunk-6I5YQTNK.js";
842
+ } from "./chunk-CXTIOJRX.js";
838
843
  import "./chunk-224IXQOM.js";
839
844
  import {
840
845
  THINKING_EFFORTS,
@@ -3962,7 +3967,7 @@ async function continueSourceThread(threadId, prompt) {
3962
3967
  await continueOnReply(threadId, prompt);
3963
3968
  return;
3964
3969
  }
3965
- const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-2QGJ7CW2.js");
3970
+ const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-JCETTHVV.js");
3966
3971
  await getOrchestrator2().send(threadId, prompt);
3967
3972
  } catch {
3968
3973
  }
@@ -6077,7 +6082,7 @@ async function startMcpServer() {
6077
6082
  );
6078
6083
  }
6079
6084
  try {
6080
- const { maxConcurrentAgents: maxConcurrentAgents2 } = await import("./app-settings-VOPXJMGV.js");
6085
+ const { maxConcurrentAgents: maxConcurrentAgents2 } = await import("./app-settings-2BHGANQH.js");
6081
6086
  orch.setMaxConcurrent(maxConcurrentAgents2());
6082
6087
  } catch {
6083
6088
  }
@@ -6572,7 +6577,7 @@ async function startMcpServer() {
6572
6577
  registerConnectedIssueVendorTools(server);
6573
6578
  registerScheduleTools(server);
6574
6579
  const { getCaffeinateHold: getCaffeinateHold2, setCaffeinateHold: setCaffeinateHold2 } = await import("./caffeinate-hold-PXHGH7ZN.js");
6575
- const { resolveNewThreadOptions: resolveNewThreadOptions2, resolveThreadDefaults: resolveThreadDefaults2 } = await import("./app-settings-VOPXJMGV.js");
6580
+ const { resolveNewThreadOptions: resolveNewThreadOptions2, resolveThreadDefaults: resolveThreadDefaults2 } = await import("./app-settings-2BHGANQH.js");
6576
6581
  const accountDefaults = resolveThreadDefaults2();
6577
6582
  const accountDefaultsHint = `Account defaults: agent=${accountDefaults.agent}, model=${accountDefaults.model?.trim() || "Auto"}, effort=${accountDefaults.effort}`;
6578
6583
  server.tool(
@@ -7122,12 +7127,12 @@ async function startMcpServer() {
7122
7127
  );
7123
7128
  server.tool(
7124
7129
  "list_prs",
7125
- 'List GitHub PRs for a registered workspace (the review surface for assigned ticket work \u2014 not the tickets). Pass repoPath from list_workspaces. "Get me N tickets to review" \u2192 queue=review and limit=N: open non-draft PRs labeled eng-review with no individual user reviewer. Prefer teams that match Settings \u2192 Agents / Projects roles for this repo. A team like engineering-team is not a claim (you are on that team). Also: state (open|closed|merged|all|review), label, reviewer (me|unassigned|login), query, limit (default 40, max 250). Then create_thread with sourceType=pr.',
7130
+ `List GitHub PRs for a registered workspace (the review surface for assigned ticket work \u2014 not the tickets). Pass repoPath from list_workspaces. "Get me N tickets to review" \u2192 queue=review and limit=N: open non-draft PRs labeled with this project's ready-for-review GitHub label (Settings \u2192 Projects; default eng-review) with no individual user reviewer. Prefer teams that match Settings \u2192 Agents / Projects roles for this repo. A team like engineering-team is not a claim (you are on that team). Also: state (open|closed|merged|all|review), label, reviewer (me|unassigned|login), query, limit (default 40, max 250). Then create_thread with sourceType=pr.`,
7126
7131
  {
7127
7132
  repoPath: z9.string(),
7128
7133
  query: z9.string().optional().describe("GitHub search tokens (title, draft:true, \u2026)"),
7129
7134
  queue: z9.enum(["review", "mine", "approved", "changes"]).optional().describe(
7130
- 'review = unclaimed eng-review inbox (use for "get me N tickets to review"). mine = review-requested:@me. approved / changes = eng-approved / eng-requested-changes.'
7135
+ "review = unclaimed ready-for-review inbox (Settings \u2192 Projects label, default eng-review). mine = review-requested:@me. approved / changes = eng-approved / eng-requested-changes."
7131
7136
  ),
7132
7137
  state: z9.enum(["open", "closed", "merged", "all", "review"]).optional().describe("GitHub PR state (default open). review is an alias for queue=review."),
7133
7138
  label: z9.string().optional().describe(
@@ -7147,7 +7152,8 @@ async function startMcpServer() {
7147
7152
  state,
7148
7153
  labels: label,
7149
7154
  reviewer,
7150
- limit: page + 1
7155
+ limit: page + 1,
7156
+ reviewLabel: resolveProjectReviewLabel(loadAppSettings(), root)
7151
7157
  });
7152
7158
  const prs = await listPrs(root, resolved);
7153
7159
  const windowed = applyIssueListWindow(prs, page);
@@ -9646,6 +9652,7 @@ export {
9646
9652
  PR_DETAILS_JSON_FIELDS,
9647
9653
  REPO_REVIEW_NAME,
9648
9654
  REPO_REVIEW_PATH,
9655
+ REVIEW_LABEL_MAX,
9649
9656
  REVIEW_REQUEST_NAME,
9650
9657
  REVIEW_REQUEST_PATH,
9651
9658
  REVIEW_REQUEST_PREFILL,
@@ -9777,6 +9784,7 @@ export {
9777
9784
  clampHistoryMaxDays,
9778
9785
  classifyRunScriptPreview,
9779
9786
  classifyWorktreeColumn,
9787
+ classifyWorktreeListBadges,
9780
9788
  claudeAdapter,
9781
9789
  claudeChromeEnabled,
9782
9790
  claudeUsageOverLimitWindows,
@@ -10217,6 +10225,7 @@ export {
10217
10225
  normalizeCodeSelection,
10218
10226
  normalizeLinearRelationType,
10219
10227
  normalizeParseResult,
10228
+ normalizeReviewLabel,
10220
10229
  normalizeServiceOrigin,
10221
10230
  normalizeThinkingEffort,
10222
10231
  normalizeThread,
@@ -10344,6 +10353,7 @@ export {
10344
10353
  resolvePlanMarkdown,
10345
10354
  resolvePrSelector,
10346
10355
  resolvePrSelectors,
10356
+ resolveProjectReviewLabel,
10347
10357
  resolveQuotaFallbackAgent,
10348
10358
  resolveRepoRoot,
10349
10359
  resolveReviewGuidelines,
@@ -10358,6 +10368,7 @@ export {
10358
10368
  resolveViewerProfile,
10359
10369
  resolveViewerProfileForRepo,
10360
10370
  resolveWorktreeStartPoint,
10371
+ reviewLabelForRepo,
10361
10372
  rewriteAbleTimeError,
10362
10373
  rewriteLinearError,
10363
10374
  run,
@@ -1651,6 +1651,12 @@ function normalizeThread(raw) {
1651
1651
  prTitle: raw.prTitle ?? null,
1652
1652
  prState: raw.prState ?? null,
1653
1653
  prIsDraft: Boolean(raw.prIsDraft),
1654
+ prReviewDecision: raw.prReviewDecision ?? null,
1655
+ prMergeable: raw.prMergeable ?? null,
1656
+ prMergeStateStatus: raw.prMergeStateStatus ?? null,
1657
+ prIsInMergeQueue: Boolean(raw.prIsInMergeQueue),
1658
+ prLabels: Array.isArray(raw.prLabels) ? raw.prLabels : [],
1659
+ prChecksFailed: typeof raw.prChecksFailed === "boolean" ? raw.prChecksFailed : void 0,
1654
1660
  skipAutoArchiveOnMerge: Boolean(raw.skipAutoArchiveOnMerge),
1655
1661
  cowboy: Boolean(raw.cowboy),
1656
1662
  stackId: raw.stackId ?? null,
@@ -1686,6 +1692,12 @@ function createEmptyThread(partial) {
1686
1692
  prIsDraft: Boolean(partial.prIsDraft),
1687
1693
  prAuthorLogin: partial.prAuthorLogin?.trim() || null,
1688
1694
  prReviewerLogins: partial.prReviewerLogins ?? [],
1695
+ prReviewDecision: partial.prReviewDecision ?? null,
1696
+ prMergeable: partial.prMergeable ?? null,
1697
+ prMergeStateStatus: partial.prMergeStateStatus ?? null,
1698
+ prIsInMergeQueue: Boolean(partial.prIsInMergeQueue),
1699
+ prLabels: partial.prLabels ?? [],
1700
+ prChecksFailed: partial.prChecksFailed,
1689
1701
  skipAutoArchiveOnMerge: partial.skipAutoArchiveOnMerge ?? false,
1690
1702
  cowboy: Boolean(partial.cowboy),
1691
1703
  stackId: partial.stackId ?? null,
@@ -3526,6 +3538,7 @@ __export(app_settings_exports, {
3526
3538
  HARNESS_ENV_KEYS: () => HARNESS_ENV_KEYS,
3527
3539
  ISSUE_SOURCE_LABELS: () => ISSUE_SOURCE_LABELS,
3528
3540
  PROFILE_NOTES_MAX: () => PROFILE_NOTES_MAX,
3541
+ REVIEW_LABEL_MAX: () => REVIEW_LABEL_MAX,
3529
3542
  USAGE_ON_LIMIT_VALUES: () => USAGE_ON_LIMIT_VALUES,
3530
3543
  agentDoneSound: () => agentDoneSound,
3531
3544
  appSettingsPath: () => appSettingsPath,
@@ -3582,6 +3595,7 @@ __export(app_settings_exports, {
3582
3595
  issueSourceLabel: () => issueSourceLabel,
3583
3596
  loadAppSettings: () => loadAppSettings,
3584
3597
  maxConcurrentAgents: () => maxConcurrentAgents,
3598
+ normalizeReviewLabel: () => normalizeReviewLabel,
3585
3599
  orchestrationQuotaFallbackAgent: () => orchestrationQuotaFallbackAgent,
3586
3600
  orchestrationQuotaOnLimit: () => orchestrationQuotaOnLimit,
3587
3601
  readViewerContext: () => readViewerContext,
@@ -3593,6 +3607,7 @@ __export(app_settings_exports, {
3593
3607
  resolveNewOrchestratorOptions: () => resolveNewOrchestratorOptions,
3594
3608
  resolveNewThreadOptions: () => resolveNewThreadOptions,
3595
3609
  resolveOrchestratorDefaults: () => resolveOrchestratorDefaults,
3610
+ resolveProjectReviewLabel: () => resolveProjectReviewLabel,
3596
3611
  resolveThreadDefaults: () => resolveThreadDefaults,
3597
3612
  resolveUsageOnLimit: () => resolveUsageOnLimit,
3598
3613
  resolveViewerProfile: () => resolveViewerProfile,
@@ -3925,13 +3940,25 @@ function normalizeDefaults(raw) {
3925
3940
  function profileRepoKey(path) {
3926
3941
  return path.trim().replace(/\/+$/, "");
3927
3942
  }
3943
+ function normalizeReviewLabel(value) {
3944
+ const label = (value ?? "").trim().replace(/^:+/, "").slice(0, REVIEW_LABEL_MAX);
3945
+ if (!label || /[,|]/.test(label)) return "";
3946
+ return label;
3947
+ }
3948
+ function projectProfileHasFields(profile) {
3949
+ return Boolean(profile.notes || profile.reviewLabel);
3950
+ }
3928
3951
  function normalizeProjectProfile(raw) {
3929
3952
  if (!raw || typeof raw !== "object") return void 0;
3930
3953
  const source = raw;
3931
3954
  const out = {};
3932
3955
  const notes = foldLegacyRolesIntoNotes(source.roles, source.role, source.notes);
3933
3956
  if (notes) out.notes = notes;
3934
- return out.notes ? out : void 0;
3957
+ const reviewLabel = normalizeReviewLabel(
3958
+ typeof source.reviewLabel === "string" ? source.reviewLabel : null
3959
+ );
3960
+ if (reviewLabel) out.reviewLabel = reviewLabel;
3961
+ return projectProfileHasFields(out) ? out : void 0;
3935
3962
  }
3936
3963
  function normalizeProjects(raw) {
3937
3964
  if (!raw || typeof raw !== "object" || Array.isArray(raw)) return {};
@@ -4604,12 +4631,22 @@ function updateProjectProfileSettings(repoPath, patch) {
4604
4631
  if (!notes) delete next.notes;
4605
4632
  else next.notes = notes;
4606
4633
  }
4634
+ if ("reviewLabel" in patch) {
4635
+ const reviewLabel = normalizeReviewLabel(patch.reviewLabel);
4636
+ if (!reviewLabel) delete next.reviewLabel;
4637
+ else next.reviewLabel = reviewLabel;
4638
+ }
4607
4639
  delete next.roles;
4608
4640
  delete next.role;
4609
- if (!next.notes) delete projects[key];
4641
+ if (!projectProfileHasFields(next)) delete projects[key];
4610
4642
  else projects[key] = next;
4611
4643
  return saveAppSettings({ ...current, projects });
4612
4644
  }
4645
+ function resolveProjectReviewLabel(settings, repoPath) {
4646
+ const key = findProjectProfileKey(settings.projects, repoPath);
4647
+ if (!key) return "";
4648
+ return settings.projects[key]?.reviewLabel?.trim() || "";
4649
+ }
4613
4650
  function getDefaultAgent(settings = loadAppSettings()) {
4614
4651
  return settings.defaults.agent ?? "claude";
4615
4652
  }
@@ -5134,7 +5171,7 @@ function childEnvWithAppSettings(extra) {
5134
5171
  function harnessEnvKey(harness) {
5135
5172
  return HARNESS_ENV_KEYS[harness];
5136
5173
  }
5137
- var import_node_crypto3, import_node_fs14, import_node_os5, import_node_path16, HARNESS_ENV_KEYS, DEFAULT_AGENTS, GITHUB_GIT_AUTH_MODES, FOLLOW_UP_BEHAVIORS, AGENT_DONE_SOUNDS, CLOUD_CONNECT_AGENTS, ISSUE_SOURCES, GIT_AUTH_MODES, EMPTY_SETTINGS, CONFIRM_ACCOUNT, CONFIRM_PROJECT, DEFAULT_CLI_BIN;
5174
+ var import_node_crypto3, import_node_fs14, import_node_os5, import_node_path16, HARNESS_ENV_KEYS, DEFAULT_AGENTS, GITHUB_GIT_AUTH_MODES, FOLLOW_UP_BEHAVIORS, AGENT_DONE_SOUNDS, CLOUD_CONNECT_AGENTS, ISSUE_SOURCES, GIT_AUTH_MODES, REVIEW_LABEL_MAX, EMPTY_SETTINGS, CONFIRM_ACCOUNT, CONFIRM_PROJECT, DEFAULT_CLI_BIN;
5138
5175
  var init_app_settings = __esm({
5139
5176
  "src/store/app-settings.ts"() {
5140
5177
  "use strict";
@@ -5191,6 +5228,7 @@ var init_app_settings = __esm({
5191
5228
  ]);
5192
5229
  ISSUE_SOURCES = /* @__PURE__ */ new Set(["linear", "github", "abletime"]);
5193
5230
  GIT_AUTH_MODES = new Set(GITHUB_GIT_AUTH_MODES);
5231
+ REVIEW_LABEL_MAX = 50;
5194
5232
  EMPTY_SETTINGS = {
5195
5233
  environment: {},
5196
5234
  claude: {},
@@ -5445,6 +5483,10 @@ function normalizePrListQueue(queue, state) {
5445
5483
  }
5446
5484
  return void 0;
5447
5485
  }
5486
+ function reviewQueueLabel(reviewLabel) {
5487
+ const label = (reviewLabel ?? "").trim();
5488
+ return label || QUEUE_DEFAULTS.review.labels[0];
5489
+ }
5448
5490
  function ticketRefsFromPrTitle(title) {
5449
5491
  const out = [];
5450
5492
  const seen = /* @__PURE__ */ new Set();
@@ -5462,10 +5504,12 @@ function resolveListPrsOptions(opts) {
5462
5504
  const defaults = queue ? QUEUE_DEFAULTS[queue] : void 0;
5463
5505
  const stateIsQueueAlias = Boolean(normalizePrListQueue(void 0, opts?.state));
5464
5506
  const labels = normalizePrLabels(opts?.labels);
5507
+ const readyLabel = reviewQueueLabel(opts?.reviewLabel);
5508
+ const queueLabels = queue === "review" || queue === "mine" ? [readyLabel] : defaults?.labels ?? [];
5465
5509
  return {
5466
5510
  ...queue ? { queue } : {},
5467
5511
  state: normalizePrListState(stateIsQueueAlias ? defaults?.state : opts?.state ?? defaults?.state),
5468
- labels: labels.length ? labels : defaults?.labels ?? [],
5512
+ labels: labels.length ? labels : queueLabels,
5469
5513
  ...opts?.reviewer?.trim() ? { reviewer: opts.reviewer.trim() } : defaults?.reviewer ? { reviewer: defaults.reviewer } : {},
5470
5514
  ...opts?.query?.trim() ? { query: opts.query.trim() } : {},
5471
5515
  ...opts?.draft !== void 0 ? { draft: opts.draft } : defaults?.draft !== void 0 ? { draft: defaults.draft } : {},
@@ -5826,6 +5870,12 @@ function prIsInMergeQueue(gate) {
5826
5870
  if (gate.isInMergeQueue) return true;
5827
5871
  return (gate.mergeStateStatus ?? "").toUpperCase() === "QUEUED";
5828
5872
  }
5873
+ function ciChecksFailed(checks) {
5874
+ if (!checks?.length) return false;
5875
+ return checks.some(
5876
+ (check) => (!check.kind || check.kind === "ci") && check.bucket === "fail"
5877
+ );
5878
+ }
5829
5879
  function buildMergeGateChecks(gate, opts = {}) {
5830
5880
  const rows = [];
5831
5881
  const base = gate.baseRefName?.trim() || "the base branch";
@@ -6729,7 +6779,7 @@ async function getPrMeta(cwd, selector) {
6729
6779
  "view",
6730
6780
  selector,
6731
6781
  "--json",
6732
- "number,title,url,state,isDraft,reviewDecision,baseRefName,headRefName,isInMergeQueue,mergeStateStatus,mergeable,author,reviewRequests"
6782
+ "number,title,url,state,isDraft,reviewDecision,baseRefName,headRefName,isInMergeQueue,mergeStateStatus,mergeable,author,reviewRequests,labels"
6733
6783
  ];
6734
6784
  if (slug) viewArgs.push("--repo", slug);
6735
6785
  let { stdout, exitCode, stderr } = await gh(viewArgs, cwd, { reject: false });
@@ -6739,7 +6789,7 @@ async function getPrMeta(cwd, selector) {
6739
6789
  "view",
6740
6790
  selector,
6741
6791
  "--json",
6742
- "number,title,url,state,isDraft,reviewDecision,baseRefName,headRefName,mergeStateStatus,mergeable,author,reviewRequests"
6792
+ "number,title,url,state,isDraft,reviewDecision,baseRefName,headRefName,mergeStateStatus,mergeable,author,reviewRequests,labels"
6743
6793
  ];
6744
6794
  if (slug) retry.push("--repo", slug);
6745
6795
  ({ stdout, exitCode, stderr } = await gh(retry, cwd, { reject: false }));
@@ -6774,7 +6824,8 @@ async function getPrMeta(cwd, selector) {
6774
6824
  mergeable: resolved.mergeable,
6775
6825
  mergeStateStatus: resolved.mergeStateStatus,
6776
6826
  authorLogin: author.login?.trim() || null,
6777
- reviewerLogins: humanReviewerLogins(view.reviewRequests)
6827
+ reviewerLogins: humanReviewerLogins(view.reviewRequests),
6828
+ labels: labelNames(view.labels)
6778
6829
  };
6779
6830
  } catch {
6780
6831
  return null;
@@ -8279,7 +8330,7 @@ var init_coordinator_prompt = __esm({
8279
8330
  "Discover:",
8280
8331
  "- list_workspaces \u2014 registered repos (path + github slug + project context when set). Use account / project context to pick the right repo for tickets or reviews.",
8281
8332
  "- list_board \u2014 Home Kanban of worktrees (New / Draft / Review / Merged; one card per checkout). Path to merge: no PR \u2192 draft PR \u2192 open PR \u2192 merged. Archive removes the card to Settings \u2192 History. Queued/running are activity on the card, not columns. Orchestration chats are not on the board. Filters: query, repoPath, kind, column, limit.",
8282
- '- list_branches / list_prs / list_issues \u2014 pass repoPath from list_workspaces. Review is PRs (the surface for assigned ticket work), not the tickets: "Get me N tickets to review" \u2192 list_prs(queue=review, limit=N) then create_thread sourceType=pr. That is open non-draft PRs labeled eng-review with no individual user reviewer yet. A team request (engineering-team) is not a claim \u2014 the viewer is on that team and can pick it up; claimed means an individual account is the reviewer. Bots ignored. Use Settings \u2192 Agents / Projects context (roles, teams, labels \u2014 freeform text; project adds to account) to prefer the right queues. queue=mine is review-requested:@me; queue=approved|changes uses those labels. Also: state, label, reviewer=me|unassigned|login, query, limit default 40 max 250; raise limit or tighten when truncated. list_issues (query, assignee=me|unassigned|all|user, limit default 40 max 250) lists Linear, AbleTime, or GitHub tickets \u2014 do not use it for that review-inbox ask. When they ask for tickets to work on, follow their context (assignee=me or unassigned as it says).',
8333
+ `- list_branches / list_prs / list_issues \u2014 pass repoPath from list_workspaces. Review is PRs (the surface for assigned ticket work), not the tickets: "Get me N tickets to review" \u2192 list_prs(queue=review, limit=N) then create_thread sourceType=pr. That is open non-draft PRs labeled with this project's ready-for-review GitHub label (Settings \u2192 Projects; default eng-review) with no individual user reviewer yet. A team request (engineering-team) is not a claim \u2014 the viewer is on that team and can pick it up; claimed means an individual account is the reviewer. Bots ignored. Use Settings \u2192 Agents / Projects context (roles, teams, labels \u2014 freeform text; project adds to account) to prefer the right queues. queue=mine is review-requested:@me; queue=approved|changes uses those labels. Also: state, label, reviewer=me|unassigned|login, query, limit default 40 max 250; raise limit or tighten when truncated. list_issues (query, assignee=me|unassigned|all|user, limit default 40 max 250) lists Linear, AbleTime, or GitHub tickets \u2014 do not use it for that review-inbox ask. When they ask for tickets to work on, follow their context (assignee=me or unassigned as it says).`,
8283
8334
  "- Find work: when they ask to find work, pick up tickets, or list reviews, use Settings \u2192 Agents (account) plus Settings \u2192 Projects (per-repo) context. Tickets \u2192 Sideboard list_issues / linear_* (Account Linear). Reviews \u2192 list_prs(queue=review). Do not call Claude Linear MCP or any other vendor Linear MCP \u2014 those HTTP connectors hang or flap on the first turn. If a vendor MCP is down or reconnecting, ignore it and keep going with Sideboard tools. Show the options \u2014 do not create_thread or start unless they also asked to start (e.g. \u201Cfind me work and start it\u201D). Do not start this unprompted. To change that context, show the proposed text, ask_user (Save this context / Do not save), wait, then update_viewer_context with confirmed=true. Never write it without confirmation.",
8284
8335
  "- Ticket updates: list_issues / linear_search_issues / github_search_issues with updatedSince (yesterday, 2d, or ISO). One call returns new assignments, ticket edits, and new comments \u2014 do not get_issue every ticket just to check for comments. kind=created vs updated distinguishes new tickets from existing ones.",
8285
8336
  "- linear_* (when Linear is connected) \u2014 list_teams for team key/states; get/create/update/comment with ENG-123. Worktree agents have the same Account tools \u2014 prefer they comment, update status, and create spin-offs (parent=) on their own ticket when they were asked to do the work. When reviewing a PR or ticket, do not comment or update until the user types a next step \u2014 they should work through the feedback in chat first. Do not tell the child to ask_user after the review. Scope errors: reconnect Linear in Account settings. Prefer these over any Linear MCP the CLI may still list.",
@@ -13727,11 +13778,41 @@ function threadPrMetaPatch(thread, meta) {
13727
13778
  if (!sameLoginList(nextReviewers, thread.prReviewerLogins)) {
13728
13779
  patch.prReviewerLogins = nextReviewers;
13729
13780
  }
13781
+ const nextDecision = meta.reviewDecision ?? null;
13782
+ if ((thread.prReviewDecision ?? null) !== nextDecision) {
13783
+ patch.prReviewDecision = nextDecision;
13784
+ }
13785
+ const nextMergeable = meta.mergeable ?? null;
13786
+ if ((thread.prMergeable ?? null) !== nextMergeable) {
13787
+ patch.prMergeable = nextMergeable;
13788
+ }
13789
+ const nextMergeState = meta.mergeStateStatus ?? null;
13790
+ if ((thread.prMergeStateStatus ?? null) !== nextMergeState) {
13791
+ patch.prMergeStateStatus = nextMergeState;
13792
+ }
13793
+ const nextQueued = Boolean(meta.isInMergeQueue);
13794
+ if (Boolean(thread.prIsInMergeQueue) !== nextQueued) {
13795
+ patch.prIsInMergeQueue = nextQueued;
13796
+ }
13797
+ const nextLabels = meta.labels ?? [];
13798
+ if (!sameLoginList(nextLabels, thread.prLabels)) {
13799
+ patch.prLabels = nextLabels;
13800
+ }
13801
+ const mergeState = (nextMergeState ?? "").toUpperCase();
13802
+ if (mergeState === "CLEAN" && thread.prChecksFailed) {
13803
+ patch.prChecksFailed = false;
13804
+ } else if ((mergeState === "UNSTABLE" || mergeState === "BLOCKED" && (nextDecision ?? "").toUpperCase() === "APPROVED") && !thread.prChecksFailed) {
13805
+ patch.prChecksFailed = true;
13806
+ }
13730
13807
  if (thread.skipAutoArchiveOnMerge && nextState && nextState !== "MERGED" && nextState !== "CLOSED") {
13731
13808
  patch.skipAutoArchiveOnMerge = false;
13732
13809
  }
13733
13810
  return patch;
13734
13811
  }
13812
+ function threadPrChecksFailedPatch(thread, failed) {
13813
+ if (thread.prChecksFailed === failed) return {};
13814
+ return { prChecksFailed: failed };
13815
+ }
13735
13816
  function shouldAutoArchiveOnPrMerge(opts) {
13736
13817
  if (!opts.autoArchiveEnabled) return false;
13737
13818
  if (opts.isGlobal) return false;
@@ -14310,6 +14391,12 @@ function worktreeBindingFrom(from) {
14310
14391
  prIsDraft: from.prIsDraft,
14311
14392
  prAuthorLogin: from.prAuthorLogin,
14312
14393
  prReviewerLogins: from.prReviewerLogins,
14394
+ prReviewDecision: from.prReviewDecision,
14395
+ prMergeable: from.prMergeable,
14396
+ prMergeStateStatus: from.prMergeStateStatus,
14397
+ prIsInMergeQueue: from.prIsInMergeQueue,
14398
+ prLabels: from.prLabels,
14399
+ prChecksFailed: from.prChecksFailed,
14313
14400
  skipAutoArchiveOnMerge: from.skipAutoArchiveOnMerge,
14314
14401
  stackId: from.stackId,
14315
14402
  stackLayer: from.stackLayer,
@@ -18585,6 +18672,7 @@ async function createThread(input, _onSetupLine) {
18585
18672
  let prUrl = null;
18586
18673
  let prTitle = null;
18587
18674
  let prAuthorLogin2 = null;
18675
+ let prLabels = [];
18588
18676
  if (sourceType === "pr") {
18589
18677
  const num2 = Number(input.sourceRef.replace(/^#/, ""));
18590
18678
  if (!Number.isFinite(num2)) throw new Error(`Invalid PR number: ${input.sourceRef}`);
@@ -18601,6 +18689,7 @@ async function createThread(input, _onSetupLine) {
18601
18689
  sourceIsFork = pr.isCrossRepository;
18602
18690
  prUrl = pr.url;
18603
18691
  prAuthorLogin2 = pr.author?.login?.trim() || null;
18692
+ prLabels = pr.labels ?? [];
18604
18693
  const localFetchBranch = `sideboard-pr-${pr.number}`;
18605
18694
  await fetchPrHead(repoPath, pr.number, localFetchBranch);
18606
18695
  sourceRef = localFetchBranch;
@@ -18624,6 +18713,7 @@ async function createThread(input, _onSetupLine) {
18624
18713
  prUrl = existing.url;
18625
18714
  prTitle = existing.title;
18626
18715
  prAuthorLogin2 = existing.author?.login?.trim() || null;
18716
+ prLabels = existing.labels ?? [];
18627
18717
  }
18628
18718
  }
18629
18719
  }
@@ -18659,7 +18749,8 @@ async function createThread(input, _onSetupLine) {
18659
18749
  status: "idle",
18660
18750
  prUrl,
18661
18751
  prTitle,
18662
- prAuthorLogin: prAuthorLogin2
18752
+ prAuthorLogin: prAuthorLogin2,
18753
+ prLabels
18663
18754
  });
18664
18755
  writeThread(thread);
18665
18756
  await ensureWorkspace(repoPath);
@@ -22438,6 +22529,7 @@ var init_orchestrator = __esm({
22438
22529
  init_stack();
22439
22530
  init_agent_git_actions();
22440
22531
  init_pr_merge_archive();
22532
+ init_pr_gates();
22441
22533
  init_conductor();
22442
22534
  init_dev_preview();
22443
22535
  init_setup_log();
@@ -24634,10 +24726,20 @@ var init_orchestrator = __esm({
24634
24726
  return { thread, selectors: connectedPrSelectors(thread, headUrl), cwd, headUrl };
24635
24727
  }
24636
24728
  async getPrChecks(threadRef) {
24637
- const { selectors, cwd } = await this.withPrSelector(threadRef);
24729
+ const { thread, selectors, cwd } = await this.withPrSelector(threadRef);
24638
24730
  for (const selector of selectors) {
24639
24731
  const checks = await getPrChecks(cwd, selector);
24640
- if (checks) return checks;
24732
+ if (!checks) continue;
24733
+ const live = this.requireThread(thread.id);
24734
+ const failed = ciChecksFailed(checks);
24735
+ const siblings = threadsSharingWorktree(live.worktreePath);
24736
+ const targets = siblings.length > 0 ? siblings : [live];
24737
+ for (const t of targets) {
24738
+ const patch = threadPrChecksFailedPatch(t, failed);
24739
+ if (Object.keys(patch).length === 0) continue;
24740
+ updateThread(t.id, patch);
24741
+ }
24742
+ return checks;
24641
24743
  }
24642
24744
  return null;
24643
24745
  }
@@ -30546,12 +30648,12 @@ async function startMcpServer() {
30546
30648
  );
30547
30649
  server.tool(
30548
30650
  "list_prs",
30549
- 'List GitHub PRs for a registered workspace (the review surface for assigned ticket work \u2014 not the tickets). Pass repoPath from list_workspaces. "Get me N tickets to review" \u2192 queue=review and limit=N: open non-draft PRs labeled eng-review with no individual user reviewer. Prefer teams that match Settings \u2192 Agents / Projects roles for this repo. A team like engineering-team is not a claim (you are on that team). Also: state (open|closed|merged|all|review), label, reviewer (me|unassigned|login), query, limit (default 40, max 250). Then create_thread with sourceType=pr.',
30651
+ `List GitHub PRs for a registered workspace (the review surface for assigned ticket work \u2014 not the tickets). Pass repoPath from list_workspaces. "Get me N tickets to review" \u2192 queue=review and limit=N: open non-draft PRs labeled with this project's ready-for-review GitHub label (Settings \u2192 Projects; default eng-review) with no individual user reviewer. Prefer teams that match Settings \u2192 Agents / Projects roles for this repo. A team like engineering-team is not a claim (you are on that team). Also: state (open|closed|merged|all|review), label, reviewer (me|unassigned|login), query, limit (default 40, max 250). Then create_thread with sourceType=pr.`,
30550
30652
  {
30551
30653
  repoPath: import_zod9.z.string(),
30552
30654
  query: import_zod9.z.string().optional().describe("GitHub search tokens (title, draft:true, \u2026)"),
30553
30655
  queue: import_zod9.z.enum(["review", "mine", "approved", "changes"]).optional().describe(
30554
- 'review = unclaimed eng-review inbox (use for "get me N tickets to review"). mine = review-requested:@me. approved / changes = eng-approved / eng-requested-changes.'
30656
+ "review = unclaimed ready-for-review inbox (Settings \u2192 Projects label, default eng-review). mine = review-requested:@me. approved / changes = eng-approved / eng-requested-changes."
30555
30657
  ),
30556
30658
  state: import_zod9.z.enum(["open", "closed", "merged", "all", "review"]).optional().describe("GitHub PR state (default open). review is an alias for queue=review."),
30557
30659
  label: import_zod9.z.string().optional().describe(
@@ -30571,7 +30673,8 @@ async function startMcpServer() {
30571
30673
  state,
30572
30674
  labels: label,
30573
30675
  reviewer,
30574
- limit: page + 1
30676
+ limit: page + 1,
30677
+ reviewLabel: resolveProjectReviewLabel(loadAppSettings(), root)
30575
30678
  });
30576
30679
  const prs = await listPrs(root, resolved);
30577
30680
  const windowed = applyIssueListWindow(prs, page);
@@ -11,7 +11,7 @@ import {
11
11
  searchAbleTimeTasks,
12
12
  toAbleTimeIssueInfo,
13
13
  updateAbleTimeTask
14
- } from "../chunk-BL2UGKWU.js";
14
+ } from "../chunk-Z7QWXE4W.js";
15
15
  import {
16
16
  AGENT_GIT_ACTIONS,
17
17
  BOARD_COLUMN_DEFS,
@@ -49,7 +49,7 @@ import {
49
49
  threadsSharingWorktree,
50
50
  updateSchedule,
51
51
  waitForDetachedJob
52
- } from "../chunk-TLPJ44Y7.js";
52
+ } from "../chunk-ERQYYL4I.js";
53
53
  import {
54
54
  PRESENT_PLAN_REQUIRES_PLAN_MODE,
55
55
  PRESENT_PLAN_TOOL_DESCRIPTION,
@@ -66,17 +66,17 @@ import {
66
66
  materializeSystemCaBundle,
67
67
  sideboardMcpProfile,
68
68
  trustSystemCertificates
69
- } from "../chunk-HRWCW6LC.js";
69
+ } from "../chunk-UVWIYSAA.js";
70
70
  import {
71
71
  GLOBAL_WORKSPACE_ID,
72
72
  isCloudCoordinatorThread,
73
73
  isOrchestratorThread,
74
74
  listWorkspaces
75
- } from "../chunk-576S3HJ7.js";
75
+ } from "../chunk-64NUGRZ3.js";
76
76
  import "../chunk-J5GON4SU.js";
77
77
  import "../chunk-P2BSMNHB.js";
78
- import "../chunk-IMO7AZI4.js";
79
- import "../chunk-WURF67ID.js";
78
+ import "../chunk-6HIAYIXT.js";
79
+ import "../chunk-BEQE7VOE.js";
80
80
  import {
81
81
  httpFetch
82
82
  } from "../chunk-VKQGAWHY.js";
@@ -90,13 +90,13 @@ import {
90
90
  resolveListPrsOptions,
91
91
  resolveRepoRoot,
92
92
  warmGithubAgentAuth
93
- } from "../chunk-5ZFULOTC.js";
93
+ } from "../chunk-XM4UIFQU.js";
94
94
  import "../chunk-D6JWYJ4P.js";
95
95
  import {
96
96
  appendMessage,
97
97
  findThreadByRef,
98
98
  readThread
99
- } from "../chunk-7HOKP4GR.js";
99
+ } from "../chunk-PELMZRDB.js";
100
100
  import "../chunk-N6XI5KXL.js";
101
101
  import "../chunk-DD67JWTN.js";
102
102
  import {
@@ -113,13 +113,14 @@ import {
113
113
  readSecureJson,
114
114
  readViewerContext,
115
115
  resolveEffectiveIssueSource,
116
+ resolveProjectReviewLabel,
116
117
  resolveVaultKey,
117
118
  resolveViewerProfile,
118
119
  resolveViewerProfileForRepo,
119
120
  saveLinearOAuth,
120
121
  writeSecureJson,
121
122
  writeViewerContext
122
- } from "../chunk-YLGBQVRK.js";
123
+ } from "../chunk-XEBQRCDW.js";
123
124
  import {
124
125
  writePrivateFile
125
126
  } from "../chunk-NSTQ6QKD.js";
@@ -2366,7 +2367,7 @@ async function continueSourceThread(threadId, prompt) {
2366
2367
  await continueOnReply(threadId, prompt);
2367
2368
  return;
2368
2369
  }
2369
- const { getOrchestrator: getOrchestrator2 } = await import("../orchestrator-DPMS5KMY.js");
2370
+ const { getOrchestrator: getOrchestrator2 } = await import("../orchestrator-2NZUV4LI.js");
2370
2371
  await getOrchestrator2().send(threadId, prompt);
2371
2372
  } catch {
2372
2373
  }
@@ -4463,7 +4464,7 @@ async function startMcpServer() {
4463
4464
  );
4464
4465
  }
4465
4466
  try {
4466
- const { maxConcurrentAgents } = await import("../app-settings-652J57CX.js");
4467
+ const { maxConcurrentAgents } = await import("../app-settings-NKXH4PKM.js");
4467
4468
  orch.setMaxConcurrent(maxConcurrentAgents());
4468
4469
  } catch {
4469
4470
  }
@@ -4958,7 +4959,7 @@ async function startMcpServer() {
4958
4959
  registerConnectedIssueVendorTools(server);
4959
4960
  registerScheduleTools(server);
4960
4961
  const { getCaffeinateHold, setCaffeinateHold } = await import("../caffeinate-hold-FNKIPXDU.js");
4961
- const { resolveNewThreadOptions, resolveThreadDefaults } = await import("../app-settings-652J57CX.js");
4962
+ const { resolveNewThreadOptions, resolveThreadDefaults } = await import("../app-settings-NKXH4PKM.js");
4962
4963
  const accountDefaults = resolveThreadDefaults();
4963
4964
  const accountDefaultsHint = `Account defaults: agent=${accountDefaults.agent}, model=${accountDefaults.model?.trim() || "Auto"}, effort=${accountDefaults.effort}`;
4964
4965
  server.tool(
@@ -5508,12 +5509,12 @@ async function startMcpServer() {
5508
5509
  );
5509
5510
  server.tool(
5510
5511
  "list_prs",
5511
- 'List GitHub PRs for a registered workspace (the review surface for assigned ticket work \u2014 not the tickets). Pass repoPath from list_workspaces. "Get me N tickets to review" \u2192 queue=review and limit=N: open non-draft PRs labeled eng-review with no individual user reviewer. Prefer teams that match Settings \u2192 Agents / Projects roles for this repo. A team like engineering-team is not a claim (you are on that team). Also: state (open|closed|merged|all|review), label, reviewer (me|unassigned|login), query, limit (default 40, max 250). Then create_thread with sourceType=pr.',
5512
+ `List GitHub PRs for a registered workspace (the review surface for assigned ticket work \u2014 not the tickets). Pass repoPath from list_workspaces. "Get me N tickets to review" \u2192 queue=review and limit=N: open non-draft PRs labeled with this project's ready-for-review GitHub label (Settings \u2192 Projects; default eng-review) with no individual user reviewer. Prefer teams that match Settings \u2192 Agents / Projects roles for this repo. A team like engineering-team is not a claim (you are on that team). Also: state (open|closed|merged|all|review), label, reviewer (me|unassigned|login), query, limit (default 40, max 250). Then create_thread with sourceType=pr.`,
5512
5513
  {
5513
5514
  repoPath: z9.string(),
5514
5515
  query: z9.string().optional().describe("GitHub search tokens (title, draft:true, \u2026)"),
5515
5516
  queue: z9.enum(["review", "mine", "approved", "changes"]).optional().describe(
5516
- 'review = unclaimed eng-review inbox (use for "get me N tickets to review"). mine = review-requested:@me. approved / changes = eng-approved / eng-requested-changes.'
5517
+ "review = unclaimed ready-for-review inbox (Settings \u2192 Projects label, default eng-review). mine = review-requested:@me. approved / changes = eng-approved / eng-requested-changes."
5517
5518
  ),
5518
5519
  state: z9.enum(["open", "closed", "merged", "all", "review"]).optional().describe("GitHub PR state (default open). review is an alias for queue=review."),
5519
5520
  label: z9.string().optional().describe(
@@ -5533,7 +5534,8 @@ async function startMcpServer() {
5533
5534
  state,
5534
5535
  labels: label,
5535
5536
  reviewer,
5536
- limit: page + 1
5537
+ limit: page + 1,
5538
+ reviewLabel: resolveProjectReviewLabel(loadAppSettings(), root)
5537
5539
  });
5538
5540
  const prs = await listPrs(root, resolved);
5539
5541
  const windowed = applyIssueListWindow(prs, page);