@sideboard-ai/core 0.1.151 → 0.1.153

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 (61) hide show
  1. package/dist/{abletime-223A3LY6.js → abletime-H7LPGIP2.js} +3 -3
  2. package/dist/{abletime-CLC5UJC2.js → abletime-JSTJLXAW.js} +3 -3
  3. package/dist/agents/cursor-runner.js +2 -2
  4. package/dist/{agents-JAOMXDXN.js → agents-V24DYZI4.js} +8 -9
  5. package/dist/{agents-U2JCFXW4.js → agents-YVW75KBO.js} +8 -9
  6. package/dist/{app-settings-3CHCNIMD.js → app-settings-H3INSR67.js} +38 -4
  7. package/dist/{app-settings-J3JBCUOT.js → app-settings-VRQI3FIE.js} +38 -4
  8. package/dist/{caffeinate-hold-NBRUWYXO.js → caffeinate-hold-DBKMRZZO.js} +2 -2
  9. package/dist/{caffeinate-hold-X3JNPR42.js → caffeinate-hold-SK2QISPE.js} +2 -2
  10. package/dist/chunk-2F63IMCL.js +959 -0
  11. package/dist/{chunk-GCWAAPJ5.js → chunk-2NRNP7QP.js} +432 -239
  12. package/dist/{chunk-4XNSGDXE.js → chunk-3BWVOUQG.js} +244 -1
  13. package/dist/{chunk-LZAOX76N.js → chunk-4THE3EY7.js} +6 -6
  14. package/dist/{chunk-TUGKX5BD.js → chunk-7UURXPKD.js} +1 -1
  15. package/dist/{chunk-DCOZABNT.js → chunk-AO35MGOE.js} +1 -1
  16. package/dist/{chunk-3JBMACYX.js → chunk-CJQLPPEJ.js} +387 -15
  17. package/dist/{chunk-CZD4NRDZ.js → chunk-D7EGJ3EI.js} +244 -1
  18. package/dist/{chunk-QZQEXME2.js → chunk-EFVFB2AH.js} +1 -1
  19. package/dist/{chunk-B7XK37WZ.js → chunk-FDCFXMDG.js} +1 -1
  20. package/dist/{chunk-WLV7TRMR.js → chunk-JOK4XWBG.js} +1 -1
  21. package/dist/{chunk-BD2ICC4D.js → chunk-JTJHOYCU.js} +1 -1
  22. package/dist/{chunk-6H4TJ5TA.js → chunk-KMNODRWF.js} +481 -212
  23. package/dist/{chunk-GE7M3QTE.js → chunk-LQMFCS54.js} +387 -15
  24. package/dist/{chunk-G7SIQFBQ.js → chunk-LZ6QMEQC.js} +1 -1
  25. package/dist/{chunk-EUXOHTUK.js → chunk-LZQULFIT.js} +1 -1
  26. package/dist/{chunk-KLBOWJ74.js → chunk-OCQPTUR7.js} +1 -1
  27. package/dist/{chunk-UIS7BVCX.js → chunk-QZEZXYVV.js} +13 -13
  28. package/dist/chunk-RNC3GR6L.js +905 -0
  29. package/dist/{chunk-VHX673DI.js → chunk-WLPXZFRE.js} +1 -1
  30. package/dist/{chunk-7F4XE6UG.js → chunk-XD2BAANL.js} +5 -5
  31. package/dist/{connected-teams-XO766HB4.js → connected-teams-DBWAMP7G.js} +2 -2
  32. package/dist/{connected-teams-I2WZZZFA.js → connected-teams-WGONUQOF.js} +2 -2
  33. package/dist/{coordinator-prompt-LWYUZAXR.js → coordinator-prompt-7FHKCWXB.js} +5 -5
  34. package/dist/{coordinator-prompt-ZK5MII7W.js → coordinator-prompt-KX2FVVYT.js} +5 -5
  35. package/dist/{cursor-recover-NOQYOFRF.js → cursor-recover-L5MD6MBO.js} +1 -1
  36. package/dist/{cursor-recover-QSLWEZNA.js → cursor-recover-NDMLLNYX.js} +2 -2
  37. package/dist/{global-workspace-IB2CCEJF.js → global-workspace-2BRRKSDN.js} +5 -6
  38. package/dist/{global-workspace-T7RL3XEC.js → global-workspace-4LHCZ2DC.js} +5 -6
  39. package/dist/index.cjs +1961 -786
  40. package/dist/index.d.cts +228 -30
  41. package/dist/index.d.ts +228 -30
  42. package/dist/index.js +322 -110
  43. package/dist/mcp/run-stdio.cjs +1817 -1264
  44. package/dist/mcp/run-stdio.js +250 -82
  45. package/dist/{orchestrator-DPTRBKEH.js → orchestrator-5PSHBLP6.js} +10 -12
  46. package/dist/{orchestrator-Y5MWUU7C.js → orchestrator-ZSSU3FKW.js} +9 -11
  47. package/dist/{paths-UMEDHOS5.js → paths-53TLA7VQ.js} +1 -1
  48. package/dist/{paths-QCI3MTO5.js → paths-RRCLNSJB.js} +1 -1
  49. package/dist/{thread-store-WGASXXXR.js → thread-store-KBFBHT5G.js} +2 -2
  50. package/dist/{thread-store-57ZLHR3A.js → thread-store-MVQU6HPJ.js} +2 -2
  51. package/dist/{workspaces-ZXCUVCZC.js → workspaces-5UNDTN4G.js} +5 -7
  52. package/dist/{workspaces-VICQYI2N.js → workspaces-MQYNZXUK.js} +5 -7
  53. package/dist/{worktree-HTUM35NT.js → worktree-PEWDAX5O.js} +4 -4
  54. package/dist/{worktree-DPIREDFR.js → worktree-T4SWFSTT.js} +4 -4
  55. package/package.json +1 -1
  56. package/dist/chunk-77MP647F.js +0 -210
  57. package/dist/chunk-ADCEGG4A.js +0 -592
  58. package/dist/chunk-HWZWBJWL.js +0 -120
  59. package/dist/chunk-OXOU2FRS.js +0 -212
  60. package/dist/chunk-TSCWSAQL.js +0 -122
  61. package/dist/chunk-Y2FNDKHF.js +0 -538
