@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.
- package/dist/{abletime-OI6FNSXX.js → abletime-GAPUN2LL.js} +4 -4
- package/dist/{abletime-CWIJ7INC.js → abletime-HTRIHTL5.js} +4 -4
- package/dist/{abletime-oauth-CHVTUZBR.js → abletime-oauth-G6ZPGVAE.js} +3 -3
- package/dist/{abletime-oauth-PUIPZTA4.js → abletime-oauth-ME7ZY2RS.js} +3 -3
- package/dist/{abletime-rest-32NIVXAY.js → abletime-rest-73EKIAZU.js} +3 -3
- package/dist/{abletime-rest-APJUKFKL.js → abletime-rest-M2D2NELV.js} +3 -3
- package/dist/{agents-G7F3BJNB.js → agents-3PQ2BWGB.js} +5 -5
- package/dist/{agents-47WI5IV2.js → agents-7SCJTTZN.js} +5 -5
- package/dist/{app-settings-VOPXJMGV.js → app-settings-2BHGANQH.js} +7 -1
- package/dist/{app-settings-652J57CX.js → app-settings-NKXH4PKM.js} +7 -1
- package/dist/{chunk-576S3HJ7.js → chunk-64NUGRZ3.js} +4 -4
- package/dist/{chunk-IMO7AZI4.js → chunk-6HIAYIXT.js} +2 -2
- package/dist/{chunk-WURF67ID.js → chunk-BEQE7VOE.js} +5 -5
- package/dist/{chunk-6I5YQTNK.js → chunk-CXTIOJRX.js} +12 -0
- package/dist/{chunk-RLNEKXXT.js → chunk-D3DYMGZS.js} +4 -4
- package/dist/{chunk-TLPJ44Y7.js → chunk-ERQYYL4I.js} +74 -23
- package/dist/{chunk-C64YQAA6.js → chunk-GFGSC4Z7.js} +3 -3
- package/dist/{chunk-43F44EKX.js → chunk-GVAR6R6R.js} +2 -2
- package/dist/{chunk-QFRX5S2E.js → chunk-KFXP4KSP.js} +143 -24
- package/dist/{chunk-G45QP2ZD.js → chunk-LPS6D346.js} +3 -3
- package/dist/{chunk-7HOKP4GR.js → chunk-PELMZRDB.js} +12 -0
- package/dist/{chunk-PPJ5JTWA.js → chunk-QVQPIFBV.js} +28 -2
- package/dist/{chunk-QNJXJIWJ.js → chunk-RF46WMSI.js} +5 -5
- package/dist/{chunk-GFRC6JQN.js → chunk-U2ZZMGPV.js} +4 -4
- package/dist/{chunk-HRWCW6LC.js → chunk-UVWIYSAA.js} +4 -4
- package/dist/{chunk-E6C5NR46.js → chunk-W4F7JKXF.js} +20 -6
- package/dist/{chunk-YLGBQVRK.js → chunk-XEBQRCDW.js} +28 -2
- package/dist/{chunk-5ZFULOTC.js → chunk-XM4UIFQU.js} +20 -6
- package/dist/{chunk-BL2UGKWU.js → chunk-Z7QWXE4W.js} +3 -3
- package/dist/{coordinator-prompt-ZBYRREHD.js → coordinator-prompt-BFO2TAVR.js} +4 -4
- package/dist/{coordinator-prompt-WQIICPT6.js → coordinator-prompt-IG676OSP.js} +4 -4
- package/dist/{global-workspace-3SQU4GL4.js → global-workspace-J6H7X5SM.js} +4 -4
- package/dist/{global-workspace-2N6KISDO.js → global-workspace-RLCICVQE.js} +4 -4
- package/dist/index.cjs +193 -14
- package/dist/index.d.cts +66 -2
- package/dist/index.d.ts +66 -2
- package/dist/index.js +27 -16
- package/dist/mcp/run-stdio.cjs +117 -14
- package/dist/mcp/run-stdio.js +17 -15
- package/dist/{orchestrator-DPMS5KMY.js → orchestrator-2NZUV4LI.js} +6 -6
- package/dist/{orchestrator-2QGJ7CW2.js → orchestrator-JCETTHVV.js} +6 -6
- package/dist/{thread-store-JQB7KZJR.js → thread-store-BEBZMOS7.js} +1 -1
- package/dist/{thread-store-SCV2IZYS.js → thread-store-S6PJADDM.js} +1 -1
- package/dist/{workspaces-QLKWW3O2.js → workspaces-NJF3GG5F.js} +4 -4
- package/dist/{workspaces-CFI7XVAE.js → workspaces-OLBW42V3.js} +4 -4
- package/dist/{worktree-PK3QETXO.js → worktree-2FYRYJTB.js} +3 -3
- package/dist/{worktree-4UAOZUJ4.js → worktree-UKLK7VHH.js} +3 -3
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1365,6 +1365,7 @@ __export(app_settings_exports, {
|
|
|
1365
1365
|
HARNESS_ENV_KEYS: () => HARNESS_ENV_KEYS,
|
|
1366
1366
|
ISSUE_SOURCE_LABELS: () => ISSUE_SOURCE_LABELS,
|
|
1367
1367
|
PROFILE_NOTES_MAX: () => PROFILE_NOTES_MAX,
|
|
1368
|
+
REVIEW_LABEL_MAX: () => REVIEW_LABEL_MAX,
|
|
1368
1369
|
USAGE_ON_LIMIT_VALUES: () => USAGE_ON_LIMIT_VALUES,
|
|
1369
1370
|
agentDoneSound: () => agentDoneSound,
|
|
1370
1371
|
appSettingsPath: () => appSettingsPath,
|
|
@@ -1421,6 +1422,7 @@ __export(app_settings_exports, {
|
|
|
1421
1422
|
issueSourceLabel: () => issueSourceLabel,
|
|
1422
1423
|
loadAppSettings: () => loadAppSettings,
|
|
1423
1424
|
maxConcurrentAgents: () => maxConcurrentAgents,
|
|
1425
|
+
normalizeReviewLabel: () => normalizeReviewLabel,
|
|
1424
1426
|
orchestrationQuotaFallbackAgent: () => orchestrationQuotaFallbackAgent,
|
|
1425
1427
|
orchestrationQuotaOnLimit: () => orchestrationQuotaOnLimit,
|
|
1426
1428
|
readViewerContext: () => readViewerContext,
|
|
@@ -1432,6 +1434,7 @@ __export(app_settings_exports, {
|
|
|
1432
1434
|
resolveNewOrchestratorOptions: () => resolveNewOrchestratorOptions,
|
|
1433
1435
|
resolveNewThreadOptions: () => resolveNewThreadOptions,
|
|
1434
1436
|
resolveOrchestratorDefaults: () => resolveOrchestratorDefaults,
|
|
1437
|
+
resolveProjectReviewLabel: () => resolveProjectReviewLabel,
|
|
1435
1438
|
resolveThreadDefaults: () => resolveThreadDefaults,
|
|
1436
1439
|
resolveUsageOnLimit: () => resolveUsageOnLimit,
|
|
1437
1440
|
resolveViewerProfile: () => resolveViewerProfile,
|
|
@@ -1764,13 +1767,25 @@ function normalizeDefaults(raw) {
|
|
|
1764
1767
|
function profileRepoKey(path2) {
|
|
1765
1768
|
return path2.trim().replace(/\/+$/, "");
|
|
1766
1769
|
}
|
|
1770
|
+
function normalizeReviewLabel(value) {
|
|
1771
|
+
const label = (value ?? "").trim().replace(/^:+/, "").slice(0, REVIEW_LABEL_MAX);
|
|
1772
|
+
if (!label || /[,|]/.test(label)) return "";
|
|
1773
|
+
return label;
|
|
1774
|
+
}
|
|
1775
|
+
function projectProfileHasFields(profile) {
|
|
1776
|
+
return Boolean(profile.notes || profile.reviewLabel);
|
|
1777
|
+
}
|
|
1767
1778
|
function normalizeProjectProfile(raw) {
|
|
1768
1779
|
if (!raw || typeof raw !== "object") return void 0;
|
|
1769
1780
|
const source = raw;
|
|
1770
1781
|
const out = {};
|
|
1771
1782
|
const notes = foldLegacyRolesIntoNotes(source.roles, source.role, source.notes);
|
|
1772
1783
|
if (notes) out.notes = notes;
|
|
1773
|
-
|
|
1784
|
+
const reviewLabel = normalizeReviewLabel(
|
|
1785
|
+
typeof source.reviewLabel === "string" ? source.reviewLabel : null
|
|
1786
|
+
);
|
|
1787
|
+
if (reviewLabel) out.reviewLabel = reviewLabel;
|
|
1788
|
+
return projectProfileHasFields(out) ? out : void 0;
|
|
1774
1789
|
}
|
|
1775
1790
|
function normalizeProjects(raw) {
|
|
1776
1791
|
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return {};
|
|
@@ -2443,12 +2458,22 @@ function updateProjectProfileSettings(repoPath, patch) {
|
|
|
2443
2458
|
if (!notes) delete next.notes;
|
|
2444
2459
|
else next.notes = notes;
|
|
2445
2460
|
}
|
|
2461
|
+
if ("reviewLabel" in patch) {
|
|
2462
|
+
const reviewLabel = normalizeReviewLabel(patch.reviewLabel);
|
|
2463
|
+
if (!reviewLabel) delete next.reviewLabel;
|
|
2464
|
+
else next.reviewLabel = reviewLabel;
|
|
2465
|
+
}
|
|
2446
2466
|
delete next.roles;
|
|
2447
2467
|
delete next.role;
|
|
2448
|
-
if (!next
|
|
2468
|
+
if (!projectProfileHasFields(next)) delete projects[key];
|
|
2449
2469
|
else projects[key] = next;
|
|
2450
2470
|
return saveAppSettings({ ...current, projects });
|
|
2451
2471
|
}
|
|
2472
|
+
function resolveProjectReviewLabel(settings, repoPath) {
|
|
2473
|
+
const key = findProjectProfileKey(settings.projects, repoPath);
|
|
2474
|
+
if (!key) return "";
|
|
2475
|
+
return settings.projects[key]?.reviewLabel?.trim() || "";
|
|
2476
|
+
}
|
|
2452
2477
|
function getDefaultAgent(settings = loadAppSettings()) {
|
|
2453
2478
|
return settings.defaults.agent ?? "claude";
|
|
2454
2479
|
}
|
|
@@ -2973,7 +2998,7 @@ function childEnvWithAppSettings(extra) {
|
|
|
2973
2998
|
function harnessEnvKey(harness) {
|
|
2974
2999
|
return HARNESS_ENV_KEYS[harness];
|
|
2975
3000
|
}
|
|
2976
|
-
var import_node_crypto2, import_node_fs8, import_node_os3, import_node_path9, 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;
|
|
3001
|
+
var import_node_crypto2, import_node_fs8, import_node_os3, import_node_path9, 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;
|
|
2977
3002
|
var init_app_settings = __esm({
|
|
2978
3003
|
"src/store/app-settings.ts"() {
|
|
2979
3004
|
"use strict";
|
|
@@ -3030,6 +3055,7 @@ var init_app_settings = __esm({
|
|
|
3030
3055
|
]);
|
|
3031
3056
|
ISSUE_SOURCES = /* @__PURE__ */ new Set(["linear", "github", "abletime"]);
|
|
3032
3057
|
GIT_AUTH_MODES = new Set(GITHUB_GIT_AUTH_MODES);
|
|
3058
|
+
REVIEW_LABEL_MAX = 50;
|
|
3033
3059
|
EMPTY_SETTINGS = {
|
|
3034
3060
|
environment: {},
|
|
3035
3061
|
claude: {},
|
|
@@ -3315,6 +3341,12 @@ function normalizeThread(raw) {
|
|
|
3315
3341
|
prTitle: raw.prTitle ?? null,
|
|
3316
3342
|
prState: raw.prState ?? null,
|
|
3317
3343
|
prIsDraft: Boolean(raw.prIsDraft),
|
|
3344
|
+
prReviewDecision: raw.prReviewDecision ?? null,
|
|
3345
|
+
prMergeable: raw.prMergeable ?? null,
|
|
3346
|
+
prMergeStateStatus: raw.prMergeStateStatus ?? null,
|
|
3347
|
+
prIsInMergeQueue: Boolean(raw.prIsInMergeQueue),
|
|
3348
|
+
prLabels: Array.isArray(raw.prLabels) ? raw.prLabels : [],
|
|
3349
|
+
prChecksFailed: typeof raw.prChecksFailed === "boolean" ? raw.prChecksFailed : void 0,
|
|
3318
3350
|
skipAutoArchiveOnMerge: Boolean(raw.skipAutoArchiveOnMerge),
|
|
3319
3351
|
cowboy: Boolean(raw.cowboy),
|
|
3320
3352
|
stackId: raw.stackId ?? null,
|
|
@@ -3350,6 +3382,12 @@ function createEmptyThread(partial) {
|
|
|
3350
3382
|
prIsDraft: Boolean(partial.prIsDraft),
|
|
3351
3383
|
prAuthorLogin: partial.prAuthorLogin?.trim() || null,
|
|
3352
3384
|
prReviewerLogins: partial.prReviewerLogins ?? [],
|
|
3385
|
+
prReviewDecision: partial.prReviewDecision ?? null,
|
|
3386
|
+
prMergeable: partial.prMergeable ?? null,
|
|
3387
|
+
prMergeStateStatus: partial.prMergeStateStatus ?? null,
|
|
3388
|
+
prIsInMergeQueue: Boolean(partial.prIsInMergeQueue),
|
|
3389
|
+
prLabels: partial.prLabels ?? [],
|
|
3390
|
+
prChecksFailed: partial.prChecksFailed,
|
|
3353
3391
|
skipAutoArchiveOnMerge: partial.skipAutoArchiveOnMerge ?? false,
|
|
3354
3392
|
cowboy: Boolean(partial.cowboy),
|
|
3355
3393
|
stackId: partial.stackId ?? null,
|
|
@@ -5823,6 +5861,72 @@ function classifyWorktreeColumn(group) {
|
|
|
5823
5861
|
}
|
|
5824
5862
|
return "new";
|
|
5825
5863
|
}
|
|
5864
|
+
function labelsInclude(labels, name) {
|
|
5865
|
+
const want = name.trim().toLowerCase();
|
|
5866
|
+
if (!want) return false;
|
|
5867
|
+
return (labels ?? []).some((label) => label.trim().toLowerCase() === want);
|
|
5868
|
+
}
|
|
5869
|
+
function reviewLabelForRepo(labelsByRepo, repoPath) {
|
|
5870
|
+
const want = repoPath.trim().replace(/\/+$/, "");
|
|
5871
|
+
if (!want || !labelsByRepo) return "";
|
|
5872
|
+
const direct = labelsByRepo[want]?.trim();
|
|
5873
|
+
if (direct) return direct;
|
|
5874
|
+
let best = "";
|
|
5875
|
+
let bestLen = 0;
|
|
5876
|
+
for (const [key, label] of Object.entries(labelsByRepo)) {
|
|
5877
|
+
const stored = key.trim().replace(/\/+$/, "");
|
|
5878
|
+
const value = label.trim();
|
|
5879
|
+
if (!stored || !value) continue;
|
|
5880
|
+
if (stored === want || want.startsWith(`${stored}/`)) {
|
|
5881
|
+
if (stored.length > bestLen) {
|
|
5882
|
+
best = value;
|
|
5883
|
+
bestLen = stored.length;
|
|
5884
|
+
}
|
|
5885
|
+
}
|
|
5886
|
+
}
|
|
5887
|
+
return best;
|
|
5888
|
+
}
|
|
5889
|
+
function groupPrLabels(group) {
|
|
5890
|
+
const out = [];
|
|
5891
|
+
const seen = /* @__PURE__ */ new Set();
|
|
5892
|
+
for (const thread of group) {
|
|
5893
|
+
for (const label of thread.prLabels ?? []) {
|
|
5894
|
+
const key = label.trim().toLowerCase();
|
|
5895
|
+
if (!key || seen.has(key)) continue;
|
|
5896
|
+
seen.add(key);
|
|
5897
|
+
out.push(label.trim());
|
|
5898
|
+
}
|
|
5899
|
+
}
|
|
5900
|
+
return out;
|
|
5901
|
+
}
|
|
5902
|
+
function classifyWorktreeListBadges(group, viewerLogin = "", reviewLabel = "") {
|
|
5903
|
+
if (group.length === 0 || group.some((t) => t.cowboy)) return [];
|
|
5904
|
+
const open = group.filter((t) => isOpenPrState(t.prUrl, t.prState));
|
|
5905
|
+
if (open.length === 0) return [];
|
|
5906
|
+
const ownership = classifyWorktreeOwnership(group, viewerLogin);
|
|
5907
|
+
if (ownership === "reviewing") {
|
|
5908
|
+
return [
|
|
5909
|
+
{
|
|
5910
|
+
id: "review",
|
|
5911
|
+
label: "review",
|
|
5912
|
+
title: "Someone else's PR",
|
|
5913
|
+
mod: "is-review"
|
|
5914
|
+
}
|
|
5915
|
+
];
|
|
5916
|
+
}
|
|
5917
|
+
const draft = open.some((t) => t.prIsDraft);
|
|
5918
|
+
const readyLabel = reviewLabel.trim();
|
|
5919
|
+
const inReview = readyLabel ? labelsInclude(groupPrLabels(group), readyLabel) : !draft;
|
|
5920
|
+
if (!inReview) return [];
|
|
5921
|
+
return [
|
|
5922
|
+
{
|
|
5923
|
+
id: "pending",
|
|
5924
|
+
label: "pending",
|
|
5925
|
+
title: "Waiting for review",
|
|
5926
|
+
mod: "is-pending"
|
|
5927
|
+
}
|
|
5928
|
+
];
|
|
5929
|
+
}
|
|
5826
5930
|
function worktreeBoardStatus(group) {
|
|
5827
5931
|
const order = ["running", "queued", "error", "broken"];
|
|
5828
5932
|
for (const status of order) {
|
|
@@ -7996,6 +8100,10 @@ function normalizePrListQueue(queue, state) {
|
|
|
7996
8100
|
}
|
|
7997
8101
|
return void 0;
|
|
7998
8102
|
}
|
|
8103
|
+
function reviewQueueLabel(reviewLabel) {
|
|
8104
|
+
const label = (reviewLabel ?? "").trim();
|
|
8105
|
+
return label || QUEUE_DEFAULTS.review.labels[0];
|
|
8106
|
+
}
|
|
7999
8107
|
function ticketRefsFromPrTitle(title) {
|
|
8000
8108
|
const out = [];
|
|
8001
8109
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -8013,10 +8121,12 @@ function resolveListPrsOptions(opts) {
|
|
|
8013
8121
|
const defaults = queue ? QUEUE_DEFAULTS[queue] : void 0;
|
|
8014
8122
|
const stateIsQueueAlias = Boolean(normalizePrListQueue(void 0, opts?.state));
|
|
8015
8123
|
const labels = normalizePrLabels(opts?.labels);
|
|
8124
|
+
const readyLabel = reviewQueueLabel(opts?.reviewLabel);
|
|
8125
|
+
const queueLabels = queue === "review" || queue === "mine" ? [readyLabel] : defaults?.labels ?? [];
|
|
8016
8126
|
return {
|
|
8017
8127
|
...queue ? { queue } : {},
|
|
8018
8128
|
state: normalizePrListState(stateIsQueueAlias ? defaults?.state : opts?.state ?? defaults?.state),
|
|
8019
|
-
labels: labels.length ? labels :
|
|
8129
|
+
labels: labels.length ? labels : queueLabels,
|
|
8020
8130
|
...opts?.reviewer?.trim() ? { reviewer: opts.reviewer.trim() } : defaults?.reviewer ? { reviewer: defaults.reviewer } : {},
|
|
8021
8131
|
...opts?.query?.trim() ? { query: opts.query.trim() } : {},
|
|
8022
8132
|
...opts?.draft !== void 0 ? { draft: opts.draft } : defaults?.draft !== void 0 ? { draft: defaults.draft } : {},
|
|
@@ -8377,6 +8487,12 @@ function prIsInMergeQueue(gate) {
|
|
|
8377
8487
|
if (gate.isInMergeQueue) return true;
|
|
8378
8488
|
return (gate.mergeStateStatus ?? "").toUpperCase() === "QUEUED";
|
|
8379
8489
|
}
|
|
8490
|
+
function ciChecksFailed(checks) {
|
|
8491
|
+
if (!checks?.length) return false;
|
|
8492
|
+
return checks.some(
|
|
8493
|
+
(check) => (!check.kind || check.kind === "ci") && check.bucket === "fail"
|
|
8494
|
+
);
|
|
8495
|
+
}
|
|
8380
8496
|
function buildMergeGateChecks(gate, opts = {}) {
|
|
8381
8497
|
const rows = [];
|
|
8382
8498
|
const base = gate.baseRefName?.trim() || "the base branch";
|
|
@@ -9284,7 +9400,7 @@ async function getPrMeta(cwd, selector) {
|
|
|
9284
9400
|
"view",
|
|
9285
9401
|
selector,
|
|
9286
9402
|
"--json",
|
|
9287
|
-
"number,title,url,state,isDraft,reviewDecision,baseRefName,headRefName,isInMergeQueue,mergeStateStatus,mergeable,author,reviewRequests"
|
|
9403
|
+
"number,title,url,state,isDraft,reviewDecision,baseRefName,headRefName,isInMergeQueue,mergeStateStatus,mergeable,author,reviewRequests,labels"
|
|
9288
9404
|
];
|
|
9289
9405
|
if (slug) viewArgs.push("--repo", slug);
|
|
9290
9406
|
let { stdout, exitCode, stderr } = await gh(viewArgs, cwd, { reject: false });
|
|
@@ -9294,7 +9410,7 @@ async function getPrMeta(cwd, selector) {
|
|
|
9294
9410
|
"view",
|
|
9295
9411
|
selector,
|
|
9296
9412
|
"--json",
|
|
9297
|
-
"number,title,url,state,isDraft,reviewDecision,baseRefName,headRefName,mergeStateStatus,mergeable,author,reviewRequests"
|
|
9413
|
+
"number,title,url,state,isDraft,reviewDecision,baseRefName,headRefName,mergeStateStatus,mergeable,author,reviewRequests,labels"
|
|
9298
9414
|
];
|
|
9299
9415
|
if (slug) retry.push("--repo", slug);
|
|
9300
9416
|
({ stdout, exitCode, stderr } = await gh(retry, cwd, { reject: false }));
|
|
@@ -9329,7 +9445,8 @@ async function getPrMeta(cwd, selector) {
|
|
|
9329
9445
|
mergeable: resolved.mergeable,
|
|
9330
9446
|
mergeStateStatus: resolved.mergeStateStatus,
|
|
9331
9447
|
authorLogin: author.login?.trim() || null,
|
|
9332
|
-
reviewerLogins: humanReviewerLogins(view.reviewRequests)
|
|
9448
|
+
reviewerLogins: humanReviewerLogins(view.reviewRequests),
|
|
9449
|
+
labels: labelNames(view.labels)
|
|
9333
9450
|
};
|
|
9334
9451
|
} catch {
|
|
9335
9452
|
return null;
|
|
@@ -10562,7 +10679,7 @@ var init_coordinator_prompt = __esm({
|
|
|
10562
10679
|
"Discover:",
|
|
10563
10680
|
"- 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.",
|
|
10564
10681
|
"- 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.",
|
|
10565
|
-
|
|
10682
|
+
`- 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).`,
|
|
10566
10683
|
"- 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.",
|
|
10567
10684
|
"- 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.",
|
|
10568
10685
|
"- 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.",
|
|
@@ -16634,11 +16751,41 @@ function threadPrMetaPatch(thread, meta) {
|
|
|
16634
16751
|
if (!sameLoginList(nextReviewers, thread.prReviewerLogins)) {
|
|
16635
16752
|
patch.prReviewerLogins = nextReviewers;
|
|
16636
16753
|
}
|
|
16754
|
+
const nextDecision = meta.reviewDecision ?? null;
|
|
16755
|
+
if ((thread.prReviewDecision ?? null) !== nextDecision) {
|
|
16756
|
+
patch.prReviewDecision = nextDecision;
|
|
16757
|
+
}
|
|
16758
|
+
const nextMergeable = meta.mergeable ?? null;
|
|
16759
|
+
if ((thread.prMergeable ?? null) !== nextMergeable) {
|
|
16760
|
+
patch.prMergeable = nextMergeable;
|
|
16761
|
+
}
|
|
16762
|
+
const nextMergeState = meta.mergeStateStatus ?? null;
|
|
16763
|
+
if ((thread.prMergeStateStatus ?? null) !== nextMergeState) {
|
|
16764
|
+
patch.prMergeStateStatus = nextMergeState;
|
|
16765
|
+
}
|
|
16766
|
+
const nextQueued = Boolean(meta.isInMergeQueue);
|
|
16767
|
+
if (Boolean(thread.prIsInMergeQueue) !== nextQueued) {
|
|
16768
|
+
patch.prIsInMergeQueue = nextQueued;
|
|
16769
|
+
}
|
|
16770
|
+
const nextLabels = meta.labels ?? [];
|
|
16771
|
+
if (!sameLoginList(nextLabels, thread.prLabels)) {
|
|
16772
|
+
patch.prLabels = nextLabels;
|
|
16773
|
+
}
|
|
16774
|
+
const mergeState = (nextMergeState ?? "").toUpperCase();
|
|
16775
|
+
if (mergeState === "CLEAN" && thread.prChecksFailed) {
|
|
16776
|
+
patch.prChecksFailed = false;
|
|
16777
|
+
} else if ((mergeState === "UNSTABLE" || mergeState === "BLOCKED" && (nextDecision ?? "").toUpperCase() === "APPROVED") && !thread.prChecksFailed) {
|
|
16778
|
+
patch.prChecksFailed = true;
|
|
16779
|
+
}
|
|
16637
16780
|
if (thread.skipAutoArchiveOnMerge && nextState && nextState !== "MERGED" && nextState !== "CLOSED") {
|
|
16638
16781
|
patch.skipAutoArchiveOnMerge = false;
|
|
16639
16782
|
}
|
|
16640
16783
|
return patch;
|
|
16641
16784
|
}
|
|
16785
|
+
function threadPrChecksFailedPatch(thread, failed) {
|
|
16786
|
+
if (thread.prChecksFailed === failed) return {};
|
|
16787
|
+
return { prChecksFailed: failed };
|
|
16788
|
+
}
|
|
16642
16789
|
function shouldAutoArchiveOnPrMerge(opts) {
|
|
16643
16790
|
if (!opts.autoArchiveEnabled) return false;
|
|
16644
16791
|
if (opts.isGlobal) return false;
|
|
@@ -17242,6 +17389,12 @@ function worktreeBindingFrom(from) {
|
|
|
17242
17389
|
prIsDraft: from.prIsDraft,
|
|
17243
17390
|
prAuthorLogin: from.prAuthorLogin,
|
|
17244
17391
|
prReviewerLogins: from.prReviewerLogins,
|
|
17392
|
+
prReviewDecision: from.prReviewDecision,
|
|
17393
|
+
prMergeable: from.prMergeable,
|
|
17394
|
+
prMergeStateStatus: from.prMergeStateStatus,
|
|
17395
|
+
prIsInMergeQueue: from.prIsInMergeQueue,
|
|
17396
|
+
prLabels: from.prLabels,
|
|
17397
|
+
prChecksFailed: from.prChecksFailed,
|
|
17245
17398
|
skipAutoArchiveOnMerge: from.skipAutoArchiveOnMerge,
|
|
17246
17399
|
stackId: from.stackId,
|
|
17247
17400
|
stackLayer: from.stackLayer,
|
|
@@ -20725,6 +20878,7 @@ async function createThread(input, _onSetupLine) {
|
|
|
20725
20878
|
let prUrl = null;
|
|
20726
20879
|
let prTitle = null;
|
|
20727
20880
|
let prAuthorLogin2 = null;
|
|
20881
|
+
let prLabels = [];
|
|
20728
20882
|
if (sourceType === "pr") {
|
|
20729
20883
|
const num2 = Number(input.sourceRef.replace(/^#/, ""));
|
|
20730
20884
|
if (!Number.isFinite(num2)) throw new Error(`Invalid PR number: ${input.sourceRef}`);
|
|
@@ -20741,6 +20895,7 @@ async function createThread(input, _onSetupLine) {
|
|
|
20741
20895
|
sourceIsFork = pr.isCrossRepository;
|
|
20742
20896
|
prUrl = pr.url;
|
|
20743
20897
|
prAuthorLogin2 = pr.author?.login?.trim() || null;
|
|
20898
|
+
prLabels = pr.labels ?? [];
|
|
20744
20899
|
const localFetchBranch = `sideboard-pr-${pr.number}`;
|
|
20745
20900
|
await fetchPrHead(repoPath, pr.number, localFetchBranch);
|
|
20746
20901
|
sourceRef = localFetchBranch;
|
|
@@ -20764,6 +20919,7 @@ async function createThread(input, _onSetupLine) {
|
|
|
20764
20919
|
prUrl = existing.url;
|
|
20765
20920
|
prTitle = existing.title;
|
|
20766
20921
|
prAuthorLogin2 = existing.author?.login?.trim() || null;
|
|
20922
|
+
prLabels = existing.labels ?? [];
|
|
20767
20923
|
}
|
|
20768
20924
|
}
|
|
20769
20925
|
}
|
|
@@ -20799,7 +20955,8 @@ async function createThread(input, _onSetupLine) {
|
|
|
20799
20955
|
status: "idle",
|
|
20800
20956
|
prUrl,
|
|
20801
20957
|
prTitle,
|
|
20802
|
-
prAuthorLogin: prAuthorLogin2
|
|
20958
|
+
prAuthorLogin: prAuthorLogin2,
|
|
20959
|
+
prLabels
|
|
20803
20960
|
});
|
|
20804
20961
|
writeThread(thread);
|
|
20805
20962
|
await ensureWorkspace(repoPath);
|
|
@@ -24255,6 +24412,7 @@ var init_orchestrator = __esm({
|
|
|
24255
24412
|
init_stack();
|
|
24256
24413
|
init_agent_git_actions();
|
|
24257
24414
|
init_pr_merge_archive();
|
|
24415
|
+
init_pr_gates();
|
|
24258
24416
|
init_conductor();
|
|
24259
24417
|
init_dev_preview();
|
|
24260
24418
|
init_setup_log();
|
|
@@ -26451,10 +26609,20 @@ var init_orchestrator = __esm({
|
|
|
26451
26609
|
return { thread, selectors: connectedPrSelectors(thread, headUrl), cwd, headUrl };
|
|
26452
26610
|
}
|
|
26453
26611
|
async getPrChecks(threadRef) {
|
|
26454
|
-
const { selectors, cwd } = await this.withPrSelector(threadRef);
|
|
26612
|
+
const { thread, selectors, cwd } = await this.withPrSelector(threadRef);
|
|
26455
26613
|
for (const selector of selectors) {
|
|
26456
26614
|
const checks = await getPrChecks(cwd, selector);
|
|
26457
|
-
if (checks)
|
|
26615
|
+
if (!checks) continue;
|
|
26616
|
+
const live = this.requireThread(thread.id);
|
|
26617
|
+
const failed = ciChecksFailed(checks);
|
|
26618
|
+
const siblings = threadsSharingWorktree(live.worktreePath);
|
|
26619
|
+
const targets = siblings.length > 0 ? siblings : [live];
|
|
26620
|
+
for (const t of targets) {
|
|
26621
|
+
const patch = threadPrChecksFailedPatch(t, failed);
|
|
26622
|
+
if (Object.keys(patch).length === 0) continue;
|
|
26623
|
+
updateThread(t.id, patch);
|
|
26624
|
+
}
|
|
26625
|
+
return checks;
|
|
26458
26626
|
}
|
|
26459
26627
|
return null;
|
|
26460
26628
|
}
|
|
@@ -27127,6 +27295,7 @@ __export(index_exports, {
|
|
|
27127
27295
|
PR_DETAILS_JSON_FIELDS: () => PR_DETAILS_JSON_FIELDS,
|
|
27128
27296
|
REPO_REVIEW_NAME: () => REPO_REVIEW_NAME,
|
|
27129
27297
|
REPO_REVIEW_PATH: () => REPO_REVIEW_PATH,
|
|
27298
|
+
REVIEW_LABEL_MAX: () => REVIEW_LABEL_MAX,
|
|
27130
27299
|
REVIEW_REQUEST_NAME: () => REVIEW_REQUEST_NAME,
|
|
27131
27300
|
REVIEW_REQUEST_PATH: () => REVIEW_REQUEST_PATH,
|
|
27132
27301
|
REVIEW_REQUEST_PREFILL: () => REVIEW_REQUEST_PREFILL,
|
|
@@ -27258,6 +27427,7 @@ __export(index_exports, {
|
|
|
27258
27427
|
clampHistoryMaxDays: () => clampHistoryMaxDays,
|
|
27259
27428
|
classifyRunScriptPreview: () => classifyRunScriptPreview,
|
|
27260
27429
|
classifyWorktreeColumn: () => classifyWorktreeColumn,
|
|
27430
|
+
classifyWorktreeListBadges: () => classifyWorktreeListBadges,
|
|
27261
27431
|
claudeAdapter: () => claudeAdapter,
|
|
27262
27432
|
claudeChromeEnabled: () => claudeChromeEnabled,
|
|
27263
27433
|
claudeUsageOverLimitWindows: () => claudeUsageOverLimitWindows,
|
|
@@ -27698,6 +27868,7 @@ __export(index_exports, {
|
|
|
27698
27868
|
normalizeCodeSelection: () => normalizeCodeSelection,
|
|
27699
27869
|
normalizeLinearRelationType: () => normalizeLinearRelationType,
|
|
27700
27870
|
normalizeParseResult: () => normalizeParseResult,
|
|
27871
|
+
normalizeReviewLabel: () => normalizeReviewLabel,
|
|
27701
27872
|
normalizeServiceOrigin: () => normalizeServiceOrigin,
|
|
27702
27873
|
normalizeThinkingEffort: () => normalizeThinkingEffort,
|
|
27703
27874
|
normalizeThread: () => normalizeThread,
|
|
@@ -27825,6 +27996,7 @@ __export(index_exports, {
|
|
|
27825
27996
|
resolvePlanMarkdown: () => resolvePlanMarkdown,
|
|
27826
27997
|
resolvePrSelector: () => resolvePrSelector,
|
|
27827
27998
|
resolvePrSelectors: () => resolvePrSelectors,
|
|
27999
|
+
resolveProjectReviewLabel: () => resolveProjectReviewLabel,
|
|
27828
28000
|
resolveQuotaFallbackAgent: () => resolveQuotaFallbackAgent,
|
|
27829
28001
|
resolveRepoRoot: () => resolveRepoRoot,
|
|
27830
28002
|
resolveReviewGuidelines: () => resolveReviewGuidelines,
|
|
@@ -27839,6 +28011,7 @@ __export(index_exports, {
|
|
|
27839
28011
|
resolveViewerProfile: () => resolveViewerProfile,
|
|
27840
28012
|
resolveViewerProfileForRepo: () => resolveViewerProfileForRepo,
|
|
27841
28013
|
resolveWorktreeStartPoint: () => resolveWorktreeStartPoint,
|
|
28014
|
+
reviewLabelForRepo: () => reviewLabelForRepo,
|
|
27842
28015
|
rewriteAbleTimeError: () => rewriteAbleTimeError,
|
|
27843
28016
|
rewriteLinearError: () => rewriteLinearError,
|
|
27844
28017
|
run: () => run,
|
|
@@ -34398,12 +34571,12 @@ async function startMcpServer() {
|
|
|
34398
34571
|
);
|
|
34399
34572
|
server.tool(
|
|
34400
34573
|
"list_prs",
|
|
34401
|
-
|
|
34574
|
+
`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.`,
|
|
34402
34575
|
{
|
|
34403
34576
|
repoPath: import_zod9.z.string(),
|
|
34404
34577
|
query: import_zod9.z.string().optional().describe("GitHub search tokens (title, draft:true, \u2026)"),
|
|
34405
34578
|
queue: import_zod9.z.enum(["review", "mine", "approved", "changes"]).optional().describe(
|
|
34406
|
-
|
|
34579
|
+
"review = unclaimed ready-for-review inbox (Settings \u2192 Projects label, default eng-review). mine = review-requested:@me. approved / changes = eng-approved / eng-requested-changes."
|
|
34407
34580
|
),
|
|
34408
34581
|
state: import_zod9.z.enum(["open", "closed", "merged", "all", "review"]).optional().describe("GitHub PR state (default open). review is an alias for queue=review."),
|
|
34409
34582
|
label: import_zod9.z.string().optional().describe(
|
|
@@ -34423,7 +34596,8 @@ async function startMcpServer() {
|
|
|
34423
34596
|
state,
|
|
34424
34597
|
labels: label,
|
|
34425
34598
|
reviewer,
|
|
34426
|
-
limit: page + 1
|
|
34599
|
+
limit: page + 1,
|
|
34600
|
+
reviewLabel: resolveProjectReviewLabel(loadAppSettings(), root)
|
|
34427
34601
|
});
|
|
34428
34602
|
const prs = await listPrs(root, resolved);
|
|
34429
34603
|
const windowed = applyIssueListWindow(prs, page);
|
|
@@ -36957,6 +37131,7 @@ async function startSlackRelayServer(opts) {
|
|
|
36957
37131
|
PR_DETAILS_JSON_FIELDS,
|
|
36958
37132
|
REPO_REVIEW_NAME,
|
|
36959
37133
|
REPO_REVIEW_PATH,
|
|
37134
|
+
REVIEW_LABEL_MAX,
|
|
36960
37135
|
REVIEW_REQUEST_NAME,
|
|
36961
37136
|
REVIEW_REQUEST_PATH,
|
|
36962
37137
|
REVIEW_REQUEST_PREFILL,
|
|
@@ -37088,6 +37263,7 @@ async function startSlackRelayServer(opts) {
|
|
|
37088
37263
|
clampHistoryMaxDays,
|
|
37089
37264
|
classifyRunScriptPreview,
|
|
37090
37265
|
classifyWorktreeColumn,
|
|
37266
|
+
classifyWorktreeListBadges,
|
|
37091
37267
|
claudeAdapter,
|
|
37092
37268
|
claudeChromeEnabled,
|
|
37093
37269
|
claudeUsageOverLimitWindows,
|
|
@@ -37528,6 +37704,7 @@ async function startSlackRelayServer(opts) {
|
|
|
37528
37704
|
normalizeCodeSelection,
|
|
37529
37705
|
normalizeLinearRelationType,
|
|
37530
37706
|
normalizeParseResult,
|
|
37707
|
+
normalizeReviewLabel,
|
|
37531
37708
|
normalizeServiceOrigin,
|
|
37532
37709
|
normalizeThinkingEffort,
|
|
37533
37710
|
normalizeThread,
|
|
@@ -37655,6 +37832,7 @@ async function startSlackRelayServer(opts) {
|
|
|
37655
37832
|
resolvePlanMarkdown,
|
|
37656
37833
|
resolvePrSelector,
|
|
37657
37834
|
resolvePrSelectors,
|
|
37835
|
+
resolveProjectReviewLabel,
|
|
37658
37836
|
resolveQuotaFallbackAgent,
|
|
37659
37837
|
resolveRepoRoot,
|
|
37660
37838
|
resolveReviewGuidelines,
|
|
@@ -37669,6 +37847,7 @@ async function startSlackRelayServer(opts) {
|
|
|
37669
37847
|
resolveViewerProfile,
|
|
37670
37848
|
resolveViewerProfileForRepo,
|
|
37671
37849
|
resolveWorktreeStartPoint,
|
|
37850
|
+
reviewLabelForRepo,
|
|
37672
37851
|
rewriteAbleTimeError,
|
|
37673
37852
|
rewriteLinearError,
|
|
37674
37853
|
run,
|