@coreplane/switchboard 1.263.0 → 1.265.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/config/config.example.yaml +4 -2
- package/dist/assets/deploy/cloudflare/prImages.ts +6 -1
- package/dist/assets/package-lock.json +3 -3
- package/dist/assets/package.json +1 -1
- package/dist/assets/source.json +3 -3
- package/dist/assets/src/core/coordinator/driver.ts +1 -0
- package/dist/assets/src/core/ship/coordinator.ts +14 -1
- package/dist/cli.js +65 -23
- package/package.json +1 -1
|
@@ -435,8 +435,10 @@ workspaceDir: ./workspaces
|
|
|
435
435
|
# integer >= 14 (the loop's reserve plus one round). `maxMinutes` is the ship
|
|
436
436
|
# preset's declared budget: a channel or user `boundary.maxMinutes` and a
|
|
437
437
|
# per-message `budget:` directive clip it like any preset's, and the card says
|
|
438
|
-
# so.
|
|
439
|
-
#
|
|
438
|
+
# so. An unfinished pipeline keeps only its remaining rounds and minutes on
|
|
439
|
+
# continuation. A new task after merge-ready starts with fresh caps, even when
|
|
440
|
+
# it adopts that pull request. Defaults shown; `maxRounds` must be an integer
|
|
441
|
+
# >= 1; any other key under `ship` fails the load by name.
|
|
440
442
|
# ship:
|
|
441
443
|
# maxRounds: 3 # review rounds per unit
|
|
442
444
|
# maxMinutes: 240 # the ship preset's wall-clock budget in minutes (the registry's default)
|
|
@@ -57,7 +57,12 @@ export async function publishPrImage(
|
|
|
57
57
|
if (!object) return json(404, { error: "artifact not found" });
|
|
58
58
|
let bytes: Uint8Array;
|
|
59
59
|
try {
|
|
60
|
-
|
|
60
|
+
// R2ObjectBody is a runtime object; its size and body need not be enumerable.
|
|
61
|
+
bytes = await readPrImage({
|
|
62
|
+
size: object.size,
|
|
63
|
+
body: object.body,
|
|
64
|
+
contentType: object.httpMetadata?.contentType ?? "",
|
|
65
|
+
});
|
|
61
66
|
} catch {
|
|
62
67
|
// A storage stream can fail with internal paths or stack details; the caller
|
|
63
68
|
// needs only the stable validation result.
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "switchboard",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.265.0",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "switchboard",
|
|
9
|
-
"version": "1.
|
|
9
|
+
"version": "1.265.0",
|
|
10
10
|
"license": "Apache-2.0",
|
|
11
11
|
"workspaces": [
|
|
12
12
|
"web",
|
|
@@ -21060,7 +21060,7 @@
|
|
|
21060
21060
|
},
|
|
21061
21061
|
"packages/switchboard": {
|
|
21062
21062
|
"name": "@coreplane/switchboard",
|
|
21063
|
-
"version": "1.
|
|
21063
|
+
"version": "1.265.0",
|
|
21064
21064
|
"license": "Apache-2.0",
|
|
21065
21065
|
"dependencies": {
|
|
21066
21066
|
"@earendil-works/pi-ai": "0.85.1",
|
package/dist/assets/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "switchboard",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.265.0",
|
|
4
4
|
"private": true,
|
|
5
5
|
"description": "Mention it in Slack and an agent reviews the PR, ships the fix, or answers the question — on the model you choose, with its tools running where you decide.",
|
|
6
6
|
"license": "Apache-2.0",
|
package/dist/assets/source.json
CHANGED
|
@@ -1050,6 +1050,7 @@ async function runUnit(
|
|
|
1050
1050
|
generated: plan.generated,
|
|
1051
1051
|
...(plan.runPageBase !== undefined ? { runPageBase: plan.runPageBase } : {}),
|
|
1052
1052
|
...(resume !== undefined ? { resume } : {}),
|
|
1053
|
+
...(row?.publication !== undefined && resume === undefined && lastPush === undefined ? { freshAdopt: true } : {}),
|
|
1053
1054
|
...(lastPush !== undefined ? { lastPush } : {}),
|
|
1054
1055
|
...(session !== undefined ? { session } : {}),
|
|
1055
1056
|
...(row?.recovery !== undefined
|
|
@@ -1167,6 +1167,9 @@ export interface UnitPipelineInput {
|
|
|
1167
1167
|
idleDays?: number;
|
|
1168
1168
|
/** Resume at review: an open pull request of ship's own the requester named. */
|
|
1169
1169
|
resume?: { pr: number; headSha?: string; url?: string };
|
|
1170
|
+
/** A task adopted an existing PR without a prior coding push. Its old
|
|
1171
|
+
* approval and checks cannot answer this task, so pre-check starts coding. */
|
|
1172
|
+
freshAdopt?: boolean;
|
|
1170
1173
|
/** The head the previous attempt's coding child last pushed (a
|
|
1171
1174
|
* `review_pending` ending's `headSha`, carried on the unit's row): when the
|
|
1172
1175
|
* pre-check finds the open pull request still at exactly this head, there is
|
|
@@ -1995,10 +1998,12 @@ function settleCoding(
|
|
|
1995
1998
|
// final observed head. Only then may a fresh remote read decide readiness.
|
|
1996
1999
|
if (round.kind === "findings" && facts.status === "completed") {
|
|
1997
2000
|
const issued = next.findingsByRound[round.index] ?? [];
|
|
1998
|
-
const matched = matchDispositions(issued, facts.dispositions ?? [])
|
|
2001
|
+
const { matched, dropped } = matchDispositions(issued, facts.dispositions ?? []);
|
|
1999
2002
|
const missingOutputs = issued
|
|
2000
2003
|
.filter((finding) => !matched.some((disposition) => disposition.findingId === finding.id))
|
|
2001
2004
|
.map((finding) => `missing disposition for ${finding.id}`);
|
|
2005
|
+
if (missingOutputs.length > 0 && dropped.length > 0)
|
|
2006
|
+
missingOutputs.push(`submitted IDs with no matching finding: ${dropped.join(", ")}`);
|
|
2002
2007
|
if (facts.description !== true) missingOutputs.push("missing updated pull request description");
|
|
2003
2008
|
const observedHead = fullHead(facts.headSha);
|
|
2004
2009
|
if (observedHead === undefined) missingOutputs.push("missing final observed commit");
|
|
@@ -3083,6 +3088,8 @@ export function applyReturn(s: UnitPipelineState, ret: StepReturn): Transition {
|
|
|
3083
3088
|
};
|
|
3084
3089
|
return nextReview(adopted);
|
|
3085
3090
|
}
|
|
3091
|
+
if (s.input.freshAdopt === true)
|
|
3092
|
+
return enterRound({ ...clocked, pr: { number: r.pr.prNumber, url: r.pr.url } }, { index: 0, kind: "coding" });
|
|
3086
3093
|
const branchHead = normalizeHead(r.pr.branchHead);
|
|
3087
3094
|
const lastPush = normalizeHead(s.input.lastPush);
|
|
3088
3095
|
const atBranchHead = head !== undefined && branchHead !== undefined && sameCommit(head, branchHead);
|
|
@@ -3121,6 +3128,12 @@ export function applyReturn(s: UnitPipelineState, ret: StepReturn): Transition {
|
|
|
3121
3128
|
return nextReview(adopted);
|
|
3122
3129
|
}
|
|
3123
3130
|
}
|
|
3131
|
+
if (s.input.freshAdopt === true)
|
|
3132
|
+
return end(clocked, {
|
|
3133
|
+
kind: "aborted",
|
|
3134
|
+
reason: `⚠️ The adopted pull request on ${s.input.repo} is no longer open, so coding did not start.`,
|
|
3135
|
+
reviewRounds: s.reviewRounds,
|
|
3136
|
+
});
|
|
3124
3137
|
return { state: { ...clocked, phase: { at: "branch" } }, notes: [] };
|
|
3125
3138
|
}
|
|
3126
3139
|
case "branch": {
|
package/dist/cli.js
CHANGED
|
@@ -36722,13 +36722,16 @@ async function resolveRepoContext(msg, history = [], probe, residentSlugs, recor
|
|
|
36722
36722
|
rejected = void 0;
|
|
36723
36723
|
unverified = void 0;
|
|
36724
36724
|
}
|
|
36725
|
+
const bareNumberText = !s.pr && repo === records?.pr?.repo ? /\b(?:PR|pull request)\s*#(\d+)\b/i.exec(unwrapSlack(msg.text).replace(CODE_SPAN, " "))?.[1] : void 0;
|
|
36726
|
+
const bareNumber = bareNumberText === void 0 ? void 0 : Number(bareNumberText);
|
|
36727
|
+
const namedPr = s.pr ?? (repo && bareNumber !== void 0 && Number.isSafeInteger(bareNumber) && bareNumber > 0 ? { repo, number: bareNumber } : void 0);
|
|
36725
36728
|
let headSha;
|
|
36726
36729
|
let baseRef;
|
|
36727
36730
|
let prSize;
|
|
36728
36731
|
let facts2;
|
|
36729
36732
|
let closedPr;
|
|
36730
|
-
if (
|
|
36731
|
-
const head = await prHead(
|
|
36733
|
+
if (namedPr && repo === namedPr.repo) {
|
|
36734
|
+
const head = await prHead(namedPr).catch(() => void 0);
|
|
36732
36735
|
if (head?.ref && head.state === "open") {
|
|
36733
36736
|
ref = head.ref;
|
|
36734
36737
|
refFromPr = true;
|
|
@@ -36739,7 +36742,7 @@ async function resolveRepoContext(msg, history = [], probe, residentSlugs, recor
|
|
|
36739
36742
|
facts2 = head?.facts;
|
|
36740
36743
|
if (head?.state === "closed")
|
|
36741
36744
|
closedPr = {
|
|
36742
|
-
number:
|
|
36745
|
+
number: namedPr.number,
|
|
36743
36746
|
merged: head.merged,
|
|
36744
36747
|
...head.mergedAt !== void 0 ? { mergedAt: head.mergedAt } : {}
|
|
36745
36748
|
};
|
|
@@ -36750,16 +36753,16 @@ async function resolveRepoContext(msg, history = [], probe, residentSlugs, recor
|
|
|
36750
36753
|
else if (rejected) out.rejectedRepo = rejected;
|
|
36751
36754
|
if (ref) out.ref = ref;
|
|
36752
36755
|
if (refFromPr) out.refFromPr = true;
|
|
36753
|
-
if (repo &&
|
|
36754
|
-
out.pr =
|
|
36756
|
+
if (repo && namedPr && repo === namedPr.repo) {
|
|
36757
|
+
out.pr = namedPr.number;
|
|
36755
36758
|
out.prFromMessage = true;
|
|
36756
|
-
if (isThreadOwnPr(records, repo,
|
|
36759
|
+
if (isThreadOwnPr(records, repo, namedPr.number)) out.prIsThreadOwn = true;
|
|
36757
36760
|
if (headSha) out.headSha = headSha;
|
|
36758
36761
|
if (baseRef) out.baseRef = baseRef;
|
|
36759
36762
|
if (prSize) out.prSize = prSize;
|
|
36760
36763
|
if (facts2) out.prDescription = facts2;
|
|
36761
36764
|
if (closedPr) out.closedPr = closedPr;
|
|
36762
|
-
} else if (repo && !
|
|
36765
|
+
} else if (repo && !namedPr) {
|
|
36763
36766
|
const inherited = inheritedPr(thread, records, repo);
|
|
36764
36767
|
if (inherited) {
|
|
36765
36768
|
const head = await openPrHeadSha(inherited);
|
|
@@ -40789,24 +40792,38 @@ function instanceOf(runs) {
|
|
|
40789
40792
|
return void 0;
|
|
40790
40793
|
}
|
|
40791
40794
|
async function ownerOf2(runs, unitsOf, threadKey) {
|
|
40792
|
-
const live = runs.find((r) => !r.finished);
|
|
40795
|
+
const live = runs.find((r) => !r.finished && r.hosted !== true);
|
|
40793
40796
|
if (live !== void 0) return { kind: "live", run: live };
|
|
40797
|
+
const hosted = runs.find((r) => !r.finished && r.hosted === true);
|
|
40794
40798
|
const instanceId = instanceOf(runs);
|
|
40799
|
+
let releasedPr;
|
|
40795
40800
|
if (instanceId !== void 0) {
|
|
40796
40801
|
const units = await unitsOf(instanceId).catch(() => []);
|
|
40797
40802
|
const unit = units.find((u) => u.threadKey === threadKey && u.ending === void 0);
|
|
40798
40803
|
if (unit !== void 0) return { kind: "unit", instanceId, unit };
|
|
40804
|
+
if (hosted !== void 0) return { kind: "live", run: hosted };
|
|
40799
40805
|
const ended = units.filter(
|
|
40800
|
-
(u) => u.threadKey === threadKey && u.ending !== void 0 && u.ending.kind !== "merged" && u.ending.kind !== "already_landed"
|
|
40806
|
+
(u) => u.threadKey === threadKey && u.ending !== void 0 && u.ending.kind !== "merged" && u.ending.kind !== "already_landed" && // A completed, publication-bound PR is new work on the next reply.
|
|
40807
|
+
// Keep older rows without that binding on the guarded recovery path.
|
|
40808
|
+
(u.ending.kind !== "merge_ready" || u.publication === void 0)
|
|
40801
40809
|
);
|
|
40802
40810
|
const ship = runs.find((r) => r.instanceId === instanceId && r.finished);
|
|
40803
40811
|
if (ended.length === 1 && ship !== void 0) return { kind: "pipeline", instanceId, run: ship, unit: ended[0] };
|
|
40804
40812
|
if (ended.length > 1 && ship !== void 0)
|
|
40805
40813
|
return { kind: "pipeline_ambiguous", instanceId, run: ship, units: ended };
|
|
40814
|
+
const released = units.filter((u) => {
|
|
40815
|
+
const binding = u.publication;
|
|
40816
|
+
return u.threadKey === threadKey && u.instanceId === instanceId && u.ending?.kind === "merge_ready" && binding !== void 0 && u.pr?.number === binding.pr && u.branch === binding.headRef && u.branch === binding.publicationRef && binding.owner.instanceId === instanceId && binding.owner.unit === u.unit && (u.lastPush === void 0 || u.lastPush === binding.expectedHeadSha);
|
|
40817
|
+
});
|
|
40818
|
+
if (released.length === 1) {
|
|
40819
|
+
const unit2 = released[0];
|
|
40820
|
+
releasedPr = { repo: unit2.publication.repo, number: unit2.publication.pr, at: unit2.ending.at };
|
|
40821
|
+
}
|
|
40806
40822
|
}
|
|
40823
|
+
if (hosted !== void 0) return { kind: "live", run: hosted };
|
|
40807
40824
|
const agent = stickyAgentOf(runs);
|
|
40808
|
-
if (agent !== void 0) return { kind: "session", agent };
|
|
40809
|
-
return { kind: "none" };
|
|
40825
|
+
if (agent !== void 0) return { kind: "session", agent, ...releasedPr ? { releasedPr } : {} };
|
|
40826
|
+
return { kind: "none", ...releasedPr ? { releasedPr } : {} };
|
|
40810
40827
|
}
|
|
40811
40828
|
async function shipRequestOf(service, runId3) {
|
|
40812
40829
|
const result = await service.getRun(runId3, { include: "messages" }).catch(() => void 0);
|
|
@@ -46057,7 +46074,7 @@ var init_submit = __esm({
|
|
|
46057
46074
|
submitDispositionsTool = {
|
|
46058
46075
|
name: "submit_dispositions",
|
|
46059
46076
|
failsInText: true,
|
|
46060
|
-
description: "Record one disposition per review finding after addressing them: `fixed` (the finding is addressed in your pushed code) or `declined` (deliberately not doing it \u2014 the note says why). `findingId` is the finding's stable id
|
|
46077
|
+
description: "Record one disposition per review finding after addressing them: `fixed` (the finding is addressed in your pushed code) or `declined` (deliberately not doing it \u2014 the note says why). `findingId` is the finding's stable id printed in the findings. Copy it exactly, including check ids such as `check:CI / checks (test)`; do not replace a check id with `F1`. An id the review never issued answers nothing and is dropped when the plan runner reads your record. Every finding gets exactly one entry, every severity included (nits too). Call it once with the complete set after your last push; a later call replaces the earlier one. The set rides this run's record, where the plan runner reads it for the re-review.",
|
|
46061
46078
|
inputSchema: {
|
|
46062
46079
|
type: "object",
|
|
46063
46080
|
properties: {
|
|
@@ -46067,7 +46084,10 @@ var init_submit = __esm({
|
|
|
46067
46084
|
items: {
|
|
46068
46085
|
type: "object",
|
|
46069
46086
|
properties: {
|
|
46070
|
-
findingId: {
|
|
46087
|
+
findingId: {
|
|
46088
|
+
type: "string",
|
|
46089
|
+
description: 'Copy the exact id in the findings (e.g. "F1" or "check:CI / checks (test)")'
|
|
46090
|
+
},
|
|
46071
46091
|
disposition: { type: "string", enum: ["fixed", "declined"], description: "fixed | declined" },
|
|
46072
46092
|
note: { type: "string", description: "One line: what was done, or why it was declined" }
|
|
46073
46093
|
},
|
|
@@ -46083,7 +46103,7 @@ var init_submit = __esm({
|
|
|
46083
46103
|
if (!ctx.onDispositions) return "no run is recording dispositions here";
|
|
46084
46104
|
ctx.onDispositions(parsed.dispositions);
|
|
46085
46105
|
const drops = parsed.dropped.length ? ` (dropped: ${parsed.dropped.join("; ")})` : "";
|
|
46086
|
-
return `dispositions recorded: ${parsed.dispositions.length}${drops}; a later call replaces this one`;
|
|
46106
|
+
return `dispositions recorded: ${parsed.dispositions.length}${drops}; IDs are checked against the findings by the plan runner; a later call replaces this one`;
|
|
46087
46107
|
}
|
|
46088
46108
|
};
|
|
46089
46109
|
submitPrDescriptionTool = {
|
|
@@ -50273,19 +50293,36 @@ function judgeBashCommand(command2, ctx) {
|
|
|
50273
50293
|
if (MERGE_OR_APPROVE.test(command2)) {
|
|
50274
50294
|
return refused4("merge/approve \u2014 a coding run never merges or approves a pull request");
|
|
50275
50295
|
}
|
|
50296
|
+
const pushCommand = withoutShellContinuations(command2);
|
|
50276
50297
|
if (ctx.identity !== "write") {
|
|
50277
|
-
if (ANY_PUSH.test(
|
|
50298
|
+
if (ANY_PUSH.test(pushCommand)) return refused4("read-only \u2014 a read-identity run never pushes");
|
|
50278
50299
|
if (GH_WRITE_VERB.test(command2) || GH_API_WRITE.test(command2) || CURL_GITHUB_WRITE.test(command2)) {
|
|
50279
50300
|
return refused4("read-only \u2014 a read-identity run never writes to GitHub");
|
|
50280
50301
|
}
|
|
50281
50302
|
return allowed;
|
|
50282
50303
|
}
|
|
50283
|
-
for (const match of
|
|
50304
|
+
for (const match of pushCommand.matchAll(GIT_PUSH)) {
|
|
50284
50305
|
const verdict = judgePush(match[1], ctx);
|
|
50285
50306
|
if (verdict.verdict !== "allowed") return verdict;
|
|
50286
50307
|
}
|
|
50287
50308
|
return allowed;
|
|
50288
50309
|
}
|
|
50310
|
+
function withoutShellContinuations(command2) {
|
|
50311
|
+
let result = "";
|
|
50312
|
+
let quote3;
|
|
50313
|
+
for (let i = 0; i < command2.length; i++) {
|
|
50314
|
+
const char = command2[i];
|
|
50315
|
+
if (char === "\\" && quote3 !== "'" && i + 1 < command2.length) {
|
|
50316
|
+
const next = command2[++i];
|
|
50317
|
+
if (next !== "\n") result += char + next;
|
|
50318
|
+
continue;
|
|
50319
|
+
}
|
|
50320
|
+
if (char === quote3) quote3 = void 0;
|
|
50321
|
+
else if (quote3 === void 0 && (char === "'" || char === '"')) quote3 = char;
|
|
50322
|
+
result += char;
|
|
50323
|
+
}
|
|
50324
|
+
return result;
|
|
50325
|
+
}
|
|
50289
50326
|
function judgeBashTimeout(timeout, ctx) {
|
|
50290
50327
|
if (!ctx.loopEndsIn || typeof timeout !== "number" || !Number.isFinite(timeout) || timeout <= 0) return allowed;
|
|
50291
50328
|
const leftMs = ctx.loopEndsIn();
|
|
@@ -50396,8 +50433,11 @@ var init_toolRules = __esm({
|
|
|
50396
50433
|
ENV_DUMP = /(^|[;&|(]\s*)((printenv|env)(\s+-[A-Za-z0-9-]+)*|export\s+-p|declare\s+-[a-zA-Z]*[px][a-zA-Z]*|set)\s*($|[|;&>)])|\/proc\/(self|\d+)\/environ|process\.env(?![.[\w])/;
|
|
50397
50434
|
CREDENTIAL_VAR = /\$\{?[A-Z][A-Z0-9_]*(_API_KEY|_TOKEN|_SECRET|_BEARER|_PASSWORD)\b|printenv\s+[A-Z][A-Z0-9_]*(_API_KEY|_TOKEN|_SECRET|_BEARER|_PASSWORD)\b/;
|
|
50398
50435
|
MERGE_OR_APPROVE = /\bgh\s+pr\s+(merge|review)\b|\/pulls\/\d+\/(merge|reviews)\b/;
|
|
50399
|
-
GIT_THEN_PUSH = String.raw`\bgit(
|
|
50400
|
-
GIT_PUSH = new RegExp(
|
|
50436
|
+
GIT_THEN_PUSH = String.raw`\bgit(?:[ \t]+(?:-C[ \t]+\S+|--git-dir=\S+|--work-tree=\S+|-c[ \t]+\S+|--no-pager))*[ \t]+push\b`;
|
|
50437
|
+
GIT_PUSH = new RegExp(
|
|
50438
|
+
GIT_THEN_PUSH + String.raw`((?:"(?:\\[\s\S]|[^"\\])*"|'[^']*'|\\[^\n]|[^\n;&|'"\\]|(?<=[<>])&|&(?=>))*)`,
|
|
50439
|
+
"g"
|
|
50440
|
+
);
|
|
50401
50441
|
ANY_PUSH = new RegExp(GIT_THEN_PUSH);
|
|
50402
50442
|
GH_WRITE_VERB = /\bgh\s+(pr|issue)\s+(comment|create|edit|close|reopen|ready|lock|unlock|review|merge|delete|transfer|pin|unpin)\b/;
|
|
50403
50443
|
WRITE_METHOD = "(POST|post|PATCH|patch|PUT|put|DELETE|delete)";
|
|
@@ -56711,7 +56751,7 @@ async function dispatch(deps, msg, io, opts = {}) {
|
|
|
56711
56751
|
// offers no steer line, the executor folds a steer bind like any
|
|
56712
56752
|
// other, and the fold runs on to the seed refusal below, which
|
|
56713
56753
|
// names the unit threads to reply in.
|
|
56714
|
-
pageOwner.run.
|
|
56754
|
+
pageOwner.run.hosted === true ? { kind: "live" } : { kind: "live", runId: pageOwner.run.id }
|
|
56715
56755
|
) : pageOwner?.kind === "unit" ? { kind: "unit", unit: pageOwner.unit.unit } : pageOwner?.kind === "pipeline" ? { kind: "pipeline", unit: pageOwner.unit.unit } : pageOwner?.kind === "pipeline_ambiguous" ? { kind: "pipeline", unit: pageOwner.units.map((unit) => unit.unit).join(", ") } : void 0;
|
|
56716
56756
|
operatorEvent = await root.span(
|
|
56717
56757
|
"dispatch.operator",
|
|
@@ -56777,7 +56817,8 @@ async function dispatch(deps, msg, io, opts = {}) {
|
|
|
56777
56817
|
);
|
|
56778
56818
|
};
|
|
56779
56819
|
const stickyAgent = thread ? stickyAgentOf(thread) : void 0;
|
|
56780
|
-
const
|
|
56820
|
+
const laterPr = (runPr, releasedPr) => releasedPr !== void 0 && (runPr === void 0 || releasedPr.at > runPr.at) ? releasedPr : runPr;
|
|
56821
|
+
let threadPr = laterPr(thread ? threadPrOf(thread) : void 0, pageOwner?.releasedPr);
|
|
56781
56822
|
const inheritedRepo = operatorRepo ?? (thread ? newestFinishedRunOf(thread)?.repo : void 0) ?? deps.config.scopes(msg.channelId, msg.userId).channel.repo;
|
|
56782
56823
|
const historicalRoutePreset = restart?.row.meta.route?.preset;
|
|
56783
56824
|
const resolveCurrent = () => resolveRun(deps, {
|
|
@@ -56798,8 +56839,9 @@ async function dispatch(deps, msg, io, opts = {}) {
|
|
|
56798
56839
|
const threadLive = admission.get(msg.threadKey) !== void 0 || !resume && !restart && deps.threadsElsewhere.get(msg.threadKey) !== void 0;
|
|
56799
56840
|
if (thread && !threadLive && deps.coordinatorInstances !== void 0) {
|
|
56800
56841
|
const owner = pageOwner ?? await ownerOf2(thread, (id) => deps.coordinatorInstances.listUnits(id), msg.threadKey);
|
|
56801
|
-
|
|
56802
|
-
|
|
56842
|
+
threadPr = laterPr(threadPr, owner.releasedPr);
|
|
56843
|
+
if (owner.kind === "live" && owner.run.hosted === true) {
|
|
56844
|
+
const units = owner.run.instanceId === void 0 ? [] : await deps.coordinatorInstances.listUnits(owner.run.instanceId).catch(() => []);
|
|
56803
56845
|
const open2 = units.filter((u) => u.ending === void 0);
|
|
56804
56846
|
await refuse3(
|
|
56805
56847
|
refusalOf(
|
|
@@ -72938,7 +72980,7 @@ function findingsRequest(input) {
|
|
|
72938
72980
|
|
|
72939
72981
|
A person answered the human-gated finding. Treat the finding and this answer together as the fix brief:
|
|
72940
72982
|
${input.answers.join("\n\n")}` : "";
|
|
72941
|
-
return `The review of ${input.where} requested changes. Load the \`address-review-findings\` skill and address every finding below, nits included: record one disposition per finding with submit_dispositions (fixed or declined, with a note),
|
|
72983
|
+
return `The review of ${input.where} requested changes. Load the \`address-review-findings\` skill and address every finding below, nits included: record one disposition per finding with submit_dispositions (fixed or declined, with a note). Copy each finding ID exactly, including any \`check:\u2026\` ID; never substitute an \`F1\` ID for a check. Squash to coherent commits, resubmit the pull request description with submit_pr_description, and push the branch. Never merge and never approve.
|
|
72942
72984
|
|
|
72943
72985
|
Findings:
|
|
72944
72986
|
${findings}${answers}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coreplane/switchboard",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.265.0",
|
|
4
4
|
"description": "Mention it in Slack and an agent reviews the PR, ships the fix, or answers the question — on the model you choose, with its tools running where you decide.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://openswitchboard.dev",
|