package/dist/index.js CHANGED
@@ -9,6 +9,7 @@ import {
9
9
  CONTEXT_KEEP_RECENT_CHARS,
10
10
  CONTEXT_KEEP_RECENT_MESSAGES,
11
11
  CONTEXT_MIN_MESSAGES,
12
+ CONTEXT_REVIEW_PATH,
12
13
  DEFAULT_WORKTREE_SORT,
13
14
  HOME_BOARD_AGENT_HINT,
14
15
  HOME_BOARD_CACHE_TTL_MS,
@@ -71,6 +72,8 @@ import {
71
72
  disconnectOptionalService,
72
73
  disconnectSlackWorkspace,
73
74
  discoverSkills,
75
+ emptySetupLog,
76
+ ensureReviewGuidelinesFile,
74
77
  ensureReviewRequestFile,
75
78
  ensureReviewSkillFile,
76
79
  estimateMessageChars,
@@ -84,6 +87,7 @@ import {
84
87
  findBoardPr,
85
88
  findLastBrightsyContextSummary,
86
89
  findLiveThreadForCreate,
90
+ findLiveThreadForCreateSource,
87
91
  findOrphanWorktrees,
88
92
  findThreadForStackLayer,
89
93
  fireSchedule,
@@ -98,6 +102,7 @@ import {
98
102
  formatMessagesAsTranscript,
99
103
  formatOptionalServicesDirective,
100
104
  formatOptionalServicesReminder,
105
+ formatPrGateDirective,
101
106
  formatProcessGuideDirective,
102
107
  formatRenameBranchDirective,
103
108
  formatScheduleWhen,
@@ -149,6 +154,7 @@ import {
149
154
  listWorktreeFiles,
150
155
  loadAgentInstructions,
151
156
  maybeCompactContext,
157
+ mergeSetupOutput,
152
158
  messagesSinceLastBrightsyContextSummary,
153
159
  normalizeServiceOrigin,
154
160
  openPrStackLayers,
@@ -161,6 +167,7 @@ import {
161
167
  pollSlackOutboundWatches,
162
168
  previewLand,
163
169
  readExistingReviewRequestFile,
170
+ readSetupLog,
164
171
  readSkillBody,
165
172
  readTurnLive,
166
173
  readWorktreeFile,
@@ -213,7 +220,7 @@ import {
213
220
  worktreeCleanupSettings,
214
221
  wrapReviewSkillMarkdown,
215
222
  writeWorktreeFile
216
- } from "./chunk-6H4TJ5TA.js";
223
+ } from "./chunk-KMNODRWF.js";
217
224
  import {
218
225
  LEGACY_PLAN_FILE_REL,
219
226
  PLAN_FILE_NAME,
@@ -307,49 +314,33 @@ import {
307
314
  withEventParentId,
308
315
  withEventsParentId,
309
316
  writeInjectedMcpConfig
310
- } from "./chunk-UIS7BVCX.js";
311
- import {
312
- brightsyMcpServerName,
313
- connectBrightsyTeam,
314
- disconnectBrightsyTeam,
315
- ensureConnectedBrightsyTeamTokens,
316
- getBrightsySession,
317
- listBrightsyAccounts,
318
- listConnectedBrightsyTeams,
319
- switchBrightsyAccount
320
- } from "./chunk-7F4XE6UG.js";
321
- import {
322
- brightsyAccessTokenNeedsRefresh,
323
- brightsyConfigPath,
324
- ensureBrightsyLocalConfigFresh,
325
- loadBrightsyConfig,
326
- refreshBrightsyAccessToken,
327
- saveBrightsyConfig
328
- } from "./chunk-M267JPEA.js";
329
- import {
330
- addWorkspace,
331
- ensureWorkspace,
332
- listWorkspaces,
333
- removeWorkspace,
334
- syncWorkspacesFromThreads
335
- } from "./chunk-HWZWBJWL.js";
317
+ } from "./chunk-QZEZXYVV.js";
336
318
  import {
337
319
  CLOUD_COORDINATOR_BUSY_REPLY,
338
320
  CLOUD_COORDINATOR_STOPPED_REPLY,
339
321
  CLOUD_COORDINATOR_TIMEOUT_REPLY,
340
322
  CLOUD_ORCHESTRATOR_GOAL,
323
+ COORDINATOR_TOOL_PLAYBOOK,
341
324
  GLOBAL_WORKSPACE_ID,
342
325
  ORCHESTRATOR_AGENT_KINDS,
343
326
  SIDEBOARD_FORCE_STOP,
327
+ SLACK_REPLY_FORMATTING,
328
+ addWorkspace,
344
329
  assertOrchestratorCapableAgent,
345
330
  attachmentFromAbsolutePath,
346
331
  attachmentsFromBuffers,
347
332
  attachmentsFromWorktreePaths,
348
333
  coerceOrchestratorAgent,
334
+ coordinatorSystemPrompt,
335
+ coordinatorTurnReminder,
349
336
  createGlobalChat,
337
+ enrichWorkspacesWithGithub,
350
338
  ensureCloudCoordinator,
339
+ ensureGlobalCoordinatorCwd,
351
340
  ensureSlackCoordinator,
341
+ ensureWorkspace,
352
342
  findSlackCoordinator,
343
+ formatWorkspaceInventory,
353
344
  healOrchestrationSoccerTitles,
354
345
  isCloudCoordinatorThread,
355
346
  isGlobalRepoPath,
@@ -359,24 +350,18 @@ import {
359
350
  isOrchestratorThread,
360
351
  isSlackCoordinatorThread,
361
352
  listGlobalThreads,
353
+ listWorkspaces,
362
354
  orchestrationTitleNeedsSoccerNickname,
363
355
  orchestratorSessionPoisonedByBuiltins,
364
356
  parseForceStopMessage,
365
357
  persistPendingFileAttachments,
358
+ removeWorkspace,
366
359
  slackCoordinatorSourceRef,
367
360
  stageAbsolutePathsAsAttachments,
368
361
  stageBuffersAsAttachments,
362
+ syncWorkspacesFromThreads,
369
363
  takenTeamSlugsForOrchestration
370
- } from "./chunk-ADCEGG4A.js";
371
- import {
372
- COORDINATOR_TOOL_PLAYBOOK,
373
- SLACK_REPLY_FORMATTING,
374
- coordinatorSystemPrompt,
375
- coordinatorTurnReminder,
376
- enrichWorkspacesWithGithub,
377
- ensureGlobalCoordinatorCwd,
378
- formatWorkspaceInventory
379
- } from "./chunk-77MP647F.js";
364
+ } from "./chunk-2F63IMCL.js";
380
365
  import {
381
366
  FAMOUS_SOCCER_TEAMS,
382
367
  GITHUB_PR_BODY_MAX_CHARS,
@@ -454,6 +439,7 @@ import {
454
439
  resolveDiffBaseRef,
455
440
  resolveGithubAgentToken,
456
441
  resolveGithubRepoSlug,
442
+ resolveListPrsOptions,
457
443
  resolvePrSelector,
458
444
  resolvePrSelectors,
459
445
  resolveRepoRoot,
@@ -468,7 +454,7 @@ import {
468
454
  worktreeDisplayLabel,
469
455
  worktreeDisplayLabelForGroup,
470
456
  worktreeNameFromPath
471
- } from "./chunk-GE7M3QTE.js";
457
+ } from "./chunk-LQMFCS54.js";
472
458
  import {
473
459
  ATTACHMENTS_DIR,
474
460
  DETACHED_JOBS_DIR,
@@ -477,6 +463,24 @@ import {
477
463
  attachmentsGitignoreBody,
478
464
  isWorkspaceScratchPath
479
465
  } from "./chunk-JRH62XC4.js";
466
+ import {
467
+ brightsyMcpServerName,
468
+ connectBrightsyTeam,
469
+ disconnectBrightsyTeam,
470
+ ensureConnectedBrightsyTeamTokens,
471
+ getBrightsySession,
472
+ listBrightsyAccounts,
473
+ listConnectedBrightsyTeams,
474
+ switchBrightsyAccount
475
+ } from "./chunk-XD2BAANL.js";
476
+ import {
477
+ brightsyAccessTokenNeedsRefresh,
478
+ brightsyConfigPath,
479
+ ensureBrightsyLocalConfigFresh,
480
+ loadBrightsyConfig,
481
+ refreshBrightsyAccessToken,
482
+ saveBrightsyConfig
483
+ } from "./chunk-M267JPEA.js";
480
484
  import {
481
485
  ABLETIME_MCP_PATH,
482
486
  DEFAULT_ABLETIME_HOST,
@@ -498,7 +502,7 @@ import {
498
502
  taskUrl,
499
503
  toAbleTimeIssueInfo,
500
504
  verifyAbleTimeConnection
501
- } from "./chunk-WLV7TRMR.js";
505
+ } from "./chunk-JOK4XWBG.js";
502
506
  import {
503
507
  formatFetchError,
504
508
  httpFetch,
@@ -515,10 +519,16 @@ import {
515
519
  withMaxOldSpaceSize
516
520
  } from "./chunk-HEII7W3Q.js";
517
521
  import {
522
+ ACCOUNT_ROLES,
523
+ ACCOUNT_ROLE_LABELS,
524
+ ACCOUNT_ROLE_MAX,
525
+ ACCOUNT_ROLE_PRESETS,
518
526
  FOLLOW_UP_BEHAVIORS,
519
527
  GITHUB_GIT_AUTH_MODES,
520
528
  HARNESS_ENV_KEYS,
521
529
  ISSUE_SOURCE_LABELS,
530
+ PROFILE_NOTES_MAX,
531
+ accountRoleLabel,
522
532
  appSettingsPath,
523
533
  applyAppEnvironment,
524
534
  autoArchiveOnMergeEnabled,
@@ -541,7 +551,11 @@ import {
541
551
  disconnectLinearConnection,
542
552
  emptyPublicIntegrations,
543
553
  ensureSlackDeviceIdentity,
554
+ findProjectProfileKey,
544
555
  followUpBehavior,
556
+ formatAccountProfilePlaybookLine,
557
+ formatProjectProfilePlaybookLines,
558
+ formatWorkspaceProfileSuffix,
545
559
  getAbleTimeAccessToken,
546
560
  getAbleTimeHost,
547
561
  getDefaultAgent,
@@ -562,13 +576,19 @@ import {
562
576
  orchestrationQuotaFallbackAgent,
563
577
  orchestrationQuotaOnLimit,
564
578
  persistVaultKeyInKeychain,
579
+ preferTeamsForRole,
565
580
  readKeychainVaultKey,
581
+ resolveAccountProfile,
582
+ resolveAccountProfileFromSettings,
566
583
  resolveAgentExecutable,
567
584
  resolveClaudeExecutable,
568
585
  resolveEffectiveIssueSource,
569
586
  resolveNewThreadOptions,
570
587
  resolveThreadDefaults,
571
588
  resolveVaultKey,
589
+ resolveViewerProfile,
590
+ resolveViewerProfileForRepo,
591
+ reviewTeamHintsForRoles,
572
592
  saveAbleTimeConnection,
573
593
  saveAppSettings,
574
594
  saveLinearOAuth,
@@ -586,8 +606,9 @@ import {
586
606
  updateCodexSettings,
587
607
  updateDefaultsSettings,
588
608
  updateIntegrationsSettings,
589
- updateOpencodeSettings
590
- } from "./chunk-4XNSGDXE.js";
609
+ updateOpencodeSettings,
610
+ updateProjectProfileSettings
611
+ } from "./chunk-3BWVOUQG.js";
591
612
  import {
592
613
  stripNestedElectronEnv
593
614
  } from "./chunk-4TR3HZFT.js";
@@ -597,7 +618,7 @@ import {
597
618
  isThreadCaffeinated,
598
619
  releaseCaffeinateHoldForThread,
599
620
  setCaffeinateHold
600
- } from "./chunk-DCOZABNT.js";
621
+ } from "./chunk-AO35MGOE.js";
601
622
  import "./chunk-JT7R45JB.js";
602
623
  import {
603
624
  appendMessage,
@@ -614,7 +635,7 @@ import {
614
635
  updateThread,
615
636
  withThreadLock,
616
637
  writeThread
617
- } from "./chunk-TUGKX5BD.js";
638
+ } from "./chunk-7UURXPKD.js";
618
639
  import {
619
640
  THINKING_EFFORTS,
620
641
  isThinkingEffort,
@@ -650,7 +671,7 @@ import {
650
671
  threadsDir,
651
672
  workspaceSettingsSourceLabel,
652
673
  worktreesRoot
653
- } from "./chunk-QZQEXME2.js";
674
+ } from "./chunk-EFVFB2AH.js";
654
675
  import "./chunk-QQKDGPUI.js";
655
676
  import {
656
677
  conductorBundledBinDir,
@@ -1018,7 +1039,7 @@ var ISSUE_FIELDS = `
1018
1039
  state { id name type }
1019
1040
  assignee { id name }
1020
1041
  creator { id name }
1021
- team { id key name states(first: 50) { nodes { id name type } } }
1042
+ team { id key name }
1022
1043
  labels(first: 50) { nodes { name } }
1023
1044
  cycle { name number startsAt endsAt completedAt }
1024
1045
  project { id name }
@@ -1499,7 +1520,9 @@ async function updateLinearIssue(input, opts) {
1499
1520
  }
1500
1521
  if (input.state?.trim()) {
1501
1522
  const existing = await getLinearIssue(issueId, opts);
1502
- const team = existing.team;
1523
+ const { teams } = await listLinearTeams(opts);
1524
+ const teamRef = existing.team?.key || existing.team?.id;
1525
+ const team = teamRef ? resolveLinearTeam(teams, teamRef) : void 0;
1503
1526
  if (!team?.states.length) {
1504
1527
  throw new Error(`Linear issue ${existing.identifier} has no workflow states to resolve "${input.state}"`);
1505
1528
  }
@@ -1556,6 +1579,11 @@ async function validateLinearApiKey(apiKey) {
1556
1579
  function assigneeKey(assignee) {
1557
1580
  return (assignee ?? "").trim().toLowerCase();
1558
1581
  }
1582
+ function takeIssuePage(issues, limit) {
1583
+ if (limit == null) return issues;
1584
+ const n = Math.max(1, Math.min(1e3, Math.floor(limit)));
1585
+ return issues.slice(0, n);
1586
+ }
1559
1587
  function issueMatchesAssignee(issue, assignee, viewerName = "") {
1560
1588
  const key = assigneeKey(assignee);
1561
1589
  if (!key || key === "all" || key === "*") return true;
@@ -1657,13 +1685,33 @@ async function listIssues(repoPath, opts) {
1657
1685
  };
1658
1686
  }
1659
1687
  if (source === "abletime") {
1660
- const [listed, searched] = await Promise.all([
1661
- listAbleTimeAssignedIssues(),
1662
- query ? searchAbleTimeTasks(query) : Promise.resolve(null)
1663
- ]);
1688
+ if (query) {
1689
+ const [searched, orientation] = await Promise.all([
1690
+ searchAbleTimeTasks(query),
1691
+ getAbleTimeOrientation().catch(() => null)
1692
+ ]);
1693
+ const viewerName2 = orientation?.viewer.name ?? orientation?.viewer.id ?? "";
1694
+ const issues3 = takeIssuePage(
1695
+ searched.map(toAbleTimeIssueInfo).filter((issue) => issueMatchesAssignee(issue, assignee, viewerName2)),
1696
+ opts?.limit
1697
+ );
1698
+ return {
1699
+ source,
1700
+ preferredSource,
1701
+ linearConnected,
1702
+ abletimeConnected,
1703
+ issues: issues3,
1704
+ viewer: {
1705
+ login: orientation?.viewer.name,
1706
+ name: orientation?.viewer.name
1707
+ }
1708
+ };
1709
+ }
1710
+ const listed = await listAbleTimeAssignedIssues();
1664
1711
  const viewerName = listed.viewer.name ?? listed.viewer.id ?? "";
1665
- const issues2 = (searched ? searched.map(toAbleTimeIssueInfo) : listed.issues).filter(
1666
- (issue) => issueMatchesAssignee(issue, assignee, viewerName)
1712
+ const issues2 = takeIssuePage(
1713
+ listed.issues.filter((issue) => issueMatchesAssignee(issue, assignee, viewerName)),
1714
+ opts?.limit
1667
1715
  );
1668
1716
  return {
1669
1717
  source,
@@ -2583,12 +2631,53 @@ function registerSlackTools(server) {
2583
2631
 
2584
2632
  // src/mcp/abletime-tools.ts
2585
2633
  import { z as z2 } from "zod";
2586
- function text2(payload, isError = false) {
2634
+
2635
+ // src/mcp/issue-list.ts
2636
+ var MCP_ISSUE_LIST_DEFAULT_LIMIT = 40;
2637
+ var MCP_ISSUE_LIST_MAX_LIMIT = 250;
2638
+ function clampMcpIssueLimit(limit) {
2639
+ if (limit == null || !Number.isFinite(limit)) return MCP_ISSUE_LIST_DEFAULT_LIMIT;
2640
+ return Math.max(1, Math.min(MCP_ISSUE_LIST_MAX_LIMIT, Math.floor(limit)));
2641
+ }
2642
+ function applyIssueListWindow(items, limit) {
2643
+ const truncated = items.length > limit;
2587
2644
  return {
2588
- content: [{ type: "text", text: JSON.stringify(payload, null, 2) }],
2645
+ items: truncated ? items.slice(0, limit) : items,
2646
+ truncated
2647
+ };
2648
+ }
2649
+ function compactIssueRow(issue) {
2650
+ return {
2651
+ identifier: issue.identifier,
2652
+ title: issue.title,
2653
+ ...issue.assignee ? { assignee: issue.assignee } : {},
2654
+ ...issue.labels.length > 0 ? { labels: issue.labels } : {},
2655
+ ...issue.teamKey ? { team: issue.teamKey } : {},
2656
+ ...issue.cycle?.name ? { cycle: issue.cycle.name } : {}
2657
+ };
2658
+ }
2659
+ function formatMcpIssueList(input) {
2660
+ return {
2661
+ ...input.source ? { source: input.source } : {},
2662
+ ...input.viewer ? { viewer: input.viewer } : {},
2663
+ limit: input.limit,
2664
+ returned: input.issues.length,
2665
+ truncated: input.truncated,
2666
+ ...input.truncated ? { hint: "More issues match. Pass a higher limit (max 250) or a tighter query." } : {},
2667
+ issues: input.issues.map(compactIssueRow)
2668
+ };
2669
+ }
2670
+ function mcpJson(payload, isError = false) {
2671
+ return {
2672
+ content: [{ type: "text", text: JSON.stringify(payload) }],
2589
2673
  ...isError ? { isError: true } : {}
2590
2674
  };
2591
2675
  }
2676
+
2677
+ // src/mcp/abletime-tools.ts
2678
+ function text2(payload, isError = false) {
2679
+ return mcpJson(payload, isError);
2680
+ }
2592
2681
  function fail2(err) {
2593
2682
  return text2(
2594
2683
  { error: err instanceof Error ? err.message : String(err) },
@@ -2598,7 +2687,7 @@ function fail2(err) {
2598
2687
  function registerAbleTimeTools(server) {
2599
2688
  server.tool(
2600
2689
  "abletime_orientation",
2601
- "Call first when using AbleTime. Returns who the Account token is, open drafts, active tasks, and current projects. Requires Agent access (MCP) enabled in AbleTime.",
2690
+ "Call first when using AbleTime. Returns viewer, active tasks, and projects.",
2602
2691
  {},
2603
2692
  async () => {
2604
2693
  try {
@@ -2615,7 +2704,7 @@ function registerAbleTimeTools(server) {
2615
2704
  );
2616
2705
  server.tool(
2617
2706
  "abletime_list_projects",
2618
- "List AbleTime projects (and categories) the Account token can see. Use a project id on abletime_create_task / abletime_ensure_task.",
2707
+ "List AbleTime projects (and categories). Use a project id on create/ensure.",
2619
2708
  {},
2620
2709
  async () => {
2621
2710
  try {
@@ -2683,7 +2772,7 @@ function registerAbleTimeTools(server) {
2683
2772
  );
2684
2773
  server.tool(
2685
2774
  "abletime_ensure_task",
2686
- "Find an open AbleTime task for this work, or create one to track against. Matches identifier or exact title before creating. Prefer this when starting work that has no ticket yet, then create_thread with sourceType=ticket and the returned identifier.",
2775
+ "Find or create an AbleTime task for this work, then create_thread with sourceType=ticket.",
2687
2776
  {
2688
2777
  title: z2.string(),
2689
2778
  description: z2.string().optional(),
@@ -2704,10 +2793,7 @@ function registerAbleTimeTools(server) {
2704
2793
  // src/mcp/linear-tools.ts
2705
2794
  import { z as z3 } from "zod";
2706
2795
  function text3(payload, isError = false) {
2707
- return {
2708
- content: [{ type: "text", text: JSON.stringify(payload, null, 2) }],
2709
- ...isError ? { isError: true } : {}
2710
- };
2796
+ return mcpJson(payload, isError);
2711
2797
  }
2712
2798
  function fail3(err) {
2713
2799
  return text3(
@@ -2719,7 +2805,7 @@ var prioritySchema = z3.number().int().min(0).max(4).optional().describe("0 none
2719
2805
  function registerLinearTools(server) {
2720
2806
  server.tool(
2721
2807
  "linear_list_teams",
2722
- "List Linear teams (id, key, name) and workflow states for the connected Account. Use team key (e.g. ENG) on linear_create_issue; use state name or type (started, completed) on create/update. Viewer id is for assignee=me.",
2808
+ "List Linear teams (id, key, name) and workflow states. Use team key on create; state name or type on create/update.",
2723
2809
  {},
2724
2810
  async () => {
2725
2811
  try {
@@ -2731,15 +2817,30 @@ function registerLinearTools(server) {
2731
2817
  );
2732
2818
  server.tool(
2733
2819
  "linear_search_issues",
2734
- "Search or list open Linear issues. Not limited to the current user \u2014 pass assignee=unassigned for issues with no owner, assignee=all (default when query is set) for anyone including unassigned, assignee=me for yours, or a user id / name. Optional query uses Linear search (title, identifier, description).",
2820
+ "Search or list open Linear issues. Default 40; pass query and/or limit (max 250) when truncated. assignee: me, unassigned, all (default with query), or a user id/name.",
2735
2821
  {
2736
2822
  query: z3.string().optional().describe("Search text (identifier, title, description). Omit to list by assignee only."),
2737
2823
  assignee: z3.string().optional().describe("me, unassigned, all, a Linear user id, or a display name. Default: all when query is set, otherwise me."),
2738
- limit: z3.number().int().positive().max(250).optional()
2824
+ limit: z3.number().int().positive().max(250).optional().describe("Page size (default 40, max 250). Raise when truncated is true.")
2739
2825
  },
2740
2826
  async ({ query, assignee, limit }) => {
2741
2827
  try {
2742
- return text3(await listLinearIssuesFiltered({ query, assignee, limit }));
2828
+ const page = clampMcpIssueLimit(limit);
2829
+ const listed = await listLinearIssuesFiltered({
2830
+ query,
2831
+ assignee,
2832
+ limit: page + 1
2833
+ });
2834
+ const windowed = applyIssueListWindow(listed.issues, page);
2835
+ return mcpJson(
2836
+ formatMcpIssueList({
2837
+ source: "linear",
2838
+ viewer: listed.viewer.name,
2839
+ limit: page,
2840
+ issues: windowed.items,
2841
+ truncated: windowed.truncated
2842
+ })
2843
+ );
2743
2844
  } catch (err) {
2744
2845
  return fail3(err);
2745
2846
  }
@@ -2747,7 +2848,7 @@ function registerLinearTools(server) {
2747
2848
  );
2748
2849
  server.tool(
2749
2850
  "linear_get_issue",
2750
- "Get a Linear issue by uuid or identifier (ENG-123). Returns description, comments, relations (blocks/blockedBy/related/duplicate), parent/children, project, cycle, labels, and other metadata.",
2851
+ "Get a Linear issue by uuid or identifier (ENG-123): description, comments, relations, parent/children.",
2751
2852
  { id: z3.string() },
2752
2853
  async ({ id }) => {
2753
2854
  try {
@@ -2759,7 +2860,7 @@ function registerLinearTools(server) {
2759
2860
  );
2760
2861
  server.tool(
2761
2862
  "linear_create_issue",
2762
- 'Create a Linear issue. Call linear_list_teams first. team is id, key, or name. state is name, type (unstarted/started/completed/canceled/backlog), or id. assignee is "me" or a user id.',
2863
+ 'Create a Linear issue. Call linear_list_teams first. team is id/key/name; state is name/type/id; assignee is "me" or a user id.',
2763
2864
  {
2764
2865
  team: z3.string(),
2765
2866
  title: z3.string(),
@@ -2778,7 +2879,7 @@ function registerLinearTools(server) {
2778
2879
  );
2779
2880
  server.tool(
2780
2881
  "linear_update_issue",
2781
- 'Update a Linear issue (uuid or ENG-123). Pass at least one of title, description, state, assignee, priority. state is name, type, or id. assignee is "me", a user id, or null to unassign.',
2882
+ "Update a Linear issue (uuid or ENG-123). Pass title, description, state, assignee, and/or priority.",
2782
2883
  {
2783
2884
  id: z3.string(),
2784
2885
  title: z3.string().optional(),
@@ -2812,6 +2913,46 @@ function registerLinearTools(server) {
2812
2913
  );
2813
2914
  }
2814
2915
 
2916
+ // src/mcp/issue-vendor-tools.ts
2917
+ function registerConnectedIssueVendorTools(server, settings = loadAppSettings()) {
2918
+ if (isLinearConnected(settings)) registerLinearTools(server);
2919
+ if (isAbleTimeConnected(settings)) registerAbleTimeTools(server);
2920
+ }
2921
+
2922
+ // src/mcp/pr-list.ts
2923
+ function compactPrRow(pr) {
2924
+ return {
2925
+ number: pr.number,
2926
+ title: pr.title,
2927
+ ...pr.headRefName ? { head: pr.headRefName } : {},
2928
+ ...pr.author?.login ? { author: pr.author.login } : {},
2929
+ ...pr.state ? { state: pr.state } : {},
2930
+ ...pr.isDraft ? { draft: true } : {},
2931
+ ...pr.labels?.length ? { labels: pr.labels } : {},
2932
+ ...pr.reviewers?.length ? { reviewers: pr.reviewers } : {},
2933
+ ...pr.teams?.length ? { teams: pr.teams } : {},
2934
+ ...pr.reviewDecision ? { reviewDecision: pr.reviewDecision } : {},
2935
+ ...pr.tickets?.length ? { tickets: pr.tickets } : {}
2936
+ };
2937
+ }
2938
+ function formatMcpPrList(input) {
2939
+ return {
2940
+ ...input.viewer ? { viewer: input.viewer } : {},
2941
+ ...input.queue ? { queue: input.queue } : {},
2942
+ state: input.state,
2943
+ ...input.labels?.length ? { labels: input.labels } : {},
2944
+ ...input.reviewer ? { reviewer: input.reviewer } : {},
2945
+ ...input.query ? { query: input.query } : {},
2946
+ limit: input.limit,
2947
+ returned: input.prs.length,
2948
+ truncated: input.truncated,
2949
+ ...input.truncated ? {
2950
+ hint: "More PRs match. Pass a higher limit (max 250) or tighten label / reviewer / query."
2951
+ } : {},
2952
+ prs: input.prs.map(compactPrRow)
2953
+ };
2954
+ }
2955
+
2815
2956
  // src/mcp/schedule-tools.ts
2816
2957
  import { z as z4 } from "zod";
2817
2958
  function text4(payload, isError = false) {
@@ -3370,7 +3511,7 @@ async function startMcpServer() {
3370
3511
  );
3371
3512
  }
3372
3513
  try {
3373
- const { maxConcurrentAgents: maxConcurrentAgents2 } = await import("./app-settings-3CHCNIMD.js");
3514
+ const { maxConcurrentAgents: maxConcurrentAgents2 } = await import("./app-settings-H3INSR67.js");
3374
3515
  orch.setMaxConcurrent(maxConcurrentAgents2());
3375
3516
  } catch {
3376
3517
  }
@@ -3390,14 +3531,21 @@ async function startMcpServer() {
3390
3531
  if (!worktreeProfile) {
3391
3532
  server.tool(
3392
3533
  "list_workspaces",
3393
- "List registered Sideboard workspaces (repos). Each line is name, path, and github:owner/repo when resolvable \u2014 use path as repoPath for list_board/list_branches/list_prs/list_issues/create_thread.",
3534
+ "List registered Sideboard workspaces (repos). Each line is name, path, github:owner/repo when resolvable, and viewer roles/notes when set \u2014 use path as repoPath for list_board/list_branches/list_prs/list_issues/create_thread. Roles and notes (Settings \u2192 Agents / Projects) say which tickets and review PRs belong to the user.",
3394
3535
  {},
3395
3536
  async () => {
3396
3537
  const workspaces = orch.listWorkspaces();
3397
3538
  const lines = await Promise.all(
3398
3539
  workspaces.map(async (w) => {
3399
3540
  const slug = await resolveGithubRepoSlug(w.path).catch(() => null);
3400
- return slug ? `${w.name} ${w.path} github:${slug}` : `${w.name} ${w.path}`;
3541
+ let profile;
3542
+ try {
3543
+ profile = resolveViewerProfileForRepo(w.path);
3544
+ } catch {
3545
+ profile = resolveViewerProfile();
3546
+ }
3547
+ const suffix = formatWorkspaceProfileSuffix(profile);
3548
+ return slug ? `${w.name} ${w.path} github:${slug}${suffix}` : `${w.name} ${w.path}${suffix}`;
3401
3549
  })
3402
3550
  );
3403
3551
  return {
@@ -3650,11 +3798,10 @@ async function startMcpServer() {
3650
3798
  );
3651
3799
  if (!worktreeProfile) {
3652
3800
  registerSlackTools(server);
3653
- registerLinearTools(server);
3654
- registerAbleTimeTools(server);
3801
+ registerConnectedIssueVendorTools(server);
3655
3802
  registerScheduleTools(server);
3656
- const { getCaffeinateHold: getCaffeinateHold2, setCaffeinateHold: setCaffeinateHold2 } = await import("./caffeinate-hold-X3JNPR42.js");
3657
- const { resolveNewThreadOptions: resolveNewThreadOptions2, resolveThreadDefaults: resolveThreadDefaults2 } = await import("./app-settings-3CHCNIMD.js");
3803
+ const { getCaffeinateHold: getCaffeinateHold2, setCaffeinateHold: setCaffeinateHold2 } = await import("./caffeinate-hold-SK2QISPE.js");
3804
+ const { resolveNewThreadOptions: resolveNewThreadOptions2, resolveThreadDefaults: resolveThreadDefaults2 } = await import("./app-settings-H3INSR67.js");
3658
3805
  const accountDefaults = resolveThreadDefaults2();
3659
3806
  const accountDefaultsHint = `Account defaults: agent=${accountDefaults.agent}, model=${accountDefaults.model?.trim() || "Auto"}, effort=${accountDefaults.effort}`;
3660
3807
  server.tool(
@@ -3697,7 +3844,7 @@ async function startMcpServer() {
3697
3844
  );
3698
3845
  server.tool(
3699
3846
  "create_thread",
3700
- `Create a worktree thread (chat) from branch, pr, or ticket. If a live worktree already matches that ticket, PR, or named branch, returns it (alreadyStarted=true) instead of a second checkout. Creating from the default branch still opens a new isolated worktree. Pass repoPath from list_workspaces. cowboy=true uses the project folder on the default branch (no isolated worktree; land is commit+push). From an orchestration chat, omit parentThreadId (Sideboard binds the child to this chat) or pass the exact id from the turn reminder \u2014 never invent a uuid. Prefer omitting agent/model so Sideboard applies ${accountDefaultsHint}. Setup (settings.toml, .cursor/worktrees.json, or script/setup) runs in the background in parallel with the first turn (skipped for cowboy). Then use send_to_thread to chat.`,
3847
+ `Create a worktree thread (chat) from branch, pr, or ticket. A ticket, PR, or named branch may have only one live worktree \u2014 if one already matches, returns it (alreadyStarted=true) instead of a second checkout. Creating from the default branch still opens a new isolated worktree. Pass repoPath from list_workspaces. cowboy=true uses the project folder on the default branch (no isolated worktree; land is commit+push). From an orchestration chat, omit parentThreadId (Sideboard binds the child to this chat) or pass the exact id from the turn reminder \u2014 never invent a uuid. Prefer omitting agent/model so Sideboard applies ${accountDefaultsHint}. Setup (settings.toml, .cursor/worktrees.json, or script/setup) runs in the background in parallel with the first turn (skipped for cowboy). Then use send_to_thread to chat.`,
3701
3848
  {
3702
3849
  sourceType: z5.enum(["branch", "pr", "ticket"]),
3703
3850
  sourceRef: z5.string(),
@@ -3724,7 +3871,7 @@ async function startMcpServer() {
3724
3871
  );
3725
3872
  server.tool(
3726
3873
  "start_board_card",
3727
- "Same as create_thread for a ticket, PR, or named branch (attaches issue text when Sideboard can resolve it). Reuses the live worktree if one already matches. Then send_to_thread.",
3874
+ "Same as create_thread for a ticket, PR, or named branch (attaches issue text when Sideboard can resolve it). Does not create a second worktree when one already matches \u2014 returns that thread (alreadyStarted). Then send_to_thread.",
3728
3875
  {
3729
3876
  kind: z5.enum(["ticket", "pr", "branch"]),
3730
3877
  ref: z5.string().describe("Ticket identifier (ENG-12), PR number (44), or branch name from list_board"),
@@ -4024,9 +4171,25 @@ async function startMcpServer() {
4024
4171
  };
4025
4172
  }
4026
4173
  );
4174
+ server.tool(
4175
+ "get_pr_checks",
4176
+ "Snapshot of GitHub PR checks for a worktree thread (`gh pr checks` plus merge/review gates). null = no PR. If the user gave a goal (Greptile 5/5, CI green), the worktree agent watches with `gh pr checks --watch` via /long-running \u2014 this tool is a snapshot, not a waiter. Coordinators: do not run gh from the orchestration cwd.",
4177
+ { ref: z5.string().describe("Worktree thread id/ref") },
4178
+ async ({ ref }) => {
4179
+ try {
4180
+ const checks = await orch.getPrChecks(ref);
4181
+ return {
4182
+ content: [{ type: "text", text: JSON.stringify(checks) }]
4183
+ };
4184
+ } catch (err) {
4185
+ const message = err instanceof Error ? err.message : String(err);
4186
+ return { content: [{ type: "text", text: message }], isError: true };
4187
+ }
4188
+ }
4189
+ );
4027
4190
  server.tool(
4028
4191
  "request_review",
4029
- 'Start a merge-readiness Review on a worktree agent thread (same as the desktop Review button). Opens a new Review chat tab, attaches .claude/skills/review/SKILL.md when present (else seeds that skill from .sideboard/review.md or the stock template), and sends "Review changes in this workspace." Expect Approve / Approve with nits / Request changes / Needs more information. Pass a worktree thread ref \u2014 not the orchestrator. Then wait_for_turn (loop while stillRunning) / get_turn_result on the returned review tab id.',
4192
+ 'Start a merge-readiness Review on a worktree agent thread (same as the desktop Review button). Opens a new Review chat tab, attaches .claude/skills/review/SKILL.md when present (else copies .sideboard/review.md into .context/review.md, or seeds that file from the stock template), and sends "Review changes in this workspace." Expect Approve / Approve with nits / Request changes / Needs more information. Pass a worktree thread ref \u2014 not the orchestrator. Then wait_for_turn (loop while stillRunning) / get_turn_result on the returned review tab id.',
4030
4193
  { ref: z5.string().describe("Worktree thread id/ref to review") },
4031
4194
  async ({ ref }) => {
4032
4195
  try {
@@ -4054,7 +4217,7 @@ async function startMcpServer() {
4054
4217
  );
4055
4218
  server.tool(
4056
4219
  "ask_git",
4057
- "Commit & push, open a draft PR, resolve conflicts, or merge \u2014 same actions as the desktop git buttons. When the worktree is clean, Sideboard pushes / opens the PR itself (HTTPS via `gh` even when origin is SSH / Settings \u2192 Git is SSH). When dirty, queues the worktree agent to commit; then wait_for_turn (loop while stillRunning). Pass a worktree thread ref (not the orchestrator). action=merge only when the user explicitly asked to merge that PR. Do not run git or gh from the orchestration cwd. If this tool errors that the GraphQL/PR body is too long, the branch is already pushed \u2014 have the worktree agent retry `gh pr create --body-file` with a short description (GitHub limit 65,536 characters). Do not invent SSH/auth failures from that error.",
4220
+ "Commit & push, open a draft PR, resolve conflicts, or merge \u2014 same actions as the desktop git buttons. When the worktree is clean, Sideboard pushes / opens the PR itself (HTTPS via `gh` even when origin is SSH / Settings \u2192 Git is SSH). When dirty, queues the worktree agent to commit; then wait_for_turn (loop while stillRunning). Do not start a checks loop on a plain push \u2014 only if the user gave a goal (Greptile 5/5, CI green). Pass a worktree thread ref (not the orchestrator). action=merge only when the user explicitly asked to merge that PR. Do not run git or gh from the orchestration cwd. If this tool errors that the GraphQL/PR body is too long, the branch is already pushed \u2014 have the worktree agent retry `gh pr create --body-file` with a short description (GitHub limit 65,536 characters). Do not invent SSH/auth failures from that error.",
4058
4221
  {
4059
4222
  ref: z5.string().describe("Worktree thread id/ref"),
4060
4223
  action: z5.enum(AGENT_GIT_ACTIONS).describe(
@@ -4354,21 +4517,47 @@ async function startMcpServer() {
4354
4517
  );
4355
4518
  server.tool(
4356
4519
  "list_prs",
4357
- "List open GitHub PRs for a registered workspace. Pass repoPath from list_workspaces (uses gh against that repo remote). Then create_thread with sourceType=pr.",
4358
- { repoPath: z5.string() },
4359
- async ({ repoPath }) => {
4520
+ '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.',
4521
+ {
4522
+ repoPath: z5.string(),
4523
+ query: z5.string().optional().describe("GitHub search tokens (title, draft:true, \u2026)"),
4524
+ queue: z5.enum(["review", "mine", "approved", "changes"]).optional().describe(
4525
+ 'review = unclaimed eng-review inbox (use for "get me N tickets to review"). mine = review-requested:@me. approved / changes = eng-approved / eng-requested-changes.'
4526
+ ),
4527
+ state: z5.enum(["open", "closed", "merged", "all", "review"]).optional().describe("GitHub PR state (default open). review is an alias for queue=review."),
4528
+ label: z5.string().optional().describe(
4529
+ "GitHub label / workflow tag. Comma-separated AND. Examples: eng-review, eng-approved, eng-requested-changes"
4530
+ ),
4531
+ reviewer: z5.string().optional().describe(
4532
+ "me (review requested of you), unassigned (no individual reviewer; team queues like engineering-team still count), all, or a GitHub login"
4533
+ ),
4534
+ limit: z5.number().int().positive().max(250).optional().describe("Page size (default 40, max 250). Raise when truncated is true.")
4535
+ },
4536
+ async ({ repoPath, query, queue, state, label, reviewer, limit }) => {
4360
4537
  const root = await resolveRepoRoot(repoPath);
4361
- const prs = await listPrs(root);
4362
- return {
4363
- content: [
4364
- {
4365
- type: "text",
4366
- text: prs.map(
4367
- (p) => `#${p.number} ${p.title} (${p.headRefName})${p.isCrossRepository ? " [fork]" : ""}`
4368
- ).join("\n")
4369
- }
4370
- ]
4371
- };
4538
+ const page = clampMcpIssueLimit(limit);
4539
+ const resolved = resolveListPrsOptions({
4540
+ query,
4541
+ queue,
4542
+ state,
4543
+ labels: label,
4544
+ reviewer,
4545
+ limit: page + 1
4546
+ });
4547
+ const prs = await listPrs(root, resolved);
4548
+ const windowed = applyIssueListWindow(prs, page);
4549
+ return mcpJson(
4550
+ formatMcpPrList({
4551
+ queue: resolved.queue,
4552
+ state: resolved.state,
4553
+ labels: resolved.labels,
4554
+ reviewer: resolved.reviewer,
4555
+ query: resolved.query,
4556
+ limit: page,
4557
+ prs: windowed.items,
4558
+ truncated: windowed.truncated
4559
+ })
4560
+ );
4372
4561
  }
4373
4562
  );
4374
4563
  server.tool(
@@ -4493,28 +4682,27 @@ async function startMcpServer() {
4493
4682
  );
4494
4683
  server.tool(
4495
4684
  "list_issues",
4496
- "List or search issues from Sideboard Account connections (Linear, AbleTime MCP, or GitHub Issues; falls back to GitHub when the preferred tracker is not connected). Linear defaults to issues assigned to you; pass assignee=unassigned for no owner, assignee=all for everyone (including unassigned), or a user id / GitHub login. Optional query searches title/identifier. Linear/AbleTime are account-wide; GitHub Issues are scoped to repoPath from list_workspaces. Prefer linear_search_issues when Linear is connected and you need unassigned or other people's tickets. When AbleTime is the issue source and work has no ticket, call abletime_ensure_task (or create_thread from the default branch \u2014 Sideboard auto-creates a task to track against). Prefer list_board for Home columns. Then create_thread with sourceType=ticket.",
4685
+ "List or search issues (Linear, AbleTime, or GitHub; falls back to GitHub). Use Settings \u2192 Agents / Projects notes and roles to pick tickets relevant to the viewer (query + assignee=me or unassigned as the notes say). Default 40; pass query and/or limit (max 250) when truncated. assignee: me (Linear default), unassigned, all, or a user id. Then create_thread with sourceType=ticket.",
4497
4686
  {
4498
4687
  repoPath: z5.string(),
4499
4688
  query: z5.string().optional().describe("Search title, identifier, or description"),
4500
- assignee: z5.string().optional().describe("me (Linear default), unassigned, all, a user id, or a GitHub login")
4689
+ assignee: z5.string().optional().describe("me (Linear default), unassigned, all, a user id, or a GitHub login"),
4690
+ limit: z5.number().int().positive().max(250).optional().describe("Page size (default 40, max 250). Raise when truncated is true.")
4501
4691
  },
4502
- async ({ repoPath, query, assignee }) => {
4692
+ async ({ repoPath, query, assignee, limit }) => {
4503
4693
  const root = await resolveRepoRoot(repoPath);
4504
- const result = await listIssues(root, { query, assignee });
4505
- return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
4506
- }
4507
- );
4508
- server.tool(
4509
- "list_linear_issues",
4510
- "Deprecated: prefer list_issues. Lists assigned Linear issues via the chosen agent MCP connector",
4511
- {
4512
- agent: z5.enum(["claude", "codex", "opencode"]),
4513
- repoPath: z5.string()
4514
- },
4515
- async ({ agent, repoPath }) => {
4516
- const issues = await listLinearIssues(agent, repoPath);
4517
- return { content: [{ type: "text", text: JSON.stringify(issues, null, 2) }] };
4694
+ const page = clampMcpIssueLimit(limit);
4695
+ const result = await listIssues(root, { query, assignee, limit: page + 1 });
4696
+ const windowed = applyIssueListWindow(result.issues, page);
4697
+ return mcpJson(
4698
+ formatMcpIssueList({
4699
+ source: result.source,
4700
+ viewer: result.viewer?.name || result.viewer?.login,
4701
+ limit: page,
4702
+ issues: windowed.items,
4703
+ truncated: windowed.truncated
4704
+ })
4705
+ );
4518
4706
  }
4519
4707
  );
4520
4708
  }
@@ -6797,6 +6985,10 @@ async function startSlackRelayServer(opts) {
6797
6985
  }
6798
6986
  export {
6799
6987
  ABLETIME_MCP_PATH,
6988
+ ACCOUNT_ROLES,
6989
+ ACCOUNT_ROLE_LABELS,
6990
+ ACCOUNT_ROLE_MAX,
6991
+ ACCOUNT_ROLE_PRESETS,
6800
6992
  AGENT_GIT_ACTIONS,
6801
6993
  AGENT_RUNNER_MAX_OLD_SPACE_MB,
6802
6994
  ATTACHMENTS_DIR,
@@ -6816,6 +7008,7 @@ export {
6816
7008
  CONTEXT_KEEP_RECENT_CHARS,
6817
7009
  CONTEXT_KEEP_RECENT_MESSAGES,
6818
7010
  CONTEXT_MIN_MESSAGES,
7011
+ CONTEXT_REVIEW_PATH,
6819
7012
  CONVENTION_SETUP_RELPATHS,
6820
7013
  COORDINATOR_TOOL_PLAYBOOK,
6821
7014
  DEFAULT_ABLETIME_HOST,
@@ -6852,6 +7045,7 @@ export {
6852
7045
  PLAN_FILE_REL,
6853
7046
  PLAN_MODE_INSTRUCTION,
6854
7047
  PLAN_QUESTION_ANSWERS_PREFIX,
7048
+ PROFILE_NOTES_MAX,
6855
7049
  REPO_REVIEW_NAME,
6856
7050
  REPO_REVIEW_PATH,
6857
7051
  REVIEW_REQUEST_NAME,
@@ -6878,6 +7072,7 @@ export {
6878
7072
  WORKTREE_MCP_TOOLS,
6879
7073
  abletimeMcpRequest,
6880
7074
  abletimeMcpUrl,
7075
+ accountRoleLabel,
6881
7076
  ackSlackInboundSeen,
6882
7077
  addBoardPin,
6883
7078
  addPrStackLayer,
@@ -7012,6 +7207,7 @@ export {
7012
7207
  discoverSkills,
7013
7208
  dropCachedPrefixOnResume,
7014
7209
  emptyPublicIntegrations,
7210
+ emptySetupLog,
7015
7211
  encodeBrightsyTarget,
7016
7212
  enrichPathWithNpmGlobalBin,
7017
7213
  enrichWorkspacesWithGithub,
@@ -7022,6 +7218,7 @@ export {
7022
7218
  ensureConnectedBrightsyTeamTokens,
7023
7219
  ensureGhPreferOrigin,
7024
7220
  ensureGlobalCoordinatorCwd,
7221
+ ensureReviewGuidelinesFile,
7025
7222
  ensureReviewRequestFile,
7026
7223
  ensureReviewSkillFile,
7027
7224
  ensureSlackCoordinator,
@@ -7044,7 +7241,9 @@ export {
7044
7241
  findInvalidCacheControlTtlOrder,
7045
7242
  findLastBrightsyContextSummary,
7046
7243
  findLiveThreadForCreate,
7244
+ findLiveThreadForCreateSource,
7047
7245
  findOrphanWorktrees,
7246
+ findProjectProfileKey,
7048
7247
  findSlackCoordinator,
7049
7248
  findThreadByRef,
7050
7249
  findThreadForStackLayer,
@@ -7055,6 +7254,7 @@ export {
7055
7254
  forkChatTab,
7056
7255
  forkMessageSlice,
7057
7256
  forkThreadWorktree,
7257
+ formatAccountProfilePlaybookLine,
7058
7258
  formatAgentInstructions,
7059
7259
  formatArtifactDirective,
7060
7260
  formatBrightsyFetchError,
@@ -7071,7 +7271,9 @@ export {
7071
7271
  formatOptionalServicesReminder,
7072
7272
  formatPlanQuestionAnswers,
7073
7273
  formatPlanQuestionsForChat,
7274
+ formatPrGateDirective,
7074
7275
  formatProcessGuideDirective,
7276
+ formatProjectProfilePlaybookLines,
7075
7277
  formatRateLimitResetHint,
7076
7278
  formatRenameBranchDirective,
7077
7279
  formatScheduleWhen,
@@ -7085,6 +7287,7 @@ export {
7085
7287
  formatTranscriptMarkdown,
7086
7288
  formatUiReminder,
7087
7289
  formatWorkspaceInventory,
7290
+ formatWorkspaceProfileSuffix,
7088
7291
  formatWorktreeDirective,
7089
7292
  formatWorktreeReminder,
7090
7293
  forwardContextUsage,
@@ -7263,6 +7466,7 @@ export {
7263
7466
  mergeAgentGitAuthEnv,
7264
7467
  mergePr,
7265
7468
  mergePrStack,
7469
+ mergeSetupOutput,
7266
7470
  mergeSideboardIntoMcpServersJson,
7267
7471
  mergeUsage,
7268
7472
  messagePartParentId,
@@ -7311,6 +7515,7 @@ export {
7311
7515
  planQuestionsSignature,
7312
7516
  pollSlackOutboundWatches,
7313
7517
  posixShellSingleQuote,
7518
+ preferTeamsForRole,
7314
7519
  preferredCursorCostCents,
7315
7520
  prepareTerminalCommand,
7316
7521
  previewLand,
@@ -7319,6 +7524,7 @@ export {
7319
7524
  readExistingReviewRequestFile,
7320
7525
  readKeychainVaultKey,
7321
7526
  readPlanFile,
7527
+ readSetupLog,
7322
7528
  readSkillBody,
7323
7529
  readThread,
7324
7530
  readWorktreeFile,
@@ -7340,6 +7546,8 @@ export {
7340
7546
  requireAgent,
7341
7547
  resetGhStackDetectCache,
7342
7548
  resetGithubAgentTokenMemo,
7549
+ resolveAccountProfile,
7550
+ resolveAccountProfileFromSettings,
7343
7551
  resolveAgentExecutable,
7344
7552
  resolveAgentGitAuthEnv,
7345
7553
  resolveClaudeExecutable,
@@ -7371,7 +7579,10 @@ export {
7371
7579
  resolveThreadDefaults,
7372
7580
  resolveThreadEffort,
7373
7581
  resolveVaultKey,
7582
+ resolveViewerProfile,
7583
+ resolveViewerProfileForRepo,
7374
7584
  resolveWorktreeStartPoint,
7585
+ reviewTeamHintsForRoles,
7375
7586
  rewriteAbleTimeError,
7376
7587
  rewriteLinearError,
7377
7588
  run,
@@ -7471,6 +7682,7 @@ export {
7471
7682
  updateIntegrationsSettings,
7472
7683
  updateLinearIssue,
7473
7684
  updateOpencodeSettings,
7685
+ updateProjectProfileSettings,
7474
7686
  updateSchedule,
7475
7687
  updateThread,
7476
7688
  userClaudeMcpConfigPath,