@coreplane/switchboard 1.230.0 → 1.231.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/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/contract.ts +22 -14
- package/dist/assets/src/core/coordinator/driver.ts +4 -0
- package/dist/assets/src/core/ship/contract.ts +35 -29
- package/dist/assets/src/core/ship/coordinator.ts +89 -4
- package/dist/assets/web/dist/.vite/manifest.json +19 -19
- package/dist/assets/web/dist/assets/CostsPage-D-v8am88.js +2 -0
- package/dist/assets/web/dist/assets/{ResidentDetailPage-DYxDruS0.js → ResidentDetailPage-Df6D2emM.js} +1 -1
- package/dist/assets/web/dist/assets/{ResidentsIndexPage-DIBRBmuq.js → ResidentsIndexPage-B0yECe2z.js} +1 -1
- package/dist/assets/web/dist/assets/{RunRoutePage-B4s8hJlW.js → RunRoutePage-D4FG8JbC.js} +3 -3
- package/dist/assets/web/dist/assets/{RunsIndexPage-CaW07KOf.js → RunsIndexPage-qxjCAVwQ.js} +1 -1
- package/dist/assets/web/dist/assets/{ScheduledPage-Cr7269s9.js → ScheduledPage-B0xQSZIS.js} +1 -1
- package/dist/assets/web/dist/assets/{StatusDot-lCLi16zY.js → StatusDot-D-h9p7Iv.js} +1 -1
- package/dist/assets/web/dist/assets/{Tooltip-DKMPwNyy.js → Tooltip-BuDnXjL7.js} +1 -1
- package/dist/assets/web/dist/assets/{dist-DRkTB2rt.js → dist-BjLBNLkl.js} +1 -1
- package/dist/assets/web/dist/assets/{main-CXKOiCOK.js → main-BRrMt0Kr.js} +2 -2
- package/dist/cli.js +369 -219
- package/package.json +1 -1
- package/dist/assets/web/dist/assets/CostsPage-B08bdD-1.js +0 -2
package/dist/cli.js
CHANGED
|
@@ -443,8 +443,10 @@ var init_store = __esm({
|
|
|
443
443
|
const contentType = res.headers.get("content-type") ?? "application/octet-stream";
|
|
444
444
|
if (res.status === 416) {
|
|
445
445
|
const total = /\/(\d+)\s*$/.exec(res.headers.get("content-range") ?? "");
|
|
446
|
-
if (
|
|
447
|
-
|
|
446
|
+
if (total) return { unsatisfiable: true, size: Number(total[1]), contentType };
|
|
447
|
+
const head = await this.head(key);
|
|
448
|
+
if (!head) return null;
|
|
449
|
+
return { unsatisfiable: true, size: head.size, contentType: head.contentType };
|
|
448
450
|
}
|
|
449
451
|
if (!res.ok || !res.body) throw new Error(`artifact store: GET ${key} answered HTTP ${res.status}`);
|
|
450
452
|
if (res.status === 206) {
|
|
@@ -1616,7 +1618,18 @@ function resolveSpecRow(ref, specMarkdown) {
|
|
|
1616
1618
|
validation: parseValidationRows(specMarkdown).filter((row) => itemNumbersNamed(row.criterion).has(ref.item))
|
|
1617
1619
|
};
|
|
1618
1620
|
}
|
|
1621
|
+
function unitTitleOf(text) {
|
|
1622
|
+
const firstLine2 = text.split("\n").find((l) => l.trim() !== "")?.trim() ?? "";
|
|
1623
|
+
return firstLine2.length > TITLE_MAX ? `${firstLine2.slice(0, TITLE_MAX - 1).trimEnd()}\u2026` : firstLine2;
|
|
1624
|
+
}
|
|
1625
|
+
function generatedUnit(id, text) {
|
|
1626
|
+
const title = unitTitleOf(text);
|
|
1627
|
+
return { id, title, section: `### ${id}. ${title}
|
|
1628
|
+
|
|
1629
|
+
${text}`, bullets: {} };
|
|
1630
|
+
}
|
|
1619
1631
|
function contractFromPlan(input) {
|
|
1632
|
+
if ("unit" in input) return contractOf(input.unit, input);
|
|
1620
1633
|
const unit = parsePlanUnit(input.planMarkdown, input.unitId);
|
|
1621
1634
|
if (!unit) {
|
|
1622
1635
|
const ids = planUnitIds(input.planMarkdown);
|
|
@@ -1624,6 +1637,9 @@ function contractFromPlan(input) {
|
|
|
1624
1637
|
`the plan has no unit ${input.unitId} (its units: ${ids.length > 0 ? ids.join(", ") : "none \u2014 no `### U<n>.` heading"})`
|
|
1625
1638
|
);
|
|
1626
1639
|
}
|
|
1640
|
+
return contractOf(unit, input);
|
|
1641
|
+
}
|
|
1642
|
+
function contractOf(unit, input) {
|
|
1627
1643
|
return {
|
|
1628
1644
|
unit,
|
|
1629
1645
|
specRows: specItemRefs(unit.section).map((ref) => resolveSpecRow(ref, input.readSpec(ref.spec))),
|
|
@@ -1633,18 +1649,6 @@ function contractFromPlan(input) {
|
|
|
1633
1649
|
issue: input.issue
|
|
1634
1650
|
};
|
|
1635
1651
|
}
|
|
1636
|
-
function contractFromTask(input) {
|
|
1637
|
-
const firstLine2 = input.task.split("\n").find((l) => l.trim() !== "")?.trim() ?? "";
|
|
1638
|
-
const title = firstLine2.length > TITLE_MAX ? `${firstLine2.slice(0, TITLE_MAX - 1).trimEnd()}\u2026` : firstLine2;
|
|
1639
|
-
return {
|
|
1640
|
-
unit: { id: "task", title, section: input.task, bullets: {} },
|
|
1641
|
-
specRows: [],
|
|
1642
|
-
agentRules: input.agentRules,
|
|
1643
|
-
guards: GUARDS,
|
|
1644
|
-
rebase: { branch: input.rebase?.branch, onto: input.rebase?.onto },
|
|
1645
|
-
issue: input.issue
|
|
1646
|
-
};
|
|
1647
|
-
}
|
|
1648
1652
|
function unitBody(unit, dropApproach) {
|
|
1649
1653
|
const lines = unit.section.split("\n");
|
|
1650
1654
|
if (dropApproach) {
|
|
@@ -12192,7 +12196,8 @@ function isCoordinatorInstance(v) {
|
|
|
12192
12196
|
if (typeof r.repo !== "string" || !REPO_SLUG2.test(r.repo)) return false;
|
|
12193
12197
|
if (!isText(r.branch) || !isOptionalText(r.base)) return false;
|
|
12194
12198
|
if (!isFinite(r.createdAt)) return false;
|
|
12195
|
-
if (r.plan !== void 0 && !(isObject(r.plan) && isText(r.plan.id) && isText(r.plan.path, 1024)))
|
|
12199
|
+
if (r.plan !== void 0 && !(isObject(r.plan) && isText(r.plan.id) && (r.plan.path === void 0 || isText(r.plan.path, 1024))))
|
|
12200
|
+
return false;
|
|
12196
12201
|
if (r.merge !== void 0 && r.merge !== "runner" && r.merge !== "person") return false;
|
|
12197
12202
|
if (r.caps !== void 0 && !(isObject(r.caps) && isFinite(r.caps.maxRounds) && isFinite(r.caps.maxMinutes)))
|
|
12198
12203
|
return false;
|
|
@@ -14159,11 +14164,10 @@ async function viewerRunUserIds(userIds, viewer, emailOfSlackUser, cache2) {
|
|
|
14159
14164
|
const out = [];
|
|
14160
14165
|
for (const id of new Set(userIds)) {
|
|
14161
14166
|
if (!id.startsWith("slack:") || id.startsWith("slack:bot:")) continue;
|
|
14162
|
-
|
|
14163
|
-
let known = cache2.get(slackId);
|
|
14167
|
+
let known = cache2.get(id);
|
|
14164
14168
|
if (known === void 0) {
|
|
14165
|
-
known = (await emailOfSlackUser(
|
|
14166
|
-
if (known !== void 0) cache2.set(
|
|
14169
|
+
known = (await emailOfSlackUser(id))?.toLowerCase();
|
|
14170
|
+
if (known !== void 0) cache2.set(id, known);
|
|
14167
14171
|
}
|
|
14168
14172
|
if (known === email) out.push(id);
|
|
14169
14173
|
}
|
|
@@ -29741,7 +29745,7 @@ var init_statusCardFrame = __esm({
|
|
|
29741
29745
|
SPINNER_GLYPHS = ["\u25D0", "\u25D3", "\u25D1", "\u25D2"];
|
|
29742
29746
|
LIVE_CARD_PREFIXES = [...SPINNER_GLYPHS, "\u{1F440}"];
|
|
29743
29747
|
ROUTED_LABEL_PREFIX = "routed:";
|
|
29744
|
-
ROUTED_CARD_FOOTER = "reply agent:<preset> to run it another way";
|
|
29748
|
+
ROUTED_CARD_FOOTER = "wrong preset? reply agent:<preset> to run it another way";
|
|
29745
29749
|
}
|
|
29746
29750
|
});
|
|
29747
29751
|
|
|
@@ -35674,7 +35678,6 @@ var init_runLoop = __esm({
|
|
|
35674
35678
|
});
|
|
35675
35679
|
|
|
35676
35680
|
// ../../src/core/ship/preflight.ts
|
|
35677
|
-
import { createHash as createHash5 } from "node:crypto";
|
|
35678
35681
|
function shipTaskText(requestText, repo) {
|
|
35679
35682
|
let t = requestText.replace(/<((?:https?):\/\/[^|>\s]+)(?:\|[^>]*)?>/gi, " $1 ");
|
|
35680
35683
|
t = t.replace(/https?:\/\/\S+/gi, " ");
|
|
@@ -35684,11 +35687,6 @@ function shipTaskText(requestText, repo) {
|
|
|
35684
35687
|
t = t.replace(/\b[a-z0-9][\w.-]*\/[\w.-]+#\d+\b/gi, " ");
|
|
35685
35688
|
return t.replace(/\s+/g, " ").trim().replace(/^[:,\-—.\s]+/, "").trim();
|
|
35686
35689
|
}
|
|
35687
|
-
function shipBranchName(task, threadKey) {
|
|
35688
|
-
const slug = task.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 24).replace(/-+$/, "") || "task";
|
|
35689
|
-
const hash = createHash5("sha256").update(threadKey).digest("hex").slice(0, 6);
|
|
35690
|
-
return `ship/${slug}-${hash}`;
|
|
35691
|
-
}
|
|
35692
35690
|
async function shipPreflight(input) {
|
|
35693
35691
|
const { repoCtx } = input;
|
|
35694
35692
|
if (!input.channelId.startsWith("slack:") && !input.channelId.startsWith("cli:")) {
|
|
@@ -35812,7 +35810,7 @@ async function shipPreflight(input) {
|
|
|
35812
35810
|
const ref = repoCtx.ref && !repoCtx.refFromPr && repoCtx.ref.toLowerCase() !== repo.toLowerCase() ? repoCtx.ref : void 0;
|
|
35813
35811
|
return {
|
|
35814
35812
|
ok: true,
|
|
35815
|
-
entry: { repo,
|
|
35813
|
+
entry: { repo, base: resolveBaseRef([ref], info.defaultBranch) }
|
|
35816
35814
|
};
|
|
35817
35815
|
}
|
|
35818
35816
|
var refuse2;
|
|
@@ -35855,6 +35853,133 @@ function planInstanceId(planId, attempt = 1) {
|
|
|
35855
35853
|
const suffix = `-${attempt}`;
|
|
35856
35854
|
return `${base.slice(0, INSTANCE_ID_MAX - suffix.length)}${suffix}`;
|
|
35857
35855
|
}
|
|
35856
|
+
function sha256Hex2(text) {
|
|
35857
|
+
const K = new Uint32Array([
|
|
35858
|
+
1116352408,
|
|
35859
|
+
1899447441,
|
|
35860
|
+
3049323471,
|
|
35861
|
+
3921009573,
|
|
35862
|
+
961987163,
|
|
35863
|
+
1508970993,
|
|
35864
|
+
2453635748,
|
|
35865
|
+
2870763221,
|
|
35866
|
+
3624381080,
|
|
35867
|
+
310598401,
|
|
35868
|
+
607225278,
|
|
35869
|
+
1426881987,
|
|
35870
|
+
1925078388,
|
|
35871
|
+
2162078206,
|
|
35872
|
+
2614888103,
|
|
35873
|
+
3248222580,
|
|
35874
|
+
3835390401,
|
|
35875
|
+
4022224774,
|
|
35876
|
+
264347078,
|
|
35877
|
+
604807628,
|
|
35878
|
+
770255983,
|
|
35879
|
+
1249150122,
|
|
35880
|
+
1555081692,
|
|
35881
|
+
1996064986,
|
|
35882
|
+
2554220882,
|
|
35883
|
+
2821834349,
|
|
35884
|
+
2952996808,
|
|
35885
|
+
3210313671,
|
|
35886
|
+
3336571891,
|
|
35887
|
+
3584528711,
|
|
35888
|
+
113926993,
|
|
35889
|
+
338241895,
|
|
35890
|
+
666307205,
|
|
35891
|
+
773529912,
|
|
35892
|
+
1294757372,
|
|
35893
|
+
1396182291,
|
|
35894
|
+
1695183700,
|
|
35895
|
+
1986661051,
|
|
35896
|
+
2177026350,
|
|
35897
|
+
2456956037,
|
|
35898
|
+
2730485921,
|
|
35899
|
+
2820302411,
|
|
35900
|
+
3259730800,
|
|
35901
|
+
3345764771,
|
|
35902
|
+
3516065817,
|
|
35903
|
+
3600352804,
|
|
35904
|
+
4094571909,
|
|
35905
|
+
275423344,
|
|
35906
|
+
430227734,
|
|
35907
|
+
506948616,
|
|
35908
|
+
659060556,
|
|
35909
|
+
883997877,
|
|
35910
|
+
958139571,
|
|
35911
|
+
1322822218,
|
|
35912
|
+
1537002063,
|
|
35913
|
+
1747873779,
|
|
35914
|
+
1955562222,
|
|
35915
|
+
2024104815,
|
|
35916
|
+
2227730452,
|
|
35917
|
+
2361852424,
|
|
35918
|
+
2428436474,
|
|
35919
|
+
2756734187,
|
|
35920
|
+
3204031479,
|
|
35921
|
+
3329325298
|
|
35922
|
+
]);
|
|
35923
|
+
const h = new Uint32Array([
|
|
35924
|
+
1779033703,
|
|
35925
|
+
3144134277,
|
|
35926
|
+
1013904242,
|
|
35927
|
+
2773480762,
|
|
35928
|
+
1359893119,
|
|
35929
|
+
2600822924,
|
|
35930
|
+
528734635,
|
|
35931
|
+
1541459225
|
|
35932
|
+
]);
|
|
35933
|
+
const bytes = new TextEncoder().encode(text);
|
|
35934
|
+
const padded = new Uint8Array((bytes.length + 8 >> 6 << 6) + 64);
|
|
35935
|
+
padded.set(bytes);
|
|
35936
|
+
padded[bytes.length] = 128;
|
|
35937
|
+
new DataView(padded.buffer).setBigUint64(padded.length - 8, BigInt(bytes.length) * 8n);
|
|
35938
|
+
const w = new Uint32Array(64);
|
|
35939
|
+
const rotr = (x, n2) => x >>> n2 | x << 32 - n2;
|
|
35940
|
+
const view = new DataView(padded.buffer);
|
|
35941
|
+
for (let i = 0; i < padded.length; i += 64) {
|
|
35942
|
+
for (let t = 0; t < 16; t++) w[t] = view.getUint32(i + t * 4);
|
|
35943
|
+
for (let t = 16; t < 64; t++) {
|
|
35944
|
+
const s0 = rotr(w[t - 15], 7) ^ rotr(w[t - 15], 18) ^ w[t - 15] >>> 3;
|
|
35945
|
+
const s1 = rotr(w[t - 2], 17) ^ rotr(w[t - 2], 19) ^ w[t - 2] >>> 10;
|
|
35946
|
+
w[t] = w[t - 16] + s0 + w[t - 7] + s1 >>> 0;
|
|
35947
|
+
}
|
|
35948
|
+
let [a, b, c, d, e, f, g, hh] = [h[0], h[1], h[2], h[3], h[4], h[5], h[6], h[7]];
|
|
35949
|
+
for (let t = 0; t < 64; t++) {
|
|
35950
|
+
const S1 = rotr(e, 6) ^ rotr(e, 11) ^ rotr(e, 25);
|
|
35951
|
+
const ch = e & f ^ ~e & g;
|
|
35952
|
+
const t1 = hh + S1 + ch + K[t] + w[t] >>> 0;
|
|
35953
|
+
const S0 = rotr(a, 2) ^ rotr(a, 13) ^ rotr(a, 22);
|
|
35954
|
+
const maj = a & b ^ a & c ^ b & c;
|
|
35955
|
+
const t2 = S0 + maj >>> 0;
|
|
35956
|
+
hh = g;
|
|
35957
|
+
g = f;
|
|
35958
|
+
f = e;
|
|
35959
|
+
e = d + t1 >>> 0;
|
|
35960
|
+
d = c;
|
|
35961
|
+
c = b;
|
|
35962
|
+
b = a;
|
|
35963
|
+
a = t1 + t2 >>> 0;
|
|
35964
|
+
}
|
|
35965
|
+
h[0] = h[0] + a >>> 0;
|
|
35966
|
+
h[1] = h[1] + b >>> 0;
|
|
35967
|
+
h[2] = h[2] + c >>> 0;
|
|
35968
|
+
h[3] = h[3] + d >>> 0;
|
|
35969
|
+
h[4] = h[4] + e >>> 0;
|
|
35970
|
+
h[5] = h[5] + f >>> 0;
|
|
35971
|
+
h[6] = h[6] + g >>> 0;
|
|
35972
|
+
h[7] = h[7] + hh >>> 0;
|
|
35973
|
+
}
|
|
35974
|
+
return [...h].map((x) => x.toString(16).padStart(8, "0")).join("");
|
|
35975
|
+
}
|
|
35976
|
+
function generatedPlanId(text, threadKey) {
|
|
35977
|
+
const normalised = text.toLowerCase().replace(/\s+/g, " ").trim();
|
|
35978
|
+
const slug = normalised.replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, SLUG_MAX).replace(/-+$/, "") || "task";
|
|
35979
|
+
const hash = sha256Hex2(`${threadKey}
|
|
35980
|
+
${normalised}`).slice(0, 6);
|
|
35981
|
+
return `${slug}-${hash}`;
|
|
35982
|
+
}
|
|
35858
35983
|
function dependenciesOf(text, self) {
|
|
35859
35984
|
const out = [];
|
|
35860
35985
|
const add = (id) => {
|
|
@@ -35947,141 +36072,6 @@ var init_coordinator = __esm({
|
|
|
35947
36072
|
}
|
|
35948
36073
|
});
|
|
35949
36074
|
|
|
35950
|
-
// ../../src/core/ship/reviewChild.ts
|
|
35951
|
-
function buildShipReviewTurn(input) {
|
|
35952
|
-
const at = input.headSha ? ` at head \`${input.headSha}\`` : "";
|
|
35953
|
-
if (input.round <= 1 || !input.prior) {
|
|
35954
|
-
return `Review pull request ${input.where}${at}. Submit your verdict with findings via submit_verdict before your final message.`;
|
|
35955
|
-
}
|
|
35956
|
-
const findings = input.prior.findings.map(formatFinding).join("\n") || "(none recorded)";
|
|
35957
|
-
const dispositions = input.prior.dispositions.map((d) => `${d.findingId}: ${d.disposition}${d.note ? ` \u2014 ${d.note}` : ""}`).join("\n") || "(none recorded)";
|
|
35958
|
-
const dropped = input.prior.dropped !== void 0 && input.prior.dropped.length > 0 ? `
|
|
35959
|
-
Dispositions naming no finding of the previous round (dropped): ${input.prior.dropped.join(", ")}` : "";
|
|
35960
|
-
return `Re-review pull request ${input.where}${at} \u2014 review round ${input.round} of this ship pipeline. Load the \`re-review-delta\` skill: narrow your READING to the delta since the previously reviewed head and verify each prior finding's disposition, but your verdict still covers the full diff against base. Carry every unresolved prior finding forward under its existing id.
|
|
35961
|
-
|
|
35962
|
-
Previous round's findings:
|
|
35963
|
-
${findings}
|
|
35964
|
-
|
|
35965
|
-
Fix round's dispositions:
|
|
35966
|
-
${dispositions}${dropped}`;
|
|
35967
|
-
}
|
|
35968
|
-
var init_reviewChild = __esm({
|
|
35969
|
-
"../../src/core/ship/reviewChild.ts"() {
|
|
35970
|
-
"use strict";
|
|
35971
|
-
init_reviewVerdict();
|
|
35972
|
-
}
|
|
35973
|
-
});
|
|
35974
|
-
|
|
35975
|
-
// ../../src/core/coordinator/briefs.ts
|
|
35976
|
-
async function contractFor(instance, unit, readers) {
|
|
35977
|
-
const rebase = { branch: unit.branch, onto: instance.base ?? "main" };
|
|
35978
|
-
const issue = unit.issue !== void 0 ? { repo: instance.repo, number: unit.issue } : void 0;
|
|
35979
|
-
if (unit.unit === TASK_UNIT || instance.plan === void 0) {
|
|
35980
|
-
const request = await readers.readShipRequest();
|
|
35981
|
-
const task = request !== void 0 ? shipTaskText(parseDirectives(request).text, instance.repo) : "";
|
|
35982
|
-
return contractFromTask({
|
|
35983
|
-
task: task || "Implement the task this thread's ship request describes.",
|
|
35984
|
-
rebase,
|
|
35985
|
-
...issue ? { issue } : {}
|
|
35986
|
-
});
|
|
35987
|
-
}
|
|
35988
|
-
const planMarkdown = await readers.readRepoFile(instance.plan.path);
|
|
35989
|
-
if (planMarkdown === void 0)
|
|
35990
|
-
throw new Error(`the plan ${instance.plan.path} is not readable at ${rebase.onto} in ${instance.repo}`);
|
|
35991
|
-
const section = parsePlanUnit(planMarkdown, unit.unit)?.section ?? "";
|
|
35992
|
-
const specs = /* @__PURE__ */ new Map();
|
|
35993
|
-
for (const spec of new Set(specItemRefs(section).map((r) => r.spec)))
|
|
35994
|
-
specs.set(spec, await readers.readRepoFile(`${SPECS_DIR2}/${spec}`));
|
|
35995
|
-
let agentRules;
|
|
35996
|
-
for (const file of RULES_FILES2) {
|
|
35997
|
-
const text = await readers.readRepoFile(file);
|
|
35998
|
-
if (text !== void 0) {
|
|
35999
|
-
agentRules = { file, text };
|
|
36000
|
-
break;
|
|
36001
|
-
}
|
|
36002
|
-
}
|
|
36003
|
-
return contractFromPlan({
|
|
36004
|
-
planMarkdown,
|
|
36005
|
-
unitId: unit.unit,
|
|
36006
|
-
readSpec: (spec) => specs.get(spec),
|
|
36007
|
-
...agentRules ? { agentRules } : {},
|
|
36008
|
-
rebase,
|
|
36009
|
-
...issue ? { issue } : {}
|
|
36010
|
-
});
|
|
36011
|
-
}
|
|
36012
|
-
function findingsRequest(input) {
|
|
36013
|
-
const findings = input.findings.map(formatFinding).join("\n") || "(the review listed no structured findings, address its prose)";
|
|
36014
|
-
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), squash to coherent commits, resubmit the pull request description with submit_pr_description, and push the branch. Never merge and never approve.
|
|
36015
|
-
|
|
36016
|
-
Findings:
|
|
36017
|
-
${findings}
|
|
36018
|
-
|
|
36019
|
-
Review:
|
|
36020
|
-
${input.review}`;
|
|
36021
|
-
}
|
|
36022
|
-
async function composeChild(brief, instance, unit, readers) {
|
|
36023
|
-
const where = `${instance.repo}#${"pr" in brief ? brief.pr : ""}`;
|
|
36024
|
-
switch (brief.kind) {
|
|
36025
|
-
case "contract": {
|
|
36026
|
-
const contract = await contractFor(instance, unit, readers);
|
|
36027
|
-
const prompt = contract.unit.id === TASK_UNIT ? contract.unit.section : `Implement unit ${contract.unit.id} \u2014 ${contract.unit.title} \u2014 of ${instance.plan?.path ?? "the plan"}: the contract below is the unit. Do its first instruction first, then add every test scenario it lists, update every spec row it names and weaken no guard.`;
|
|
36028
|
-
return { preset: "coding", prompt, ref: unit.branch, contract };
|
|
36029
|
-
}
|
|
36030
|
-
case "review": {
|
|
36031
|
-
let prior;
|
|
36032
|
-
if (brief.prior !== void 0) {
|
|
36033
|
-
const findings = (await facts(readers, brief.prior.reviewRunId)).findings ?? [];
|
|
36034
|
-
const recorded = brief.prior.codingRunId !== void 0 ? (await facts(readers, brief.prior.codingRunId)).dispositions ?? [] : [];
|
|
36035
|
-
const { matched, dropped } = matchDispositions(findings, recorded);
|
|
36036
|
-
prior = { findings, dispositions: matched, dropped };
|
|
36037
|
-
}
|
|
36038
|
-
const turn = buildShipReviewTurn({
|
|
36039
|
-
where,
|
|
36040
|
-
round: brief.round,
|
|
36041
|
-
...brief.headSha !== void 0 ? { headSha: brief.headSha } : {},
|
|
36042
|
-
...prior ? { prior } : {}
|
|
36043
|
-
});
|
|
36044
|
-
const contract = await contractFor(instance, unit, readers);
|
|
36045
|
-
return { preset: "review", prompt: `${prUrl(instance.repo, brief.pr)}
|
|
36046
|
-
|
|
36047
|
-
${turn}`, contract };
|
|
36048
|
-
}
|
|
36049
|
-
case "findings": {
|
|
36050
|
-
const review = await facts(readers, brief.reviewRunId);
|
|
36051
|
-
return {
|
|
36052
|
-
preset: "coding",
|
|
36053
|
-
prompt: findingsRequest({ where, findings: review.findings ?? [], review: review.finalReply ?? "" }),
|
|
36054
|
-
ref: unit.branch
|
|
36055
|
-
};
|
|
36056
|
-
}
|
|
36057
|
-
default: {
|
|
36058
|
-
const unknown = brief;
|
|
36059
|
-
throw new Error(`unknown brief kind ${JSON.stringify(unknown.kind)}`);
|
|
36060
|
-
}
|
|
36061
|
-
}
|
|
36062
|
-
}
|
|
36063
|
-
async function facts(readers, runId3) {
|
|
36064
|
-
const read = await readers.readRunFacts(runId3);
|
|
36065
|
-
if (!read) throw new Error(`run ${runId3} is not in the run history`);
|
|
36066
|
-
return read;
|
|
36067
|
-
}
|
|
36068
|
-
var SPECS_DIR2, RULES_FILES2, TASK_UNIT, prUrl;
|
|
36069
|
-
var init_briefs = __esm({
|
|
36070
|
-
"../../src/core/coordinator/briefs.ts"() {
|
|
36071
|
-
"use strict";
|
|
36072
|
-
init_directives();
|
|
36073
|
-
init_reviewVerdict();
|
|
36074
|
-
init_coordinator();
|
|
36075
|
-
init_contract();
|
|
36076
|
-
init_preflight();
|
|
36077
|
-
init_reviewChild();
|
|
36078
|
-
SPECS_DIR2 = "docs/reference/specs";
|
|
36079
|
-
RULES_FILES2 = ["AGENTS.md", "CLAUDE.md"];
|
|
36080
|
-
TASK_UNIT = "task";
|
|
36081
|
-
prUrl = (repo, pr) => `https://github.com/${repo}/pull/${pr}`;
|
|
36082
|
-
}
|
|
36083
|
-
});
|
|
36084
|
-
|
|
36085
36075
|
// ../../src/core/coordinator/handOff.ts
|
|
36086
36076
|
async function plan(deps, input) {
|
|
36087
36077
|
const { entry, msg } = input;
|
|
@@ -36107,29 +36097,26 @@ async function plan(deps, input) {
|
|
|
36107
36097
|
runId: input.runId,
|
|
36108
36098
|
label: input.label
|
|
36109
36099
|
};
|
|
36110
|
-
const
|
|
36100
|
+
const taskText = shipTaskText(input.requestText, entry.repo);
|
|
36101
|
+
const request = parseShipPlanRequest(taskText);
|
|
36111
36102
|
if (request === void 0) {
|
|
36112
|
-
const
|
|
36113
|
-
const
|
|
36114
|
-
const
|
|
36103
|
+
const text2 = taskText || "Implement the task this thread's ship request describes.";
|
|
36104
|
+
const planId2 = generatedPlanId(text2, msg.threadKey);
|
|
36105
|
+
const graph2 = {
|
|
36106
|
+
planId: planId2,
|
|
36107
|
+
units: [{ id: "U1", title: unitTitleOf(text2), slug: "u1", branch: unitBranch(planId2, "u1"), dependsOn: [] }]
|
|
36108
|
+
};
|
|
36115
36109
|
return {
|
|
36116
36110
|
ok: true,
|
|
36117
36111
|
planned: {
|
|
36118
|
-
|
|
36119
|
-
|
|
36120
|
-
|
|
36121
|
-
|
|
36122
|
-
|
|
36123
|
-
|
|
36124
|
-
|
|
36125
|
-
|
|
36126
|
-
branch: entry.branch,
|
|
36127
|
-
dependsOn: [],
|
|
36128
|
-
rounds: [],
|
|
36129
|
-
...resume !== void 0 ? { resume } : {}
|
|
36130
|
-
}
|
|
36131
|
-
],
|
|
36132
|
-
where: resume !== void 0 ? `the review loop of ${prUrl2} resumes at its next review round on \`${entry.branch}\` in this thread under your grants \u2014 no new coding round first; this card follows it and the report lands here.` : `the task runs on \`${entry.branch}\` in this thread under your grants; this card follows it and the report lands here.`
|
|
36112
|
+
planId: planId2,
|
|
36113
|
+
base,
|
|
36114
|
+
graph: graph2,
|
|
36115
|
+
selected: ["U1"],
|
|
36116
|
+
identity: identity2,
|
|
36117
|
+
merge: "person",
|
|
36118
|
+
...entry.resume !== void 0 ? { resume: entry.resume } : {},
|
|
36119
|
+
...entry.branch !== void 0 ? { entryBranch: entry.branch } : {}
|
|
36133
36120
|
}
|
|
36134
36121
|
};
|
|
36135
36122
|
}
|
|
@@ -36160,42 +36147,55 @@ async function plan(deps, input) {
|
|
|
36160
36147
|
} catch (err2) {
|
|
36161
36148
|
return { ok: false, reply: `\u{1F6AB} ${describe6(err2)}` };
|
|
36162
36149
|
}
|
|
36163
|
-
return {
|
|
36150
|
+
return {
|
|
36151
|
+
ok: true,
|
|
36152
|
+
planned: { planId, path: request.planPath, base, graph, selected, identity: identity2, merge: "runner" }
|
|
36153
|
+
};
|
|
36164
36154
|
}
|
|
36165
|
-
function rowsFor(
|
|
36166
|
-
return graph.units.filter((u) => selected.includes(u.id)).map((u) => ({
|
|
36155
|
+
function rowsFor(p, selected, instanceId) {
|
|
36156
|
+
return p.graph.units.filter((u) => selected.includes(u.id)).map((u) => ({
|
|
36167
36157
|
instanceId,
|
|
36168
36158
|
unit: u.id,
|
|
36169
36159
|
slug: u.slug,
|
|
36170
36160
|
title: u.title,
|
|
36171
|
-
branch: u.branch,
|
|
36161
|
+
branch: p.entryBranch ?? u.branch,
|
|
36172
36162
|
dependsOn: u.dependsOn,
|
|
36173
|
-
rounds: []
|
|
36163
|
+
rounds: [],
|
|
36164
|
+
...p.resume !== void 0 ? { resume: p.resume } : {}
|
|
36174
36165
|
}));
|
|
36175
36166
|
}
|
|
36176
36167
|
function planWhere(p, units, mergedBefore) {
|
|
36168
|
+
const at = p.path !== void 0 ? ` (\`${p.path}\` at \`${p.base}\`)` : "";
|
|
36177
36169
|
const count = `${units.length} unit${units.length === 1 ? "" : "s"}`;
|
|
36178
36170
|
const left = mergedBefore.length > 0 ? ` left` : "";
|
|
36179
36171
|
const merged = mergedBefore.length > 0 ? `; merged before: ${mergedBefore.join(", ")}` : "";
|
|
36180
|
-
|
|
36172
|
+
const head = `plan \`${p.planId}\`${at}, ${count}${left} in dependency order \u2014 ${units.map((u) => u.unit).join(", ")}${merged}.`;
|
|
36173
|
+
if (p.path !== void 0)
|
|
36174
|
+
return `${head} Each unit runs in a thread of its own in this channel under your grants; this card follows the plan and its summary lands in this thread.`;
|
|
36175
|
+
const branch2 = units[0]?.branch ?? "";
|
|
36176
|
+
const prUrl2 = p.resume?.url ?? (p.resume !== void 0 ? `https://github.com/${p.identity.repo}/pull/${p.resume.pr}` : void 0);
|
|
36177
|
+
const runs = p.resume !== void 0 ? `the review loop of ${prUrl2} resumes at its next review round on \`${branch2}\` in this thread under your grants \u2014 no new coding round first` : `the unit runs on \`${branch2}\` in this thread under your grants`;
|
|
36178
|
+
return `${head} ${runs}; this card follows it and the report lands here.`;
|
|
36181
36179
|
}
|
|
36182
36180
|
async function handOffToCoordinator(deps, input) {
|
|
36183
36181
|
const log = deps.log ?? console.log;
|
|
36184
36182
|
const planned = await plan(deps, input);
|
|
36185
36183
|
if (!planned.ok) return refused3(planned.reply);
|
|
36186
36184
|
const p = planned.planned;
|
|
36187
|
-
|
|
36185
|
+
const planOf = () => ({
|
|
36186
|
+
id: p.planId,
|
|
36187
|
+
...p.path !== void 0 ? { path: p.path } : {}
|
|
36188
|
+
});
|
|
36188
36189
|
const firstId = planInstanceId(p.planId);
|
|
36189
36190
|
const first = await deps.instances.get(firstId);
|
|
36190
36191
|
if (first === null) {
|
|
36191
|
-
const units2 = rowsFor(p
|
|
36192
|
+
const units2 = rowsFor(p, p.selected, firstId);
|
|
36192
36193
|
const instance2 = {
|
|
36193
36194
|
id: firstId,
|
|
36194
36195
|
...p.identity,
|
|
36195
36196
|
branch: units2[0].branch,
|
|
36196
|
-
plan:
|
|
36197
|
-
|
|
36198
|
-
merge: "runner"
|
|
36197
|
+
plan: planOf(),
|
|
36198
|
+
merge: p.merge
|
|
36199
36199
|
};
|
|
36200
36200
|
return start(deps, input, instance2, units2, planWhere(p, units2, []), "put");
|
|
36201
36201
|
}
|
|
@@ -36232,13 +36232,13 @@ async function handOffToCoordinator(deps, input) {
|
|
|
36232
36232
|
);
|
|
36233
36233
|
const mergedBefore = p.selected.filter((u) => merged.has(u));
|
|
36234
36234
|
if (status3.kind === "absent") {
|
|
36235
|
-
const units2 = rowsFor(p
|
|
36235
|
+
const units2 = rowsFor(p, remaining, latest.id);
|
|
36236
36236
|
const instance2 = {
|
|
36237
36237
|
id: latest.id,
|
|
36238
36238
|
...p.identity,
|
|
36239
36239
|
branch: units2[0].branch,
|
|
36240
|
-
plan:
|
|
36241
|
-
merge:
|
|
36240
|
+
plan: planOf(),
|
|
36241
|
+
merge: p.merge,
|
|
36242
36242
|
...attempt > 1 ? { attempt } : {}
|
|
36243
36243
|
};
|
|
36244
36244
|
log(`[ship] ${input.msg.threadKey}: ${latest.id} has records but no instance \u2014 replacing the earlier attempt's`);
|
|
@@ -36246,13 +36246,13 @@ async function handOffToCoordinator(deps, input) {
|
|
|
36246
36246
|
return start(deps, input, instance2, units2, `${prefix}${planWhere(p, units2, mergedBefore)}`, "replace");
|
|
36247
36247
|
}
|
|
36248
36248
|
const nextId = planInstanceId(p.planId, attempt + 1);
|
|
36249
|
-
const units = rowsFor(p
|
|
36249
|
+
const units = rowsFor(p, remaining, nextId);
|
|
36250
36250
|
const instance = {
|
|
36251
36251
|
id: nextId,
|
|
36252
36252
|
...p.identity,
|
|
36253
36253
|
branch: units[0].branch,
|
|
36254
|
-
plan:
|
|
36255
|
-
merge:
|
|
36254
|
+
plan: planOf(),
|
|
36255
|
+
merge: p.merge,
|
|
36256
36256
|
attempt: attempt + 1
|
|
36257
36257
|
};
|
|
36258
36258
|
return start(deps, input, instance, units, `attempt ${attempt + 1} of ${planWhere(p, units, mergedBefore)}`, "put");
|
|
@@ -36304,9 +36304,9 @@ var refused3, describe6, RUNNING, ENDED;
|
|
|
36304
36304
|
var init_handOff = __esm({
|
|
36305
36305
|
"../../src/core/coordinator/handOff.ts"() {
|
|
36306
36306
|
"use strict";
|
|
36307
|
+
init_contract();
|
|
36307
36308
|
init_preflight();
|
|
36308
36309
|
init_coordinator();
|
|
36309
|
-
init_briefs();
|
|
36310
36310
|
refused3 = (reply) => ({ status: "aborted", reply });
|
|
36311
36311
|
describe6 = (err2) => err2 instanceof Error ? err2.message : String(err2);
|
|
36312
36312
|
RUNNING = /* @__PURE__ */ new Set(["queued", "running", "paused", "waiting", "waitingForPause"]);
|
|
@@ -43751,7 +43751,7 @@ var init_accessAuth = __esm({
|
|
|
43751
43751
|
});
|
|
43752
43752
|
|
|
43753
43753
|
// ../../src/channels/dashboardAuth.ts
|
|
43754
|
-
import { createHash as
|
|
43754
|
+
import { createHash as createHash5, timingSafeEqual as timingSafeEqual4 } from "node:crypto";
|
|
43755
43755
|
function header2(headers, name) {
|
|
43756
43756
|
const raw = headers[name];
|
|
43757
43757
|
return Array.isArray(raw) ? raw[0] : raw;
|
|
@@ -43769,8 +43769,8 @@ function accessVerifier(config, deps) {
|
|
|
43769
43769
|
};
|
|
43770
43770
|
}
|
|
43771
43771
|
function secretsEqual(a, b) {
|
|
43772
|
-
const ha =
|
|
43773
|
-
const hb =
|
|
43772
|
+
const ha = createHash5("sha256").update(a).digest();
|
|
43773
|
+
const hb = createHash5("sha256").update(b).digest();
|
|
43774
43774
|
return timingSafeEqual4(ha, hb);
|
|
43775
43775
|
}
|
|
43776
43776
|
function tokenVerifier(opts) {
|
|
@@ -44799,6 +44799,147 @@ var init_adminRestartAuthorize = __esm({
|
|
|
44799
44799
|
}
|
|
44800
44800
|
});
|
|
44801
44801
|
|
|
44802
|
+
// ../../src/core/ship/reviewChild.ts
|
|
44803
|
+
function buildShipReviewTurn(input) {
|
|
44804
|
+
const at = input.headSha ? ` at head \`${input.headSha}\`` : "";
|
|
44805
|
+
if (input.round <= 1 || !input.prior) {
|
|
44806
|
+
return `Review pull request ${input.where}${at}. Submit your verdict with findings via submit_verdict before your final message.`;
|
|
44807
|
+
}
|
|
44808
|
+
const findings = input.prior.findings.map(formatFinding).join("\n") || "(none recorded)";
|
|
44809
|
+
const dispositions = input.prior.dispositions.map((d) => `${d.findingId}: ${d.disposition}${d.note ? ` \u2014 ${d.note}` : ""}`).join("\n") || "(none recorded)";
|
|
44810
|
+
const dropped = input.prior.dropped !== void 0 && input.prior.dropped.length > 0 ? `
|
|
44811
|
+
Dispositions naming no finding of the previous round (dropped): ${input.prior.dropped.join(", ")}` : "";
|
|
44812
|
+
return `Re-review pull request ${input.where}${at} \u2014 review round ${input.round} of this ship pipeline. Load the \`re-review-delta\` skill: narrow your READING to the delta since the previously reviewed head and verify each prior finding's disposition, but your verdict still covers the full diff against base. Carry every unresolved prior finding forward under its existing id.
|
|
44813
|
+
|
|
44814
|
+
Previous round's findings:
|
|
44815
|
+
${findings}
|
|
44816
|
+
|
|
44817
|
+
Fix round's dispositions:
|
|
44818
|
+
${dispositions}${dropped}`;
|
|
44819
|
+
}
|
|
44820
|
+
var init_reviewChild = __esm({
|
|
44821
|
+
"../../src/core/ship/reviewChild.ts"() {
|
|
44822
|
+
"use strict";
|
|
44823
|
+
init_reviewVerdict();
|
|
44824
|
+
}
|
|
44825
|
+
});
|
|
44826
|
+
|
|
44827
|
+
// ../../src/core/coordinator/briefs.ts
|
|
44828
|
+
async function generatedUnitOf(instance, unit, readers) {
|
|
44829
|
+
const resume = unit.resume;
|
|
44830
|
+
if (resume !== void 0) {
|
|
44831
|
+
const url = resume.url ?? `https://github.com/${instance.repo}/pull/${resume.pr}`;
|
|
44832
|
+
return generatedUnit(unit.unit, `Resume the review loop of ${url}`);
|
|
44833
|
+
}
|
|
44834
|
+
const request = await readers.readShipRequest();
|
|
44835
|
+
const task = request !== void 0 ? shipTaskText(parseDirectives(request).text, instance.repo) : "";
|
|
44836
|
+
return generatedUnit(unit.unit, task || "Implement the task this thread's ship request describes.");
|
|
44837
|
+
}
|
|
44838
|
+
async function contractFor(instance, unit, readers) {
|
|
44839
|
+
const rebase = { branch: unit.branch, onto: instance.base ?? "main" };
|
|
44840
|
+
const issue = unit.issue !== void 0 ? { repo: instance.repo, number: unit.issue } : void 0;
|
|
44841
|
+
let source2;
|
|
44842
|
+
if (isGenerated(instance)) {
|
|
44843
|
+
source2 = { unit: await generatedUnitOf(instance, unit, readers) };
|
|
44844
|
+
} else {
|
|
44845
|
+
const planMarkdown = await readers.readRepoFile(instance.plan.path);
|
|
44846
|
+
if (planMarkdown === void 0)
|
|
44847
|
+
throw new Error(`the plan ${instance.plan.path} is not readable at ${rebase.onto} in ${instance.repo}`);
|
|
44848
|
+
source2 = { planMarkdown, unitId: unit.unit };
|
|
44849
|
+
}
|
|
44850
|
+
const section = ("unit" in source2 ? source2.unit : parsePlanUnit(source2.planMarkdown, unit.unit))?.section ?? "";
|
|
44851
|
+
const specs = /* @__PURE__ */ new Map();
|
|
44852
|
+
for (const spec of new Set(specItemRefs(section).map((r) => r.spec)))
|
|
44853
|
+
specs.set(spec, await readers.readRepoFile(`${SPECS_DIR2}/${spec}`));
|
|
44854
|
+
let agentRules;
|
|
44855
|
+
for (const file of RULES_FILES2) {
|
|
44856
|
+
const text = await readers.readRepoFile(file);
|
|
44857
|
+
if (text !== void 0) {
|
|
44858
|
+
agentRules = { file, text };
|
|
44859
|
+
break;
|
|
44860
|
+
}
|
|
44861
|
+
}
|
|
44862
|
+
return contractFromPlan({
|
|
44863
|
+
...source2,
|
|
44864
|
+
readSpec: (spec) => specs.get(spec),
|
|
44865
|
+
...agentRules ? { agentRules } : {},
|
|
44866
|
+
rebase,
|
|
44867
|
+
...issue ? { issue } : {}
|
|
44868
|
+
});
|
|
44869
|
+
}
|
|
44870
|
+
function findingsRequest(input) {
|
|
44871
|
+
const findings = input.findings.map(formatFinding).join("\n") || "(the review listed no structured findings, address its prose)";
|
|
44872
|
+
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), squash to coherent commits, resubmit the pull request description with submit_pr_description, and push the branch. Never merge and never approve.
|
|
44873
|
+
|
|
44874
|
+
Findings:
|
|
44875
|
+
${findings}
|
|
44876
|
+
|
|
44877
|
+
Review:
|
|
44878
|
+
${input.review}`;
|
|
44879
|
+
}
|
|
44880
|
+
async function composeChild(brief, instance, unit, readers) {
|
|
44881
|
+
const where = `${instance.repo}#${"pr" in brief ? brief.pr : ""}`;
|
|
44882
|
+
switch (brief.kind) {
|
|
44883
|
+
case "contract": {
|
|
44884
|
+
const contract = await contractFor(instance, unit, readers);
|
|
44885
|
+
const prompt = isGenerated(instance) ? contract.unit.section.split("\n").slice(1).join("\n").trim() : `Implement unit ${contract.unit.id} \u2014 ${contract.unit.title} \u2014 of ${instance.plan?.path ?? "the plan"}: the contract below is the unit. Do its first instruction first, then add every test scenario it lists, update every spec row it names and weaken no guard.`;
|
|
44886
|
+
return { preset: "coding", prompt, ref: unit.branch, contract };
|
|
44887
|
+
}
|
|
44888
|
+
case "review": {
|
|
44889
|
+
let prior;
|
|
44890
|
+
if (brief.prior !== void 0) {
|
|
44891
|
+
const findings = (await facts(readers, brief.prior.reviewRunId)).findings ?? [];
|
|
44892
|
+
const recorded = brief.prior.codingRunId !== void 0 ? (await facts(readers, brief.prior.codingRunId)).dispositions ?? [] : [];
|
|
44893
|
+
const { matched, dropped } = matchDispositions(findings, recorded);
|
|
44894
|
+
prior = { findings, dispositions: matched, dropped };
|
|
44895
|
+
}
|
|
44896
|
+
const turn = buildShipReviewTurn({
|
|
44897
|
+
where,
|
|
44898
|
+
round: brief.round,
|
|
44899
|
+
...brief.headSha !== void 0 ? { headSha: brief.headSha } : {},
|
|
44900
|
+
...prior ? { prior } : {}
|
|
44901
|
+
});
|
|
44902
|
+
const contract = await contractFor(instance, unit, readers);
|
|
44903
|
+
return { preset: "review", prompt: `${prUrl(instance.repo, brief.pr)}
|
|
44904
|
+
|
|
44905
|
+
${turn}`, contract };
|
|
44906
|
+
}
|
|
44907
|
+
case "findings": {
|
|
44908
|
+
const review = await facts(readers, brief.reviewRunId);
|
|
44909
|
+
return {
|
|
44910
|
+
preset: "coding",
|
|
44911
|
+
prompt: findingsRequest({ where, findings: review.findings ?? [], review: review.finalReply ?? "" }),
|
|
44912
|
+
ref: unit.branch
|
|
44913
|
+
};
|
|
44914
|
+
}
|
|
44915
|
+
default: {
|
|
44916
|
+
const unknown = brief;
|
|
44917
|
+
throw new Error(`unknown brief kind ${JSON.stringify(unknown.kind)}`);
|
|
44918
|
+
}
|
|
44919
|
+
}
|
|
44920
|
+
}
|
|
44921
|
+
async function facts(readers, runId3) {
|
|
44922
|
+
const read = await readers.readRunFacts(runId3);
|
|
44923
|
+
if (!read) throw new Error(`run ${runId3} is not in the run history`);
|
|
44924
|
+
return read;
|
|
44925
|
+
}
|
|
44926
|
+
var SPECS_DIR2, RULES_FILES2, isGenerated, prUrl;
|
|
44927
|
+
var init_briefs = __esm({
|
|
44928
|
+
"../../src/core/coordinator/briefs.ts"() {
|
|
44929
|
+
"use strict";
|
|
44930
|
+
init_directives();
|
|
44931
|
+
init_reviewVerdict();
|
|
44932
|
+
init_coordinator();
|
|
44933
|
+
init_contract();
|
|
44934
|
+
init_preflight();
|
|
44935
|
+
init_reviewChild();
|
|
44936
|
+
SPECS_DIR2 = "docs/reference/specs";
|
|
44937
|
+
RULES_FILES2 = ["AGENTS.md", "CLAUDE.md"];
|
|
44938
|
+
isGenerated = (instance) => instance.plan?.path === void 0;
|
|
44939
|
+
prUrl = (repo, pr) => `https://github.com/${repo}/pull/${pr}`;
|
|
44940
|
+
}
|
|
44941
|
+
});
|
|
44942
|
+
|
|
44802
44943
|
// ../../src/channels/adminCoordinator.ts
|
|
44803
44944
|
function isCoordinatorAdminPath(path) {
|
|
44804
44945
|
return path.startsWith(COORDINATOR_ADMIN_PREFIX) && path.length > COORDINATOR_ADMIN_PREFIX.length;
|
|
@@ -44913,7 +45054,7 @@ async function unitRowOf(deps, instance, unit) {
|
|
|
44913
45054
|
return { ok: true, row };
|
|
44914
45055
|
}
|
|
44915
45056
|
function unitThread(instance, row) {
|
|
44916
|
-
const threadKey = row?.threadKey ?? (row === void 0 ||
|
|
45057
|
+
const threadKey = row?.threadKey ?? (row === void 0 || isGenerated2(instance) ? instance.threadKey : void 0);
|
|
44917
45058
|
const sourceUrl = row?.sourceUrl ?? (threadKey === instance.threadKey ? instance.sourceUrl : void 0);
|
|
44918
45059
|
return { threadKey, sourceUrl };
|
|
44919
45060
|
}
|
|
@@ -45054,7 +45195,7 @@ async function spawn6(body, deps) {
|
|
|
45054
45195
|
if (req.brief !== void 0) {
|
|
45055
45196
|
if (row === void 0) return json(400, { ok: false, error: "a brief needs the unit it runs for" });
|
|
45056
45197
|
try {
|
|
45057
|
-
turn = await composeChild(req.brief, instance, row, briefReaders(deps, instance
|
|
45198
|
+
turn = await composeChild(req.brief, instance, row, briefReaders(deps, instance));
|
|
45058
45199
|
} catch (err2) {
|
|
45059
45200
|
log(`[coordinator] ${instance.id} ${req.step}: the brief could not be composed: ${describe11(err2)}`);
|
|
45060
45201
|
return json(502, { ok: false, error: "brief_failed", message: describe11(err2), at });
|
|
@@ -45283,6 +45424,8 @@ async function plan2(body, deps) {
|
|
|
45283
45424
|
...instance.plan !== void 0 ? { planId: instance.plan.id } : {},
|
|
45284
45425
|
// Who merges: the instance's field; a record written before it existed is a person's merge.
|
|
45285
45426
|
merge: instance.merge ?? "person",
|
|
45427
|
+
// The mark (item 16): the machine's report keys its re-issue line on it.
|
|
45428
|
+
generated: isGenerated2(instance),
|
|
45286
45429
|
repo: instance.repo,
|
|
45287
45430
|
base: instance.base ?? "main",
|
|
45288
45431
|
caps: instance.caps ?? resolveShipCaps(void 0),
|
|
@@ -45312,7 +45455,7 @@ async function unitStart(body, deps) {
|
|
|
45312
45455
|
if (!unit.ok) return unit.response;
|
|
45313
45456
|
let row = unit.row;
|
|
45314
45457
|
if (row.threadKey === void 0) {
|
|
45315
|
-
if (
|
|
45458
|
+
if (isGenerated2(instance)) {
|
|
45316
45459
|
row = {
|
|
45317
45460
|
...row,
|
|
45318
45461
|
threadKey: instance.threadKey,
|
|
@@ -45332,7 +45475,7 @@ async function unitStart(body, deps) {
|
|
|
45332
45475
|
}
|
|
45333
45476
|
row = review.row;
|
|
45334
45477
|
}
|
|
45335
|
-
if (row.issue === void 0 &&
|
|
45478
|
+
if (row.issue === void 0 && !isGenerated2(instance)) {
|
|
45336
45479
|
const issue = await unitIssueOf(deps, instance.repo, row.unit);
|
|
45337
45480
|
if (issue !== void 0) row = { ...row, issue };
|
|
45338
45481
|
}
|
|
@@ -45359,7 +45502,7 @@ function unitLead(instance, row) {
|
|
|
45359
45502
|
function reviewLead(instance, row) {
|
|
45360
45503
|
const who2 = instance.userName ?? instance.userId;
|
|
45361
45504
|
const from = instance.sourceUrl !== void 0 ? `[the *ship* run](${instance.sourceUrl})` : "the *ship* run";
|
|
45362
|
-
const what =
|
|
45505
|
+
const what = isGenerated2(instance) ? "the task" : `unit ${row.unit}${row.title ? ` \u2014 ${row.title}` : ""}`;
|
|
45363
45506
|
return `\u21B3 *ship* review of ${what} for ${who2}, from ${from}: \`${row.branch}\` in ${instance.repo}`;
|
|
45364
45507
|
}
|
|
45365
45508
|
async function branch(body, deps) {
|
|
@@ -45382,11 +45525,11 @@ async function branch(body, deps) {
|
|
|
45382
45525
|
return json(200, { ok: false, reason: describe11(err2), at });
|
|
45383
45526
|
}
|
|
45384
45527
|
}
|
|
45385
|
-
function unitLines(units) {
|
|
45528
|
+
function unitLines(units, generated) {
|
|
45386
45529
|
return units.map((u) => {
|
|
45387
45530
|
const last = u.rounds.at(-1);
|
|
45388
45531
|
const state = u.ending ? u.ending.kind : last ? `${shipRoundHeader({ index: last.index, agent: last.agent })} \xB7 ${last.outcome}` : u.threadKey ? "starting" : "waiting";
|
|
45389
|
-
return
|
|
45532
|
+
return generated ? state : `${u.unit} \xB7 ${state}`;
|
|
45390
45533
|
});
|
|
45391
45534
|
}
|
|
45392
45535
|
async function drawCard(deps, instance, units, close) {
|
|
@@ -45395,7 +45538,7 @@ async function drawCard(deps, instance, units, close) {
|
|
|
45395
45538
|
if (!io) return;
|
|
45396
45539
|
const clock4 = deps.clock ?? systemClock;
|
|
45397
45540
|
const shell = createCardShell({ label: instance.label ?? "*ship*", startedAt: instance.createdAt, now: clock4 });
|
|
45398
|
-
const detail = unitLines(units);
|
|
45541
|
+
const detail = unitLines(units, isGenerated2(instance));
|
|
45399
45542
|
if (!close) {
|
|
45400
45543
|
await io.status(shell.live({ detail }));
|
|
45401
45544
|
return;
|
|
@@ -45613,7 +45756,7 @@ function parentRunRecord(instance, units, outcome, channelVisibility, finishedAt
|
|
|
45613
45756
|
at: r.at
|
|
45614
45757
|
}))
|
|
45615
45758
|
),
|
|
45616
|
-
{ type: "answer", text: planSummary(units), at: finishedAt }
|
|
45759
|
+
{ type: "answer", text: planSummary(units, isGenerated2(instance)), at: finishedAt }
|
|
45617
45760
|
];
|
|
45618
45761
|
events.forEach((e, i) => {
|
|
45619
45762
|
e.seq = i + 1;
|
|
@@ -45639,11 +45782,11 @@ function parentRunRecord(instance, units, outcome, channelVisibility, finishedAt
|
|
|
45639
45782
|
...instance.sourceUrl !== void 0 ? { sourceUrl: instance.sourceUrl } : {}
|
|
45640
45783
|
};
|
|
45641
45784
|
}
|
|
45642
|
-
function planSummary(units) {
|
|
45785
|
+
function planSummary(units, generated = false) {
|
|
45643
45786
|
const lines = units.map((u) => {
|
|
45644
45787
|
const how = u.ending ? u.ending.kind : u.threadKey ? "unfinished" : "not started";
|
|
45645
45788
|
const pr = u.pr ? ` \u2014 ${u.pr.url}` : "";
|
|
45646
|
-
return
|
|
45789
|
+
return generated ? `${ENDING_ICON[how] ?? "\u2022"} ${how}${pr}` : `${ENDING_ICON[how] ?? "\u2022"} ${u.unit} \u2014 ${how}${pr}`;
|
|
45647
45790
|
});
|
|
45648
45791
|
return lines.join("\n");
|
|
45649
45792
|
}
|
|
@@ -45661,8 +45804,7 @@ async function finish(body, deps) {
|
|
|
45661
45804
|
deps.runHistoryWriter.write(record2);
|
|
45662
45805
|
await drawCard(deps, instance, units, { icon: body.outcome === "completed" ? "\u2705" : "\u26A0\uFE0F" }).catch(() => {
|
|
45663
45806
|
});
|
|
45664
|
-
|
|
45665
|
-
if (isPlan) {
|
|
45807
|
+
if (!isGenerated2(instance)) {
|
|
45666
45808
|
const io = deps.ioFor({ threadKey: instance.threadKey, userId: instance.userId });
|
|
45667
45809
|
await io?.reply(`Plan ${instance.plan?.id ?? ""} ended (${body.outcome}):
|
|
45668
45810
|
${planSummary(units)}`).catch(() => {
|
|
@@ -45671,7 +45813,7 @@ ${planSummary(units)}`).catch(() => {
|
|
|
45671
45813
|
(deps.log ?? console.log)(`[coordinator] ${instance.id}: finished ${body.outcome} \u2014 record ${record2.id}`);
|
|
45672
45814
|
return json(200, { ok: true, runId: record2.id, at });
|
|
45673
45815
|
}
|
|
45674
|
-
function briefReaders(deps, instance
|
|
45816
|
+
function briefReaders(deps, instance) {
|
|
45675
45817
|
const ref = instance.base ?? "main";
|
|
45676
45818
|
return {
|
|
45677
45819
|
readRepoFile: async (path) => {
|
|
@@ -45691,9 +45833,16 @@ function briefReaders(deps, instance, io) {
|
|
|
45691
45833
|
...finalReplyOf2(r.events) !== void 0 ? { finalReply: finalReplyOf2(r.events) } : {}
|
|
45692
45834
|
};
|
|
45693
45835
|
},
|
|
45836
|
+
// The generated plan's request text: the ship run's own record
|
|
45837
|
+
// (`instance.runId`, its `input` event) — never a scan of the thread, so a
|
|
45838
|
+
// routed request with no `agent:ship` turn anywhere still reads back the
|
|
45839
|
+
// words the person typed (agent-ship item 13).
|
|
45694
45840
|
readShipRequest: async () => {
|
|
45695
|
-
|
|
45696
|
-
|
|
45841
|
+
if (instance.runId === void 0) return void 0;
|
|
45842
|
+
const res = await deps.runs.getRun(instance.runId, { include: "messages" }).catch(() => void 0);
|
|
45843
|
+
if (res === void 0 || !res.ok) return void 0;
|
|
45844
|
+
const input = (res.value.events ?? []).find((e) => e.type === "input");
|
|
45845
|
+
return input?.type === "input" ? input.text : void 0;
|
|
45697
45846
|
}
|
|
45698
45847
|
};
|
|
45699
45848
|
}
|
|
@@ -45769,7 +45918,7 @@ function createAdminCoordinatorHandler(deps) {
|
|
|
45769
45918
|
})();
|
|
45770
45919
|
};
|
|
45771
45920
|
}
|
|
45772
|
-
var COORDINATOR_ADMIN_PREFIX, MAX_SPAWN_PROMPT_CHARS, FINISHED_LOOKBACK_PAGES, MAX_ADMIN_BODY_BYTES, UNIT_ID, PRESETS_OF_KIND, invalid, json, describe11, EVERY_RUN, REVIEW_POSTED_CHECKS, REVIEW_POSTED_RECHECK_MS, ROUND_OUTCOMES, ENDING_ICON, STEPS;
|
|
45921
|
+
var COORDINATOR_ADMIN_PREFIX, MAX_SPAWN_PROMPT_CHARS, FINISHED_LOOKBACK_PAGES, MAX_ADMIN_BODY_BYTES, UNIT_ID, PRESETS_OF_KIND, invalid, json, describe11, isGenerated2, EVERY_RUN, REVIEW_POSTED_CHECKS, REVIEW_POSTED_RECHECK_MS, ROUND_OUTCOMES, ENDING_ICON, STEPS;
|
|
45773
45922
|
var init_adminCoordinator = __esm({
|
|
45774
45923
|
"../../src/channels/adminCoordinator.ts"() {
|
|
45775
45924
|
"use strict";
|
|
@@ -45803,6 +45952,7 @@ var init_adminCoordinator = __esm({
|
|
|
45803
45952
|
invalid = (error) => ({ ok: false, error });
|
|
45804
45953
|
json = (status3, body) => ({ status: status3, body });
|
|
45805
45954
|
describe11 = (err2) => err2 instanceof Error ? err2.message : String(err2);
|
|
45955
|
+
isGenerated2 = (instance) => instance.plan?.path === void 0;
|
|
45806
45956
|
EVERY_RUN = { kind: "all" };
|
|
45807
45957
|
REVIEW_POSTED_CHECKS = 3;
|
|
45808
45958
|
REVIEW_POSTED_RECHECK_MS = 2e3;
|