@runfusion/fusion 0.77.0-beta.12 → 0.77.0-beta.13
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/bin.js +1636 -903
- package/dist/child-process-worker.js +1064 -466
- package/dist/client/.vite/manifest.json +260 -260
- package/dist/client/assets/AgentDetailView-DPoh46Ym.css +1 -0
- package/dist/client/assets/{AgentDetailView-BZfDgV8f.js → AgentDetailView-DwCr9HOY.js} +1 -1
- package/dist/client/assets/{AgentPermissionPolicyEditor-8yBqnwbx.js → AgentPermissionPolicyEditor-CXRP1R7V.js} +1 -1
- package/dist/client/assets/{AgentsView-BjMOtIMq.js → AgentsView-DEVhP_Ad.js} +3 -3
- package/dist/client/assets/CommandCenter-BshTzOtB.css +1 -0
- package/dist/client/assets/{CommandCenter-CDuO3HPd.js → CommandCenter-sNTR0N1L.js} +22 -22
- package/dist/client/assets/{DevServerView-C96RV0QJ.js → DevServerView-X1Ncu9x-.js} +1 -1
- package/dist/client/assets/{DirectoryPicker-iRielXf7.js → DirectoryPicker-UrDTGJYj.js} +1 -1
- package/dist/client/assets/{DocumentsView-DhAUnUD_.js → DocumentsView-DyyfLF1R.js} +1 -1
- package/dist/client/assets/{EvalsView--n1p2Bt0.js → EvalsView-DgMdhmj1.js} +1 -1
- package/dist/client/assets/{ExperimentalAgentOnboardingModal-DraglCCV.js → ExperimentalAgentOnboardingModal-DqETOMkr.js} +1 -1
- package/dist/client/assets/{GoalsView-BOWOua5t.js → GoalsView-Cai1_q1j.js} +1 -1
- package/dist/client/assets/{InsightsView-C5YcJZSc.js → InsightsView-DN9i_pr2.js} +1 -1
- package/dist/client/assets/{MemoryView-DsCuGVGx.js → MemoryView-DpVhI_BB.js} +1 -1
- package/dist/client/assets/{PatchnodeView-CzgChkJV.js → PatchnodeView-C9glaWoU.js} +1 -1
- package/dist/client/assets/{PiExtensionsManager-qYbmaigE.js → PiExtensionsManager-DkJ3I9ur.js} +1 -1
- package/dist/client/assets/{PluginManager-Cklj4Smo.js → PluginManager-C3BKqDE-.js} +1 -1
- package/dist/client/assets/{PullRequestView-C6vozTTI.js → PullRequestView-BCPolzJY.js} +1 -1
- package/dist/client/assets/{ReportModal-B0LU4E4L.js → ReportModal-CBc5lSf3.js} +1 -1
- package/dist/client/assets/{ResearchView-CpESx46e.js → ResearchView-BInIb1tK.js} +1 -1
- package/dist/client/assets/{SecretsView-8ZdH9Yzs.js → SecretsView-Db2mKOcp.js} +1 -1
- package/dist/client/assets/SettingsModal-BEULP2a7.css +1 -0
- package/dist/client/assets/SettingsModal-Dn9vcqW7.js +21 -0
- package/dist/client/assets/{SettingsModal-BJXu-dhz.js → SettingsModal-tnr4Y2cG.js} +1 -1
- package/dist/client/assets/{SettingsTextareaRow-th-q0_2k.js → SettingsTextareaRow-DDIEo7kX.js} +1 -1
- package/dist/client/assets/{SetupWizardModal-CBElxrRA.js → SetupWizardModal-BgpCpOJi.js} +2 -2
- package/dist/client/assets/{SkillsView-BuoicLbJ.js → SkillsView-C4_dPxaH.js} +1 -1
- package/dist/client/assets/{WorkflowNodeEditor-BDw0LpWM.js → WorkflowNodeEditor-BRIoMtdz.js} +1 -1
- package/dist/client/assets/{agent-import-generation-CNridJHO.js → agent-import-generation-DZjrAuLD.js} +1 -1
- package/dist/client/assets/{agentsOrgChartLayout-BopFGp0r.js → agentsOrgChartLayout-T3vfKGm-.js} +1 -1
- package/dist/client/assets/{app-DKzqBaeH.js → app-BUPxz3_I.js} +1 -1
- package/dist/client/assets/{app-y8x9KYqa.js → app-Bsb-vSJ2.js} +3 -3
- package/dist/client/assets/{app-DkJZhePX.js → app-CDMzhkVk.js} +1 -1
- package/dist/client/assets/{app-BtBMuy2Z.js → app-Ca3_7roP.js} +3 -3
- package/dist/client/assets/{app-JnrgtY9I.js → app-CaiQxtA9.js} +3 -3
- package/dist/client/assets/{app-LrO9EOLE.js → app-D7N3gRgK.js} +3 -3
- package/dist/client/assets/{app-Cv-4fcPl.js → app-Du0s0Xs8.js} +1 -1
- package/dist/client/assets/{architectureDiagram-3BPJPVTR-2_yoUOD5.js → architectureDiagram-3BPJPVTR-CG7lqp3T.js} +1 -1
- package/dist/client/assets/{blockDiagram-GPEHLZMM-ueBSwDJh.js → blockDiagram-GPEHLZMM-CCQyln9-.js} +1 -1
- package/dist/client/assets/{c4Diagram-AAUBKEIU-D0cUU3pE.js → c4Diagram-AAUBKEIU-DgTWfMuv.js} +1 -1
- package/dist/client/assets/channel-DQn8tAbt.js +1 -0
- package/dist/client/assets/{chunk-2J33WTMH-DKJnGdD6.js → chunk-2J33WTMH-DbvgPKWu.js} +1 -1
- package/dist/client/assets/{chunk-4BX2VUAB-BUrgUtvt.js → chunk-4BX2VUAB-Jeug78io.js} +1 -1
- package/dist/client/assets/{chunk-55IACEB6-DHy2hCYz.js → chunk-55IACEB6-wSkfWEqo.js} +1 -1
- package/dist/client/assets/{chunk-727SXJPM-Dgbhllem.js → chunk-727SXJPM-o-cSBR4a.js} +1 -1
- package/dist/client/assets/{chunk-AQP2D5EJ-tPbicvl-.js → chunk-AQP2D5EJ-9iL_Co48.js} +1 -1
- package/dist/client/assets/{chunk-FMBD7UC4-BpHFGFmo.js → chunk-FMBD7UC4-HKJKjpLt.js} +1 -1
- package/dist/client/assets/{chunk-ND2GUHAM-DUTQ63ld.js → chunk-ND2GUHAM-DZUdY7Yv.js} +1 -1
- package/dist/client/assets/{chunk-QZHKN3VN-ChCf_usL.js → chunk-QZHKN3VN-AFzlVJep.js} +1 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-BVZs0DmH.js +1 -0
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-BVZs0DmH.js +1 -0
- package/dist/client/assets/{cose-bilkent-S5V4N54A-DgWzHtF9.js → cose-bilkent-S5V4N54A-vhimfYza.js} +1 -1
- package/dist/client/assets/{dagre-BM42HDAG-gQ1C1xHJ.js → dagre-BM42HDAG-wPz2jgXD.js} +1 -1
- package/dist/client/assets/{dashboard-view-BtFepPos.js → dashboard-view-BJVPfjWI.js} +1 -1
- package/dist/client/assets/{dashboard-view-BXtoQ9a4.js → dashboard-view-BN6as5aN.js} +1 -1
- package/dist/client/assets/{dashboard-view-AQmzkBNb.js → dashboard-view-ByLTU9KO.js} +1 -1
- package/dist/client/assets/{dashboard-view-BLenRoXu.js → dashboard-view-HiX6AOAw.js} +1 -1
- package/dist/client/assets/{diagram-2AECGRRQ-Dv96I1MI.js → diagram-2AECGRRQ-DvPGnzo9.js} +1 -1
- package/dist/client/assets/{diagram-5GNKFQAL-BRyhjYes.js → diagram-5GNKFQAL-CUD0xVXq.js} +1 -1
- package/dist/client/assets/{diagram-KO2AKTUF-Bmj3ihjc.js → diagram-KO2AKTUF-p88av64o.js} +1 -1
- package/dist/client/assets/{diagram-LMA3HP47-BYHVCFK2.js → diagram-LMA3HP47-B2V_VFOf.js} +1 -1
- package/dist/client/assets/{diagram-OG6HWLK6-0WZBLayt.js → diagram-OG6HWLK6-CO02xKJJ.js} +1 -1
- package/dist/client/assets/{erDiagram-TEJ5UH35-Cu-yj8hA.js → erDiagram-TEJ5UH35-LiIZMOks.js} +1 -1
- package/dist/client/assets/{flowDiagram-I6XJVG4X-BSetu6oh.js → flowDiagram-I6XJVG4X-BMgU0xdB.js} +1 -1
- package/dist/client/assets/{folder-open-CkswT0lE.js → folder-open-Bfz0pfA0.js} +1 -1
- package/dist/client/assets/{ganttDiagram-6RSMTGT7-B5qn0KFQ.js → ganttDiagram-6RSMTGT7-C-DNnJ7F.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-PVQCEYII-BVB3wm46.js → gitGraphDiagram-PVQCEYII-BKnH_s4c.js} +1 -1
- package/dist/client/assets/index-D6zw4rNc.js +2937 -0
- package/dist/client/assets/index-lxhrCjd_.css +1 -0
- package/dist/client/assets/{infoDiagram-5YYISTIA-ZBNKOBSK.js → infoDiagram-5YYISTIA-DrFgtiS_.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-CbNKgenI.js → ishikawaDiagram-YF4QCWOH-cXcVkWVR.js} +1 -1
- package/dist/client/assets/{journeyDiagram-JHISSGLW-BLc2FHIF.js → journeyDiagram-JHISSGLW-2rAR6JrI.js} +1 -1
- package/dist/client/assets/{kanban-definition-UN3LZRKU-B08tij8f.js → kanban-definition-UN3LZRKU-uaIVKg6k.js} +1 -1
- package/dist/client/assets/{mermaid.core-QX5z7w8Z.js → mermaid.core-Bl1eKb-3.js} +4 -4
- package/dist/client/assets/{mindmap-definition-RKZ34NQL-C1md8M3c.js → mindmap-definition-RKZ34NQL-C_ZfL855.js} +1 -1
- package/dist/client/assets/{pieDiagram-4H26LBE5-BoQbn3Xp.js → pieDiagram-4H26LBE5-B-GWMxe6.js} +1 -1
- package/dist/client/assets/{puzzle-DCqPnWPE.js → puzzle--EYtEUHj.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-W4KKPZXB-DPvNcVK-.js → quadrantDiagram-W4KKPZXB-C4yu-vxx.js} +1 -1
- package/dist/client/assets/{requirementDiagram-4Y6WPE33-KfdYf15t.js → requirementDiagram-4Y6WPE33-CmsMO-mZ.js} +1 -1
- package/dist/client/assets/{sankeyDiagram-5OEKKPKP-D1Eyoanf.js → sankeyDiagram-5OEKKPKP-DKXXMJDr.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-3UESZ5HK-CmODsbCf.js → sequenceDiagram-3UESZ5HK-DbpptsX5.js} +1 -1
- package/dist/client/assets/{standing-instructions-template-D_mPaGcG.js → standing-instructions-template-bCcrFYtU.js} +1 -1
- package/dist/client/assets/{stateDiagram-AJRCARHV-Blbw_21G.js → stateDiagram-AJRCARHV-DDwdEj_k.js} +1 -1
- package/dist/client/assets/{stateDiagram-v2-BHNVJYJU-DwMgvYO8.js → stateDiagram-v2-BHNVJYJU-CjOnclTc.js} +1 -1
- package/dist/client/assets/{timeline-definition-PNZ67QCA-DDtndgLc.js → timeline-definition-PNZ67QCA-Q8Appf3Z.js} +1 -1
- package/dist/client/assets/{upload-DGCjJkMH.js → upload-Ka3GrAEL.js} +1 -1
- package/dist/client/assets/{users-CbWZvFZP.js → users-B7a_oi7v.js} +1 -1
- package/dist/client/assets/{vennDiagram-CIIHVFJN-B6Sx0OqW.js → vennDiagram-CIIHVFJN-ZsuVN3Hk.js} +1 -1
- package/dist/client/assets/{wardley-L42UT6IY-_SQFYU4g.js → wardley-L42UT6IY-Eh9WyxS2.js} +1 -1
- package/dist/client/assets/{wardleyDiagram-YWT4CUSO-Ce5igv6s.js → wardleyDiagram-YWT4CUSO-CG1fl8Sj.js} +1 -1
- package/dist/client/assets/{xychartDiagram-2RQKCTM6-zI0zyvDP.js → xychartDiagram-2RQKCTM6-BnZAlrGh.js} +1 -1
- package/dist/client/index.html +2 -2
- package/dist/client/version.json +1 -1
- package/dist/droid-cli/package.json +1 -1
- package/dist/extension.js +1479 -798
- package/dist/pi-claude-cli/package.json +1 -1
- package/dist/plugin-sdk/index.d.ts +1 -1
- package/dist/plugin-sdk/index.js +25 -14
- package/dist/plugins/fusion-plugin-acp-runtime/bundled.js +25 -14
- package/dist/plugins/fusion-plugin-acp-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-claude-runtime/bundled.js +25 -14
- package/dist/plugins/fusion-plugin-claude-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-cli-printing-press/bundled.js +25 -14
- package/dist/plugins/fusion-plugin-cli-printing-press/package.json +1 -1
- package/dist/plugins/fusion-plugin-compound-engineering/bundled.js +25 -14
- package/dist/plugins/fusion-plugin-compound-engineering/package.json +1 -1
- package/dist/plugins/fusion-plugin-cursor-runtime/bundled.js +25 -14
- package/dist/plugins/fusion-plugin-cursor-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-dependency-graph/bundled.js +25 -14
- package/dist/plugins/fusion-plugin-dependency-graph/package.json +1 -1
- package/dist/plugins/fusion-plugin-droid-runtime/bundled.js +25 -14
- package/dist/plugins/fusion-plugin-droid-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-grok-runtime/bundled.js +25 -14
- package/dist/plugins/fusion-plugin-grok-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-hermes-runtime/bundled.js +25 -14
- package/dist/plugins/fusion-plugin-hermes-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-linear-import/bundled.js +25 -14
- package/dist/plugins/fusion-plugin-linear-import/package.json +1 -1
- package/dist/plugins/fusion-plugin-omp-runtime/bundled.js +25 -14
- package/dist/plugins/fusion-plugin-omp-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-openclaw-runtime/bundled.js +25 -14
- package/dist/plugins/fusion-plugin-openclaw-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-paperclip-runtime/bundled.js +25 -14
- package/dist/plugins/fusion-plugin-paperclip-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-quality/bundled.js +25 -14
- package/dist/plugins/fusion-plugin-quality/package.json +1 -1
- package/dist/plugins/fusion-plugin-reports/bundled.js +25 -14
- package/dist/plugins/fusion-plugin-reports/package.json +1 -1
- package/dist/plugins/fusion-plugin-roadmap/bundled.js +25 -14
- package/dist/plugins/fusion-plugin-roadmap/package.json +1 -1
- package/dist/plugins/fusion-plugin-todos/bundled.js +25 -14
- package/dist/plugins/fusion-plugin-todos/package.json +1 -1
- package/dist/plugins/fusion-plugin-whatsapp-chat/bundled.js +25 -14
- package/dist/plugins/fusion-plugin-whatsapp-chat/package.json +1 -1
- package/package.json +1 -1
- package/dist/client/assets/AgentDetailView-jzgy1BAS.css +0 -1
- package/dist/client/assets/CommandCenter-ilm-DbtI.css +0 -1
- package/dist/client/assets/SettingsModal-B1UCDc_h.js +0 -21
- package/dist/client/assets/SettingsModal-C5ic1ls7.css +0 -1
- package/dist/client/assets/channel-DfvbdnTK.js +0 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-CkMyClXV.js +0 -1
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-CkMyClXV.js +0 -1
- package/dist/client/assets/index-BgE915SE.js +0 -2937
- package/dist/client/assets/index-e2yEk7y4.css +0 -1
package/dist/extension.js
CHANGED
|
@@ -1513,6 +1513,199 @@ Be specific: cite the plan section or file path for every finding and explain th
|
|
|
1513
1513
|
}
|
|
1514
1514
|
});
|
|
1515
1515
|
|
|
1516
|
+
// ../core/src/workflows/workflow-merge-region.ts
|
|
1517
|
+
function isMergeRegionNode(node) {
|
|
1518
|
+
return MERGE_REGION_ENTRY_NODE_KINDS.has(node.kind) || node.config?.seam === "merge";
|
|
1519
|
+
}
|
|
1520
|
+
function classifyWorkflowNodeMergeRegion(ir2, nodeId) {
|
|
1521
|
+
if (ir2.version !== "v2" || !Array.isArray(ir2.nodes)) return "unknown";
|
|
1522
|
+
const node = ir2.nodes.find((candidate) => candidate.id === nodeId);
|
|
1523
|
+
if (!node) return "unknown";
|
|
1524
|
+
return isMergeRegionNode(node) ? "merge-region" : "outside-merge-region";
|
|
1525
|
+
}
|
|
1526
|
+
var MERGE_REGION_ENTRY_NODE_KINDS;
|
|
1527
|
+
var init_workflow_merge_region = __esm({
|
|
1528
|
+
"../core/src/workflows/workflow-merge-region.ts"() {
|
|
1529
|
+
"use strict";
|
|
1530
|
+
MERGE_REGION_ENTRY_NODE_KINDS = /* @__PURE__ */ new Set([
|
|
1531
|
+
"merge-gate",
|
|
1532
|
+
"merge-attempt",
|
|
1533
|
+
"manual-merge-hold",
|
|
1534
|
+
"retry-backoff",
|
|
1535
|
+
"recovery-router",
|
|
1536
|
+
"branch-group-member-integration",
|
|
1537
|
+
"branch-group-promotion",
|
|
1538
|
+
"pr-create",
|
|
1539
|
+
"pr-respond",
|
|
1540
|
+
"pr-merge"
|
|
1541
|
+
]);
|
|
1542
|
+
}
|
|
1543
|
+
});
|
|
1544
|
+
|
|
1545
|
+
// ../core/src/workflows/workflow-optional-steps.ts
|
|
1546
|
+
function isWorkflowOptionalGroupEnabled(enabledWorkflowSteps, groupId, defaultOn = false) {
|
|
1547
|
+
return Array.isArray(enabledWorkflowSteps) ? enabledWorkflowSteps.includes(groupId) : defaultOn;
|
|
1548
|
+
}
|
|
1549
|
+
function isOptionalGroupNode(node) {
|
|
1550
|
+
return node.kind === "optional-group";
|
|
1551
|
+
}
|
|
1552
|
+
function computeNodeExecutionRanks(ir2) {
|
|
1553
|
+
const ranks = /* @__PURE__ */ new Map();
|
|
1554
|
+
if (ir2.version !== "v2" || !Array.isArray(ir2.nodes) || !Array.isArray(ir2.edges)) {
|
|
1555
|
+
return ranks;
|
|
1556
|
+
}
|
|
1557
|
+
const outgoing = /* @__PURE__ */ new Map();
|
|
1558
|
+
for (const edge of ir2.edges) {
|
|
1559
|
+
if (!outgoing.has(edge.from)) outgoing.set(edge.from, []);
|
|
1560
|
+
outgoing.get(edge.from)?.push(edge.to);
|
|
1561
|
+
}
|
|
1562
|
+
const queue = [];
|
|
1563
|
+
for (const node of ir2.nodes) {
|
|
1564
|
+
if (node.kind === "start" || node.id === "start") {
|
|
1565
|
+
queue.push({ id: node.id, rank: 0 });
|
|
1566
|
+
}
|
|
1567
|
+
}
|
|
1568
|
+
while (queue.length > 0) {
|
|
1569
|
+
const next = queue.shift();
|
|
1570
|
+
if (!next) continue;
|
|
1571
|
+
const current = ranks.get(next.id);
|
|
1572
|
+
if (current !== void 0 && current <= next.rank) continue;
|
|
1573
|
+
ranks.set(next.id, next.rank);
|
|
1574
|
+
for (const target of outgoing.get(next.id) ?? []) {
|
|
1575
|
+
queue.push({ id: target, rank: next.rank + 1 });
|
|
1576
|
+
}
|
|
1577
|
+
}
|
|
1578
|
+
return ranks;
|
|
1579
|
+
}
|
|
1580
|
+
function resolveWorkflowOptionalSteps(ir2, _pluginTemplates = []) {
|
|
1581
|
+
if (ir2.version !== "v2" || !Array.isArray(ir2.nodes)) return [];
|
|
1582
|
+
const ranks = computeNodeExecutionRanks(ir2);
|
|
1583
|
+
const resolved = [];
|
|
1584
|
+
for (const [nodeIndex, node] of ir2.nodes.entries()) {
|
|
1585
|
+
if (!isOptionalGroupNode(node)) continue;
|
|
1586
|
+
const config3 = node.config ?? {};
|
|
1587
|
+
resolved.push({
|
|
1588
|
+
// Keyed by the group node id (documented above); field name preserved.
|
|
1589
|
+
templateId: node.id,
|
|
1590
|
+
name: typeof config3.name === "string" && config3.name.trim() ? config3.name : node.id,
|
|
1591
|
+
description: "",
|
|
1592
|
+
/*
|
|
1593
|
+
FNXC:WorkflowOptionalSteps 2026-06-29-12:47:
|
|
1594
|
+
Post-merge verification is now a graph-native optional group. Task creation and detail surfaces need the resolver to preserve `config.phase` so post-merge toggles do not look like pre-merge gates.
|
|
1595
|
+
*/
|
|
1596
|
+
phase: config3.phase === "post-merge" ? "post-merge" : "pre-merge",
|
|
1597
|
+
defaultOn: config3.defaultOn === true,
|
|
1598
|
+
reportingOnly: config3.reportingOnly === true,
|
|
1599
|
+
/*
|
|
1600
|
+
FNXC:WorkflowDefinitionSteps 2026-06-29-00:41:
|
|
1601
|
+
Definition/task creation surfaces must order optional groups by graph execution position, not raw node-array order. Derived built-ins can insert Plan Review between planning and parse while appending its node object, and operators still need the step list to show Plan Review before execution.
|
|
1602
|
+
*/
|
|
1603
|
+
rank: ranks.get(node.id) ?? Number.MAX_SAFE_INTEGER,
|
|
1604
|
+
nodeIndex
|
|
1605
|
+
});
|
|
1606
|
+
}
|
|
1607
|
+
return resolved.sort((a, b3) => a.rank - b3.rank || a.nodeIndex - b3.nodeIndex).map(({ rank: _rank, nodeIndex: _nodeIndex, ...step }) => step);
|
|
1608
|
+
}
|
|
1609
|
+
function resolveDefaultOnOptionalGroupIds(ir2) {
|
|
1610
|
+
return resolveWorkflowOptionalSteps(ir2).filter((step) => step.defaultOn).map((step) => step.templateId);
|
|
1611
|
+
}
|
|
1612
|
+
function resolveAllOptionalGroupIds(ir2) {
|
|
1613
|
+
return resolveWorkflowOptionalSteps(ir2).map((step) => step.templateId);
|
|
1614
|
+
}
|
|
1615
|
+
function isReportingOnlyOptionalGroup(ir2, nodeId) {
|
|
1616
|
+
if (!nodeId) return false;
|
|
1617
|
+
return resolveWorkflowOptionalSteps(ir2).some((step) => step.templateId === nodeId && step.reportingOnly);
|
|
1618
|
+
}
|
|
1619
|
+
var init_workflow_optional_steps = __esm({
|
|
1620
|
+
"../core/src/workflows/workflow-optional-steps.ts"() {
|
|
1621
|
+
"use strict";
|
|
1622
|
+
}
|
|
1623
|
+
});
|
|
1624
|
+
|
|
1625
|
+
// ../core/src/workflows/workflow-fast-lane.ts
|
|
1626
|
+
function isFastExecutionMode(task) {
|
|
1627
|
+
return task.executionMode === "fast";
|
|
1628
|
+
}
|
|
1629
|
+
function configString(node, key) {
|
|
1630
|
+
const value = node.config?.[key];
|
|
1631
|
+
return typeof value === "string" ? value : void 0;
|
|
1632
|
+
}
|
|
1633
|
+
function isTaskStepsForeach(node) {
|
|
1634
|
+
return node.kind === "foreach" && node.config?.source === "task-steps";
|
|
1635
|
+
}
|
|
1636
|
+
function isFastLaneSkippableCustomNode(node, opts = {}) {
|
|
1637
|
+
if (node.config?.summaryTarget === "task" || node.id === "completion-summary") return false;
|
|
1638
|
+
if (opts.optionalGroupId) return false;
|
|
1639
|
+
if (node.config?.seam) return false;
|
|
1640
|
+
return node.kind === "prompt" || node.kind === "script" || node.kind === "gate";
|
|
1641
|
+
}
|
|
1642
|
+
function isFastLaneBypassedTemplateNode(node) {
|
|
1643
|
+
return node.kind === "step-review";
|
|
1644
|
+
}
|
|
1645
|
+
function inactiveRoute() {
|
|
1646
|
+
return {
|
|
1647
|
+
active: false,
|
|
1648
|
+
bypassedNodeIds: /* @__PURE__ */ new Set(),
|
|
1649
|
+
bypassedPreMergeGroups: [],
|
|
1650
|
+
parseStepsNodeIds: /* @__PURE__ */ new Set()
|
|
1651
|
+
};
|
|
1652
|
+
}
|
|
1653
|
+
function resolveFastLaneRoute(ir2, task) {
|
|
1654
|
+
if (!isFastExecutionMode(task)) return inactiveRoute();
|
|
1655
|
+
const foreachNode = ir2.nodes.find(isTaskStepsForeach);
|
|
1656
|
+
const executeNode = ir2.nodes.find((node) => configString(node, "seam") === "execute");
|
|
1657
|
+
const implementationNode = foreachNode ?? executeNode;
|
|
1658
|
+
if (!implementationNode) {
|
|
1659
|
+
return { ...inactiveRoute(), unsupportedReason: "no-implementation-node" };
|
|
1660
|
+
}
|
|
1661
|
+
const implementationKind = foreachNode ? "foreach-steps" : "execute-seam";
|
|
1662
|
+
const bypassedPreMergeGroups = resolveWorkflowOptionalSteps(ir2).filter((step) => step.phase === "pre-merge").map((step) => ({ nodeId: step.templateId, name: step.name }));
|
|
1663
|
+
const bypassedGroupIds = new Set(bypassedPreMergeGroups.map((group) => group.nodeId));
|
|
1664
|
+
const bypassedNodeIds = /* @__PURE__ */ new Set();
|
|
1665
|
+
for (const node of ir2.nodes) {
|
|
1666
|
+
if (isMergeRegionNode(node) || node.id === "completion-summary" || node.config?.summaryTarget === "task") continue;
|
|
1667
|
+
if (configString(node, "seam") === "planning") {
|
|
1668
|
+
bypassedNodeIds.add(node.id);
|
|
1669
|
+
continue;
|
|
1670
|
+
}
|
|
1671
|
+
if (bypassedGroupIds.has(node.id)) {
|
|
1672
|
+
bypassedNodeIds.add(node.id);
|
|
1673
|
+
continue;
|
|
1674
|
+
}
|
|
1675
|
+
const workflowAction = configString(node, "workflowAction");
|
|
1676
|
+
const groupId = configString(node, "forWorkflowStepId");
|
|
1677
|
+
if (workflowAction === "plan-replan" || workflowAction === "plan-review-no-op" || workflowAction === "pre-merge-remediation" || workflowAction === "review-remediation-steps" || groupId !== void 0 && bypassedGroupIds.has(groupId)) {
|
|
1678
|
+
bypassedNodeIds.add(node.id);
|
|
1679
|
+
}
|
|
1680
|
+
}
|
|
1681
|
+
const parseStepsNodeIds = new Set(ir2.nodes.filter((node) => node.kind === "parse-steps").map((node) => node.id));
|
|
1682
|
+
for (const parseNodeId of parseStepsNodeIds) {
|
|
1683
|
+
if (bypassedNodeIds.has(parseNodeId)) {
|
|
1684
|
+
throw new Error(`Fast lane cannot bypass parse-steps node '${parseNodeId}'`);
|
|
1685
|
+
}
|
|
1686
|
+
}
|
|
1687
|
+
return {
|
|
1688
|
+
active: true,
|
|
1689
|
+
bypassedNodeIds,
|
|
1690
|
+
bypassedPreMergeGroups,
|
|
1691
|
+
parseStepsNodeIds,
|
|
1692
|
+
implementationNodeId: implementationNode.id,
|
|
1693
|
+
implementationKind
|
|
1694
|
+
};
|
|
1695
|
+
}
|
|
1696
|
+
var FAST_LANE_STEP_NAME, FAST_LANE_SKIP_VALUE, FAST_MODE_BYPASS_ACTOR, FAST_LANE_STEP_REVIEW_ROUTE_VALUE;
|
|
1697
|
+
var init_workflow_fast_lane = __esm({
|
|
1698
|
+
"../core/src/workflows/workflow-fast-lane.ts"() {
|
|
1699
|
+
"use strict";
|
|
1700
|
+
init_workflow_merge_region();
|
|
1701
|
+
init_workflow_optional_steps();
|
|
1702
|
+
FAST_LANE_STEP_NAME = "Fast implementation";
|
|
1703
|
+
FAST_LANE_SKIP_VALUE = "fast-lane-skip";
|
|
1704
|
+
FAST_MODE_BYPASS_ACTOR = "fast-mode";
|
|
1705
|
+
FAST_LANE_STEP_REVIEW_ROUTE_VALUE = "approve";
|
|
1706
|
+
}
|
|
1707
|
+
});
|
|
1708
|
+
|
|
1516
1709
|
// ../core/src/workflows/workflow-step-results.ts
|
|
1517
1710
|
function isWorkflowStepNotRun(result2) {
|
|
1518
1711
|
return result2.status === "skipped" && typeof result2.notRunReason === "string" && WORKFLOW_STEP_NOT_RUN_REASONS.includes(result2.notRunReason);
|
|
@@ -1813,6 +2006,31 @@ var init_workflow_step_results = __esm({
|
|
|
1813
2006
|
});
|
|
1814
2007
|
|
|
1815
2008
|
// ../core/src/merge/pre-merge-approval.ts
|
|
2009
|
+
function requiresContentReviewProof(workflowStepId, result2) {
|
|
2010
|
+
return workflowStepId === "code-review" || result2.reviewKind === "code";
|
|
2011
|
+
}
|
|
2012
|
+
function isAuditedOperatorBypass(result2) {
|
|
2013
|
+
if (result2.status !== "skipped") return false;
|
|
2014
|
+
const actor = result2.bypassedBy?.trim();
|
|
2015
|
+
return Boolean(
|
|
2016
|
+
actor && !AUTOMATED_BYPASS_ACTORS.has(actor) && result2.bypassedAt?.trim() && result2.bypassReason?.trim()
|
|
2017
|
+
);
|
|
2018
|
+
}
|
|
2019
|
+
function resolveUnprovenReviewApproval(result2, options) {
|
|
2020
|
+
if ((result2.phase ?? "pre-merge") !== "pre-merge" || !requiresContentReviewProof(result2.workflowStepId, result2) || options.workspace || result2.status !== "passed" || result2.verdict !== "APPROVE" && result2.verdict !== "APPROVE_WITH_NOTES" || result2.reviewInputFingerprint !== void 0 || result2.bypassedBy !== void 0 || result2.remediationArchivedAt != null) {
|
|
2021
|
+
return void 0;
|
|
2022
|
+
}
|
|
2023
|
+
const { verdict: _verdict, ...withoutVerdict } = result2;
|
|
2024
|
+
return {
|
|
2025
|
+
downgraded: {
|
|
2026
|
+
...withoutVerdict,
|
|
2027
|
+
status: "failed",
|
|
2028
|
+
output: UNPROVEN_REVIEW_APPROVAL_DIAGNOSTIC,
|
|
2029
|
+
notes: UNPROVEN_REVIEW_APPROVAL_DIAGNOSTIC
|
|
2030
|
+
},
|
|
2031
|
+
reason: UNPROVEN_REVIEW_APPROVAL_DIAGNOSTIC
|
|
2032
|
+
};
|
|
2033
|
+
}
|
|
1816
2034
|
function evaluatePreMergeApprovals(task, options = {}) {
|
|
1817
2035
|
const required2 = options.requiredPreMergeStepIds;
|
|
1818
2036
|
if (!required2?.size) return [];
|
|
@@ -1823,13 +2041,16 @@ function evaluateStep(workflowStepId, results, task, descriptor) {
|
|
|
1823
2041
|
const result2 = results.filter((candidate) => candidate.workflowStepId === workflowStepId).at(-1);
|
|
1824
2042
|
if (!result2 && descriptor?.kind !== "workspace") return { workflowStepId, state: "missing" };
|
|
1825
2043
|
if (result2) {
|
|
1826
|
-
const requiresExplicitVerdict = workflowStepId
|
|
2044
|
+
const requiresExplicitVerdict = requiresContentReviewProof(workflowStepId, result2);
|
|
1827
2045
|
const approvedVerdict = result2.verdict === "APPROVE" || result2.verdict === "APPROVE_WITH_NOTES";
|
|
1828
2046
|
const isPlanDomain = workflowStepId === PLAN_REVIEW_GROUP_ID || result2.reviewKind === "plan";
|
|
1829
2047
|
const notRunApproves = isWorkflowStepNotRun(result2) && !requiresExplicitVerdict && !isPlanDomain;
|
|
1830
2048
|
const approved = result2.status === "passed" && (requiresExplicitVerdict ? approvedVerdict : result2.verdict === void 0 || approvedVerdict) || result2.status === "skipped" && !!result2.bypassedBy || notRunApproves;
|
|
1831
2049
|
if (!approved || !!result2.remediationArchivedAt) return { workflowStepId, state: "not-approved" };
|
|
1832
2050
|
if (result2.reviewKind === "plan") return { workflowStepId, state: "approved" };
|
|
2051
|
+
if (isAuditedOperatorBypass(result2) && descriptor?.kind !== "workspace") {
|
|
2052
|
+
return { workflowStepId, state: "approved" };
|
|
2053
|
+
}
|
|
1833
2054
|
const bindsContent = requiresExplicitVerdict || result2.reviewInputFingerprint !== void 0;
|
|
1834
2055
|
if (!bindsContent) return { workflowStepId, state: "approved" };
|
|
1835
2056
|
}
|
|
@@ -1860,11 +2081,15 @@ function evaluateStep(workflowStepId, results, task, descriptor) {
|
|
|
1860
2081
|
if (stale2.length) return { workflowStepId, state: "stale-content", repositories: stale2 };
|
|
1861
2082
|
return { workflowStepId, state: "approved" };
|
|
1862
2083
|
}
|
|
2084
|
+
var AUTOMATED_BYPASS_ACTORS, UNPROVEN_REVIEW_APPROVAL_DIAGNOSTIC;
|
|
1863
2085
|
var init_pre_merge_approval = __esm({
|
|
1864
2086
|
"../core/src/merge/pre-merge-approval.ts"() {
|
|
1865
2087
|
"use strict";
|
|
1866
2088
|
init_builtin_plan_review_group();
|
|
2089
|
+
init_workflow_fast_lane();
|
|
1867
2090
|
init_workflow_step_results();
|
|
2091
|
+
AUTOMATED_BYPASS_ACTORS = /* @__PURE__ */ new Set([FAST_MODE_BYPASS_ACTOR]);
|
|
2092
|
+
UNPROVEN_REVIEW_APPROVAL_DIAGNOSTIC = "Content-binding review approval recorded without reviewInputFingerprint; approval invalidated so the gate can run again.";
|
|
1868
2093
|
}
|
|
1869
2094
|
});
|
|
1870
2095
|
|
|
@@ -11374,35 +11599,6 @@ var init_workflow_ir_types = __esm({
|
|
|
11374
11599
|
}
|
|
11375
11600
|
});
|
|
11376
11601
|
|
|
11377
|
-
// ../core/src/workflows/workflow-merge-region.ts
|
|
11378
|
-
function isMergeRegionNode(node) {
|
|
11379
|
-
return MERGE_REGION_ENTRY_NODE_KINDS.has(node.kind) || node.config?.seam === "merge";
|
|
11380
|
-
}
|
|
11381
|
-
function classifyWorkflowNodeMergeRegion(ir2, nodeId) {
|
|
11382
|
-
if (ir2.version !== "v2" || !Array.isArray(ir2.nodes)) return "unknown";
|
|
11383
|
-
const node = ir2.nodes.find((candidate) => candidate.id === nodeId);
|
|
11384
|
-
if (!node) return "unknown";
|
|
11385
|
-
return isMergeRegionNode(node) ? "merge-region" : "outside-merge-region";
|
|
11386
|
-
}
|
|
11387
|
-
var MERGE_REGION_ENTRY_NODE_KINDS;
|
|
11388
|
-
var init_workflow_merge_region = __esm({
|
|
11389
|
-
"../core/src/workflows/workflow-merge-region.ts"() {
|
|
11390
|
-
"use strict";
|
|
11391
|
-
MERGE_REGION_ENTRY_NODE_KINDS = /* @__PURE__ */ new Set([
|
|
11392
|
-
"merge-gate",
|
|
11393
|
-
"merge-attempt",
|
|
11394
|
-
"manual-merge-hold",
|
|
11395
|
-
"retry-backoff",
|
|
11396
|
-
"recovery-router",
|
|
11397
|
-
"branch-group-member-integration",
|
|
11398
|
-
"branch-group-promotion",
|
|
11399
|
-
"pr-create",
|
|
11400
|
-
"pr-respond",
|
|
11401
|
-
"pr-merge"
|
|
11402
|
-
]);
|
|
11403
|
-
}
|
|
11404
|
-
});
|
|
11405
|
-
|
|
11406
11602
|
// ../core/src/workflows/workflow-extension-types.ts
|
|
11407
11603
|
function workflowExtensionRegistryId(pluginId, extensionId) {
|
|
11408
11604
|
return `plugin:${pluginId}:${extensionId}`;
|
|
@@ -12398,6 +12594,16 @@ function validateReviewerAgentOverrides(nodes2) {
|
|
|
12398
12594
|
if (Array.isArray(templateNodes)) validateReviewerAgentOverrides(templateNodes);
|
|
12399
12595
|
}
|
|
12400
12596
|
}
|
|
12597
|
+
function validateReadonlyMcpServersConfig(nodes2) {
|
|
12598
|
+
for (const node of nodes2) {
|
|
12599
|
+
const value = node.config?.readonlyMcpServers;
|
|
12600
|
+
if (value !== void 0 && (!Array.isArray(value) || value.some((name2) => typeof name2 !== "string" || !name2.trim()))) {
|
|
12601
|
+
throw new WorkflowIrError(`Workflow node '${node.id}' readonlyMcpServers must be an array of non-empty strings when present`);
|
|
12602
|
+
}
|
|
12603
|
+
const templateNodes = node.config?.template?.nodes;
|
|
12604
|
+
if (Array.isArray(templateNodes)) validateReadonlyMcpServersConfig(templateNodes);
|
|
12605
|
+
}
|
|
12606
|
+
}
|
|
12401
12607
|
function validateThinkingLevelConfig(nodes2) {
|
|
12402
12608
|
for (const node of nodes2) {
|
|
12403
12609
|
const value = node.config?.thinkingLevel;
|
|
@@ -13012,6 +13218,7 @@ function validateV2(ir2) {
|
|
|
13012
13218
|
const topLevelIds = new Set(ir2.nodes.map((n) => n.id));
|
|
13013
13219
|
validateStepExecutePlacement(ir2.nodes);
|
|
13014
13220
|
validateThinkingLevelConfig(ir2.nodes);
|
|
13221
|
+
validateReadonlyMcpServersConfig(ir2.nodes);
|
|
13015
13222
|
validateCredentialInstanceIdConfig(ir2.nodes);
|
|
13016
13223
|
validateReviewerAgentOverrides(ir2.nodes);
|
|
13017
13224
|
for (const node of ir2.nodes) {
|
|
@@ -29082,169 +29289,6 @@ var init_explicit_duplicate_marker = __esm({
|
|
|
29082
29289
|
}
|
|
29083
29290
|
});
|
|
29084
29291
|
|
|
29085
|
-
// ../core/src/workflows/workflow-optional-steps.ts
|
|
29086
|
-
function isWorkflowOptionalGroupEnabled(enabledWorkflowSteps, groupId, defaultOn = false) {
|
|
29087
|
-
return Array.isArray(enabledWorkflowSteps) ? enabledWorkflowSteps.includes(groupId) : defaultOn;
|
|
29088
|
-
}
|
|
29089
|
-
function isOptionalGroupNode(node) {
|
|
29090
|
-
return node.kind === "optional-group";
|
|
29091
|
-
}
|
|
29092
|
-
function computeNodeExecutionRanks(ir2) {
|
|
29093
|
-
const ranks = /* @__PURE__ */ new Map();
|
|
29094
|
-
if (ir2.version !== "v2" || !Array.isArray(ir2.nodes) || !Array.isArray(ir2.edges)) {
|
|
29095
|
-
return ranks;
|
|
29096
|
-
}
|
|
29097
|
-
const outgoing = /* @__PURE__ */ new Map();
|
|
29098
|
-
for (const edge of ir2.edges) {
|
|
29099
|
-
if (!outgoing.has(edge.from)) outgoing.set(edge.from, []);
|
|
29100
|
-
outgoing.get(edge.from)?.push(edge.to);
|
|
29101
|
-
}
|
|
29102
|
-
const queue = [];
|
|
29103
|
-
for (const node of ir2.nodes) {
|
|
29104
|
-
if (node.kind === "start" || node.id === "start") {
|
|
29105
|
-
queue.push({ id: node.id, rank: 0 });
|
|
29106
|
-
}
|
|
29107
|
-
}
|
|
29108
|
-
while (queue.length > 0) {
|
|
29109
|
-
const next = queue.shift();
|
|
29110
|
-
if (!next) continue;
|
|
29111
|
-
const current = ranks.get(next.id);
|
|
29112
|
-
if (current !== void 0 && current <= next.rank) continue;
|
|
29113
|
-
ranks.set(next.id, next.rank);
|
|
29114
|
-
for (const target of outgoing.get(next.id) ?? []) {
|
|
29115
|
-
queue.push({ id: target, rank: next.rank + 1 });
|
|
29116
|
-
}
|
|
29117
|
-
}
|
|
29118
|
-
return ranks;
|
|
29119
|
-
}
|
|
29120
|
-
function resolveWorkflowOptionalSteps(ir2, _pluginTemplates = []) {
|
|
29121
|
-
if (ir2.version !== "v2" || !Array.isArray(ir2.nodes)) return [];
|
|
29122
|
-
const ranks = computeNodeExecutionRanks(ir2);
|
|
29123
|
-
const resolved = [];
|
|
29124
|
-
for (const [nodeIndex, node] of ir2.nodes.entries()) {
|
|
29125
|
-
if (!isOptionalGroupNode(node)) continue;
|
|
29126
|
-
const config3 = node.config ?? {};
|
|
29127
|
-
resolved.push({
|
|
29128
|
-
// Keyed by the group node id (documented above); field name preserved.
|
|
29129
|
-
templateId: node.id,
|
|
29130
|
-
name: typeof config3.name === "string" && config3.name.trim() ? config3.name : node.id,
|
|
29131
|
-
description: "",
|
|
29132
|
-
/*
|
|
29133
|
-
FNXC:WorkflowOptionalSteps 2026-06-29-12:47:
|
|
29134
|
-
Post-merge verification is now a graph-native optional group. Task creation and detail surfaces need the resolver to preserve `config.phase` so post-merge toggles do not look like pre-merge gates.
|
|
29135
|
-
*/
|
|
29136
|
-
phase: config3.phase === "post-merge" ? "post-merge" : "pre-merge",
|
|
29137
|
-
defaultOn: config3.defaultOn === true,
|
|
29138
|
-
reportingOnly: config3.reportingOnly === true,
|
|
29139
|
-
/*
|
|
29140
|
-
FNXC:WorkflowDefinitionSteps 2026-06-29-00:41:
|
|
29141
|
-
Definition/task creation surfaces must order optional groups by graph execution position, not raw node-array order. Derived built-ins can insert Plan Review between planning and parse while appending its node object, and operators still need the step list to show Plan Review before execution.
|
|
29142
|
-
*/
|
|
29143
|
-
rank: ranks.get(node.id) ?? Number.MAX_SAFE_INTEGER,
|
|
29144
|
-
nodeIndex
|
|
29145
|
-
});
|
|
29146
|
-
}
|
|
29147
|
-
return resolved.sort((a, b3) => a.rank - b3.rank || a.nodeIndex - b3.nodeIndex).map(({ rank: _rank, nodeIndex: _nodeIndex, ...step }) => step);
|
|
29148
|
-
}
|
|
29149
|
-
function resolveDefaultOnOptionalGroupIds(ir2) {
|
|
29150
|
-
return resolveWorkflowOptionalSteps(ir2).filter((step) => step.defaultOn).map((step) => step.templateId);
|
|
29151
|
-
}
|
|
29152
|
-
function resolveAllOptionalGroupIds(ir2) {
|
|
29153
|
-
return resolveWorkflowOptionalSteps(ir2).map((step) => step.templateId);
|
|
29154
|
-
}
|
|
29155
|
-
function isReportingOnlyOptionalGroup(ir2, nodeId) {
|
|
29156
|
-
if (!nodeId) return false;
|
|
29157
|
-
return resolveWorkflowOptionalSteps(ir2).some((step) => step.templateId === nodeId && step.reportingOnly);
|
|
29158
|
-
}
|
|
29159
|
-
var init_workflow_optional_steps = __esm({
|
|
29160
|
-
"../core/src/workflows/workflow-optional-steps.ts"() {
|
|
29161
|
-
"use strict";
|
|
29162
|
-
}
|
|
29163
|
-
});
|
|
29164
|
-
|
|
29165
|
-
// ../core/src/workflows/workflow-fast-lane.ts
|
|
29166
|
-
function isFastExecutionMode(task) {
|
|
29167
|
-
return task.executionMode === "fast";
|
|
29168
|
-
}
|
|
29169
|
-
function configString(node, key) {
|
|
29170
|
-
const value = node.config?.[key];
|
|
29171
|
-
return typeof value === "string" ? value : void 0;
|
|
29172
|
-
}
|
|
29173
|
-
function isTaskStepsForeach(node) {
|
|
29174
|
-
return node.kind === "foreach" && node.config?.source === "task-steps";
|
|
29175
|
-
}
|
|
29176
|
-
function isFastLaneSkippableCustomNode(node, opts = {}) {
|
|
29177
|
-
if (node.config?.summaryTarget === "task" || node.id === "completion-summary") return false;
|
|
29178
|
-
if (opts.optionalGroupId) return false;
|
|
29179
|
-
if (node.config?.seam) return false;
|
|
29180
|
-
return node.kind === "prompt" || node.kind === "script" || node.kind === "gate";
|
|
29181
|
-
}
|
|
29182
|
-
function isFastLaneBypassedTemplateNode(node) {
|
|
29183
|
-
return node.kind === "step-review";
|
|
29184
|
-
}
|
|
29185
|
-
function inactiveRoute() {
|
|
29186
|
-
return {
|
|
29187
|
-
active: false,
|
|
29188
|
-
bypassedNodeIds: /* @__PURE__ */ new Set(),
|
|
29189
|
-
bypassedPreMergeGroups: [],
|
|
29190
|
-
parseStepsNodeIds: /* @__PURE__ */ new Set()
|
|
29191
|
-
};
|
|
29192
|
-
}
|
|
29193
|
-
function resolveFastLaneRoute(ir2, task) {
|
|
29194
|
-
if (!isFastExecutionMode(task)) return inactiveRoute();
|
|
29195
|
-
const foreachNode = ir2.nodes.find(isTaskStepsForeach);
|
|
29196
|
-
const executeNode = ir2.nodes.find((node) => configString(node, "seam") === "execute");
|
|
29197
|
-
const implementationNode = foreachNode ?? executeNode;
|
|
29198
|
-
if (!implementationNode) {
|
|
29199
|
-
return { ...inactiveRoute(), unsupportedReason: "no-implementation-node" };
|
|
29200
|
-
}
|
|
29201
|
-
const implementationKind = foreachNode ? "foreach-steps" : "execute-seam";
|
|
29202
|
-
const bypassedPreMergeGroups = resolveWorkflowOptionalSteps(ir2).filter((step) => step.phase === "pre-merge").map((step) => ({ nodeId: step.templateId, name: step.name }));
|
|
29203
|
-
const bypassedGroupIds = new Set(bypassedPreMergeGroups.map((group) => group.nodeId));
|
|
29204
|
-
const bypassedNodeIds = /* @__PURE__ */ new Set();
|
|
29205
|
-
for (const node of ir2.nodes) {
|
|
29206
|
-
if (isMergeRegionNode(node) || node.id === "completion-summary" || node.config?.summaryTarget === "task") continue;
|
|
29207
|
-
if (configString(node, "seam") === "planning") {
|
|
29208
|
-
bypassedNodeIds.add(node.id);
|
|
29209
|
-
continue;
|
|
29210
|
-
}
|
|
29211
|
-
if (bypassedGroupIds.has(node.id)) {
|
|
29212
|
-
bypassedNodeIds.add(node.id);
|
|
29213
|
-
continue;
|
|
29214
|
-
}
|
|
29215
|
-
const workflowAction = configString(node, "workflowAction");
|
|
29216
|
-
const groupId = configString(node, "forWorkflowStepId");
|
|
29217
|
-
if (workflowAction === "plan-replan" || workflowAction === "plan-review-no-op" || workflowAction === "pre-merge-remediation" || workflowAction === "review-remediation-steps" || groupId !== void 0 && bypassedGroupIds.has(groupId)) {
|
|
29218
|
-
bypassedNodeIds.add(node.id);
|
|
29219
|
-
}
|
|
29220
|
-
}
|
|
29221
|
-
const parseStepsNodeIds = new Set(ir2.nodes.filter((node) => node.kind === "parse-steps").map((node) => node.id));
|
|
29222
|
-
for (const parseNodeId of parseStepsNodeIds) {
|
|
29223
|
-
if (bypassedNodeIds.has(parseNodeId)) {
|
|
29224
|
-
throw new Error(`Fast lane cannot bypass parse-steps node '${parseNodeId}'`);
|
|
29225
|
-
}
|
|
29226
|
-
}
|
|
29227
|
-
return {
|
|
29228
|
-
active: true,
|
|
29229
|
-
bypassedNodeIds,
|
|
29230
|
-
bypassedPreMergeGroups,
|
|
29231
|
-
parseStepsNodeIds,
|
|
29232
|
-
implementationNodeId: implementationNode.id,
|
|
29233
|
-
implementationKind
|
|
29234
|
-
};
|
|
29235
|
-
}
|
|
29236
|
-
var FAST_LANE_STEP_NAME, FAST_LANE_SKIP_VALUE, FAST_LANE_STEP_REVIEW_ROUTE_VALUE;
|
|
29237
|
-
var init_workflow_fast_lane = __esm({
|
|
29238
|
-
"../core/src/workflows/workflow-fast-lane.ts"() {
|
|
29239
|
-
"use strict";
|
|
29240
|
-
init_workflow_merge_region();
|
|
29241
|
-
init_workflow_optional_steps();
|
|
29242
|
-
FAST_LANE_STEP_NAME = "Fast implementation";
|
|
29243
|
-
FAST_LANE_SKIP_VALUE = "fast-lane-skip";
|
|
29244
|
-
FAST_LANE_STEP_REVIEW_ROUTE_VALUE = "approve";
|
|
29245
|
-
}
|
|
29246
|
-
});
|
|
29247
|
-
|
|
29248
29292
|
// ../core/src/mesh/mesh-task-replication.ts
|
|
29249
29293
|
function buildBootstrapPrompt(taskId, title, description) {
|
|
29250
29294
|
const heading = title ? `${taskId}: ${title}` : taskId;
|
|
@@ -66445,10 +66489,10 @@ var init_migration = __esm({
|
|
|
66445
66489
|
return basename6(projectPath);
|
|
66446
66490
|
}
|
|
66447
66491
|
try {
|
|
66448
|
-
const { execFile:
|
|
66449
|
-
const { promisify:
|
|
66450
|
-
const
|
|
66451
|
-
const { stdout } = await
|
|
66492
|
+
const { execFile: execFile47 } = await import("node:child_process");
|
|
66493
|
+
const { promisify: promisify102 } = await import("node:util");
|
|
66494
|
+
const execFileAsync41 = promisify102(execFile47);
|
|
66495
|
+
const { stdout } = await execFileAsync41(
|
|
66452
66496
|
"git",
|
|
66453
66497
|
["remote", "get-url", "origin"],
|
|
66454
66498
|
{ cwd: projectPath, timeout: 1e3 }
|
|
@@ -68643,10 +68687,10 @@ var init_central_core = __esm({
|
|
|
68643
68687
|
*/
|
|
68644
68688
|
async generateProjectName(projectPath) {
|
|
68645
68689
|
try {
|
|
68646
|
-
const { execFile:
|
|
68647
|
-
const { promisify:
|
|
68648
|
-
const
|
|
68649
|
-
const { stdout } = await
|
|
68690
|
+
const { execFile: execFile47 } = await import("node:child_process");
|
|
68691
|
+
const { promisify: promisify102 } = await import("node:util");
|
|
68692
|
+
const execFileAsync41 = promisify102(execFile47);
|
|
68693
|
+
const { stdout } = await execFileAsync41(
|
|
68650
68694
|
"git",
|
|
68651
68695
|
["remote", "get-url", "origin"],
|
|
68652
68696
|
{ cwd: projectPath, timeout: 5e3 }
|
|
@@ -85448,14 +85492,12 @@ async function listWorkflowDefinitionsImpl(store, options) {
|
|
|
85448
85492
|
return pluginFiltered;
|
|
85449
85493
|
}
|
|
85450
85494
|
async function readAllWorkflowDefinitionsImpl(store) {
|
|
85451
|
-
if (store.workflowDefinitionsCache) return store.workflowDefinitionsCache;
|
|
85452
85495
|
const layer = store.getAsyncLayer();
|
|
85453
85496
|
if (!layer) {
|
|
85454
85497
|
throw new Error("workflow definitions: AsyncDataLayer not initialized in backend mode");
|
|
85455
85498
|
}
|
|
85456
85499
|
const rows = await listWorkflowRows(layer);
|
|
85457
|
-
|
|
85458
|
-
return store.workflowDefinitionsCache;
|
|
85500
|
+
return [...BUILTIN_WORKFLOWS, ...rows.map((row) => store.toWorkflowDefinition(row))];
|
|
85459
85501
|
}
|
|
85460
85502
|
async function getWorkflowDefinitionImpl(store, id) {
|
|
85461
85503
|
const builtin = getBuiltinWorkflow(id);
|
|
@@ -85524,7 +85566,6 @@ function insertWorkflowDefinitionSyncImpl(store, input) {
|
|
|
85524
85566
|
if (!isWorkflowDefinitionIdPrimaryKeyCollision(error3)) throw error3;
|
|
85525
85567
|
continue;
|
|
85526
85568
|
}
|
|
85527
|
-
store.workflowDefinitionsCache = null;
|
|
85528
85569
|
return definition;
|
|
85529
85570
|
}
|
|
85530
85571
|
throw new Error("Unable to allocate a free workflow definition id after repeated id collisions");
|
|
@@ -85914,11 +85955,6 @@ function getPluginStoreImpl(store) {
|
|
|
85914
85955
|
...pluginLayer ? { asyncLayer: pluginLayer } : {}
|
|
85915
85956
|
}
|
|
85916
85957
|
);
|
|
85917
|
-
const clearWorkflowDefinitionCache = () => {
|
|
85918
|
-
store.workflowDefinitionsCache = null;
|
|
85919
|
-
};
|
|
85920
|
-
store.pluginStore.on("plugin:registered", clearWorkflowDefinitionCache);
|
|
85921
|
-
store.pluginStore.on("plugin:unregistered", clearWorkflowDefinitionCache);
|
|
85922
85958
|
}
|
|
85923
85959
|
return store.pluginStore;
|
|
85924
85960
|
}
|
|
@@ -90290,11 +90326,11 @@ async function searchWithQmd(rootDir, options) {
|
|
|
90290
90326
|
const command = "qmd";
|
|
90291
90327
|
const limit = Math.max(1, Math.min(options.limit ?? 5, 20));
|
|
90292
90328
|
try {
|
|
90293
|
-
const
|
|
90294
|
-
await ensureQmdProjectMemoryCollection(rootDir,
|
|
90329
|
+
const execFileAsync41 = await getDefaultExecFileAsync();
|
|
90330
|
+
await ensureQmdProjectMemoryCollection(rootDir, execFileAsync41);
|
|
90295
90331
|
scheduleQmdProjectMemoryRefresh(rootDir);
|
|
90296
90332
|
const args = buildQmdSearchArgs(rootDir, options);
|
|
90297
|
-
const { stdout } = await
|
|
90333
|
+
const { stdout } = await execFileAsync41(command, args, {
|
|
90298
90334
|
cwd: rootDir,
|
|
90299
90335
|
timeout: 4e3,
|
|
90300
90336
|
maxBuffer: 1024 * 1024
|
|
@@ -90319,12 +90355,12 @@ async function searchWithQmd(rootDir, options) {
|
|
|
90319
90355
|
return [];
|
|
90320
90356
|
}
|
|
90321
90357
|
}
|
|
90322
|
-
async function ensureQmdProjectMemoryCollection(rootDir,
|
|
90358
|
+
async function ensureQmdProjectMemoryCollection(rootDir, execFileAsync41) {
|
|
90323
90359
|
const collectionName = qmdMemoryCollectionName(rootDir);
|
|
90324
90360
|
const memoryDir = memoryWorkspacePath(rootDir);
|
|
90325
90361
|
await mkdir10(memoryDir, { recursive: true });
|
|
90326
90362
|
try {
|
|
90327
|
-
await
|
|
90363
|
+
await execFileAsync41("qmd", buildQmdCollectionAddArgs(rootDir), {
|
|
90328
90364
|
cwd: rootDir,
|
|
90329
90365
|
timeout: 4e3,
|
|
90330
90366
|
maxBuffer: 512 * 1024
|
|
@@ -90422,14 +90458,14 @@ async function refreshQmdProjectMemoryIndex(rootDir, options) {
|
|
|
90422
90458
|
}
|
|
90423
90459
|
}
|
|
90424
90460
|
const promise = (async () => {
|
|
90425
|
-
const
|
|
90426
|
-
await ensureQmdProjectMemoryCollection(rootDir,
|
|
90427
|
-
await
|
|
90461
|
+
const execFileAsync41 = options?.execFileAsync ?? await getDefaultExecFileAsync();
|
|
90462
|
+
await ensureQmdProjectMemoryCollection(rootDir, execFileAsync41);
|
|
90463
|
+
await execFileAsync41("qmd", ["update"], {
|
|
90428
90464
|
cwd: rootDir,
|
|
90429
90465
|
timeout: 3e4,
|
|
90430
90466
|
maxBuffer: 1024 * 1024
|
|
90431
90467
|
});
|
|
90432
|
-
await
|
|
90468
|
+
await execFileAsync41("qmd", ["embed"], {
|
|
90433
90469
|
cwd: rootDir,
|
|
90434
90470
|
timeout: 12e4,
|
|
90435
90471
|
maxBuffer: 1024 * 1024
|
|
@@ -90465,12 +90501,12 @@ async function refreshQmdAgentMemoryIndex(rootDir, agentId, options) {
|
|
|
90465
90501
|
}
|
|
90466
90502
|
}
|
|
90467
90503
|
const promise = (async () => {
|
|
90468
|
-
const
|
|
90504
|
+
const execFileAsync41 = options?.execFileAsync ?? await getDefaultExecFileAsync();
|
|
90469
90505
|
const { agentMemoryWorkspacePath: agentMemoryWorkspacePath2 } = await Promise.resolve().then(() => (init_memory_dreams(), memory_dreams_exports));
|
|
90470
90506
|
const workspacePath = agentMemoryWorkspacePath2(rootDir, agentId);
|
|
90471
90507
|
await mkdir10(workspacePath, { recursive: true });
|
|
90472
90508
|
try {
|
|
90473
|
-
await
|
|
90509
|
+
await execFileAsync41("qmd", ["collection", "add", workspacePath, "--name", qmdAgentMemoryCollectionName(rootDir, agentId), "--mask", "**/*.md"], {
|
|
90474
90510
|
cwd: rootDir,
|
|
90475
90511
|
timeout: 4e3,
|
|
90476
90512
|
maxBuffer: 512 * 1024
|
|
@@ -90483,8 +90519,8 @@ ${stderr}`)) {
|
|
|
90483
90519
|
throw err;
|
|
90484
90520
|
}
|
|
90485
90521
|
}
|
|
90486
|
-
await
|
|
90487
|
-
await
|
|
90522
|
+
await execFileAsync41("qmd", ["update"], { cwd: rootDir, timeout: 3e4, maxBuffer: 1024 * 1024 });
|
|
90523
|
+
await execFileAsync41("qmd", ["embed"], { cwd: rootDir, timeout: 12e4, maxBuffer: 1024 * 1024 });
|
|
90488
90524
|
})();
|
|
90489
90525
|
qmdAgentRefreshState.set(key, { lastStartedAt: now, inFlight: promise });
|
|
90490
90526
|
try {
|
|
@@ -90505,8 +90541,8 @@ function scheduleQmdAgentMemoryRefresh(rootDir, agentId) {
|
|
|
90505
90541
|
}
|
|
90506
90542
|
async function isQmdAvailable() {
|
|
90507
90543
|
try {
|
|
90508
|
-
const
|
|
90509
|
-
await
|
|
90544
|
+
const execFileAsync41 = await getDefaultExecFileAsync();
|
|
90545
|
+
await execFileAsync41("qmd", ["--help"], {
|
|
90510
90546
|
timeout: 3e3,
|
|
90511
90547
|
maxBuffer: 128 * 1024,
|
|
90512
90548
|
keepAlive: true
|
|
@@ -90517,12 +90553,12 @@ async function isQmdAvailable() {
|
|
|
90517
90553
|
}
|
|
90518
90554
|
}
|
|
90519
90555
|
async function installQmd(options) {
|
|
90520
|
-
const
|
|
90556
|
+
const execFileAsync41 = options?.execFileAsync ?? await getDefaultExecFileAsync();
|
|
90521
90557
|
const [command, ...args] = QMD_INSTALL_COMMAND.split(" ");
|
|
90522
90558
|
if (!command || args.length === 0) {
|
|
90523
90559
|
throw new MemoryBackendError("BACKEND_UNAVAILABLE", "qmd install command is not configured", "qmd");
|
|
90524
90560
|
}
|
|
90525
|
-
await
|
|
90561
|
+
await execFileAsync41(command, args, {
|
|
90526
90562
|
timeout: 12e4,
|
|
90527
90563
|
maxBuffer: 1024 * 1024
|
|
90528
90564
|
});
|
|
@@ -100037,7 +100073,6 @@ async function createWorkflowDefinitionImpl(store, input) {
|
|
|
100037
100073
|
if (!isWorkflowDefinitionIdPrimaryKeyCollision(error3)) throw error3;
|
|
100038
100074
|
continue;
|
|
100039
100075
|
}
|
|
100040
|
-
store.workflowDefinitionsCache = null;
|
|
100041
100076
|
return definition;
|
|
100042
100077
|
}
|
|
100043
100078
|
throw new Error("Unable to allocate a free workflow definition id after repeated id collisions");
|
|
@@ -103621,7 +103656,6 @@ async function updateWorkflowDefinitionImpl(store, id, updates) {
|
|
|
103621
103656
|
eq(project_exports.workflows.id, id),
|
|
103622
103657
|
projectScopeFor(project_exports.workflows.projectId, layer.projectId)
|
|
103623
103658
|
));
|
|
103624
|
-
store.workflowDefinitionsCache = null;
|
|
103625
103659
|
return next;
|
|
103626
103660
|
});
|
|
103627
103661
|
if (pendingRehome) {
|
|
@@ -103656,7 +103690,6 @@ async function deleteWorkflowDefinitionImpl(store, id) {
|
|
|
103656
103690
|
projectScopeFor(project_exports.workflows.projectId, layer.projectId)
|
|
103657
103691
|
)).returning();
|
|
103658
103692
|
if (deleted.length === 0) throw new Error(`Workflow '${id}' not found`);
|
|
103659
|
-
store.workflowDefinitionsCache = null;
|
|
103660
103693
|
await layer.db.delete(project_exports.workflowSettings).where(and(
|
|
103661
103694
|
eq(project_exports.workflowSettings.workflowId, id),
|
|
103662
103695
|
projectScopeFor(project_exports.workflowSettings.projectId, layer.projectId)
|
|
@@ -108250,7 +108283,6 @@ var init_store = __esm({
|
|
|
108250
108283
|
taskIdIntegrityReport = { status: "ok", checkedAt: (/* @__PURE__ */ new Date()).toISOString(), anomalies: [] };
|
|
108251
108284
|
lastTaskIdIntegrityLogSignature = null;
|
|
108252
108285
|
workflowStepsCache = null;
|
|
108253
|
-
workflowDefinitionsCache = null;
|
|
108254
108286
|
_pluginWorkflowStepTemplates = [];
|
|
108255
108287
|
globalSettingsStore;
|
|
108256
108288
|
donePauseBackfillDone = false;
|
|
@@ -115880,7 +115912,7 @@ function getPostMergeFinalizeBlocker(task) {
|
|
|
115880
115912
|
}
|
|
115881
115913
|
function planConfirmedMergeChecklistReconciliation(task) {
|
|
115882
115914
|
return {
|
|
115883
|
-
skippedStepIndexes: task.steps.map((step, index2) => step.status === "pending" || step.status === "in-progress" ? index2 : -1).filter((index2) => index2 >= 0),
|
|
115915
|
+
skippedStepIndexes: (task.steps ?? []).map((step, index2) => step.status === "pending" || step.status === "in-progress" ? index2 : -1).filter((index2) => index2 >= 0),
|
|
115884
115916
|
reconciledWorkflowStepIds: (task.workflowStepResults ?? []).filter((result2) => result2.status === "pending").map((result2) => result2.workflowStepId)
|
|
115885
115917
|
};
|
|
115886
115918
|
}
|
|
@@ -135930,11 +135962,11 @@ var require_extract_zip = __commonJS({
|
|
|
135930
135962
|
var { createWriteStream, promises: fs10 } = __require("fs");
|
|
135931
135963
|
var getStream = require_get_stream();
|
|
135932
135964
|
var path13 = __require("path");
|
|
135933
|
-
var { promisify:
|
|
135965
|
+
var { promisify: promisify102 } = __require("util");
|
|
135934
135966
|
var stream = __require("stream");
|
|
135935
135967
|
var yauzl = require_yauzl();
|
|
135936
|
-
var openZip =
|
|
135937
|
-
var pipeline =
|
|
135968
|
+
var openZip = promisify102(yauzl.open);
|
|
135969
|
+
var pipeline = promisify102(stream.pipeline);
|
|
135938
135970
|
var Extractor = class {
|
|
135939
135971
|
constructor(zipPath, opts) {
|
|
135940
135972
|
this.zipPath = zipPath;
|
|
@@ -136016,7 +136048,7 @@ var require_extract_zip = __commonJS({
|
|
|
136016
136048
|
await fs10.mkdir(destDir, mkdirOptions);
|
|
136017
136049
|
if (isDir) return;
|
|
136018
136050
|
debug("opening read stream", dest);
|
|
136019
|
-
const readStream = await
|
|
136051
|
+
const readStream = await promisify102(this.zipfile.openReadStream.bind(this.zipfile))(entry);
|
|
136020
136052
|
if (symlink) {
|
|
136021
136053
|
const link = await getStream(readStream);
|
|
136022
136054
|
debug("creating symlink", link, dest);
|
|
@@ -137455,6 +137487,7 @@ async function updateChatSession(handle2, id, input) {
|
|
|
137455
137487
|
if (input.status !== void 0) setValues.status = input.status;
|
|
137456
137488
|
if (input.modelProvider !== void 0) setValues.modelProvider = input.modelProvider;
|
|
137457
137489
|
if (input.modelId !== void 0) setValues.modelId = input.modelId;
|
|
137490
|
+
if (input.agentId !== void 0) setValues.agentId = input.agentId;
|
|
137458
137491
|
if (input.thinkingLevel !== void 0) setValues.thinkingLevel = input.thinkingLevel;
|
|
137459
137492
|
if (input.memoryFocus !== void 0) setValues.memoryFocus = input.memoryFocus;
|
|
137460
137493
|
if (input.pinnedAt !== void 0) setValues.pinnedAt = input.pinnedAt;
|
|
@@ -138508,6 +138541,7 @@ var init_cli_session_store = __esm({
|
|
|
138508
138541
|
});
|
|
138509
138542
|
|
|
138510
138543
|
// ../core/src/secrets/oauth-credential-interop.ts
|
|
138544
|
+
import { createHash as createHash22 } from "node:crypto";
|
|
138511
138545
|
import { existsSync as existsSync40, readFileSync as readFileSync11 } from "node:fs";
|
|
138512
138546
|
import { homedir as homedir7 } from "node:os";
|
|
138513
138547
|
import { join as join55 } from "node:path";
|
|
@@ -138567,6 +138601,22 @@ function getLastRefreshFallbackExpiryMs(lastRefresh) {
|
|
|
138567
138601
|
}
|
|
138568
138602
|
return parsed + CODEX_REFRESH_FALLBACK_WINDOW_MS;
|
|
138569
138603
|
}
|
|
138604
|
+
function isSameStoredCredentialMaterial(left, right) {
|
|
138605
|
+
if (!left || !right || left.type !== right.type) {
|
|
138606
|
+
return false;
|
|
138607
|
+
}
|
|
138608
|
+
return left.key === right.key && left.access === right.access && left.refresh === right.refresh;
|
|
138609
|
+
}
|
|
138610
|
+
function computeStoredCredentialAccountFingerprint(credential) {
|
|
138611
|
+
if (!credential) {
|
|
138612
|
+
return void 0;
|
|
138613
|
+
}
|
|
138614
|
+
const material = typeof credential.refresh === "string" && credential.refresh.length > 0 ? credential.refresh : typeof credential.access === "string" && credential.access.length > 0 ? credential.access : typeof credential.key === "string" && credential.key.length > 0 ? credential.key : void 0;
|
|
138615
|
+
if (!material) {
|
|
138616
|
+
return void 0;
|
|
138617
|
+
}
|
|
138618
|
+
return createHash22("sha256").update(`${credential.type ?? ""}\0${material}`).digest("hex").slice(0, 16);
|
|
138619
|
+
}
|
|
138570
138620
|
function isStoredAuthCredential(value) {
|
|
138571
138621
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
138572
138622
|
return false;
|
|
@@ -139537,7 +139587,7 @@ var init_task_timing = __esm({
|
|
|
139537
139587
|
});
|
|
139538
139588
|
|
|
139539
139589
|
// ../core/src/task-recommendation-notice.ts
|
|
139540
|
-
import { createHash as
|
|
139590
|
+
import { createHash as createHash23 } from "node:crypto";
|
|
139541
139591
|
function registerTaskRecommendationNoticeMailbox(store, mailbox) {
|
|
139542
139592
|
mailboxes2.set(store, mailbox);
|
|
139543
139593
|
return () => {
|
|
@@ -139562,7 +139612,7 @@ function buildTaskRecommendationNoticeContent(task, recommendations) {
|
|
|
139562
139612
|
}
|
|
139563
139613
|
function buildTaskRecommendationNoticeIdempotencyKey(taskId, recommendations) {
|
|
139564
139614
|
const ids = recommendations.map(({ id }) => id).sort().join("\n");
|
|
139565
|
-
const digest =
|
|
139615
|
+
const digest = createHash23("sha256").update(ids, "utf8").digest("hex").slice(0, 16);
|
|
139566
139616
|
return `task-recommendation-notice:${taskId}:${digest}`;
|
|
139567
139617
|
}
|
|
139568
139618
|
async function notifyOperatorOfTaskRecommendations(store, task, recommendations, settings) {
|
|
@@ -140008,6 +140058,7 @@ __export(src_exports, {
|
|
|
140008
140058
|
APPROVAL_REQUEST_STATUSES: () => APPROVAL_REQUEST_STATUSES,
|
|
140009
140059
|
ARCHIVED_TASK_DOCUMENT_ADDITION_BOUNDARY: () => ARCHIVED_TASK_DOCUMENT_ADDITION_BOUNDARY,
|
|
140010
140060
|
ARCHIVED_TASK_DOCUMENT_PUBLICATION_REJECTED: () => ARCHIVED_TASK_DOCUMENT_PUBLICATION_REJECTED,
|
|
140061
|
+
AUTOMATED_BYPASS_ACTORS: () => AUTOMATED_BYPASS_ACTORS,
|
|
140011
140062
|
AUTOMATION_PRESETS: () => AUTOMATION_PRESETS,
|
|
140012
140063
|
AUTOMATION_SELECTABLE_TOOLS: () => AUTOMATION_SELECTABLE_TOOLS,
|
|
140013
140064
|
AUTOPILOT_STATES: () => AUTOPILOT_STATES,
|
|
@@ -140203,6 +140254,7 @@ __export(src_exports, {
|
|
|
140203
140254
|
FAST_LANE_SKIP_VALUE: () => FAST_LANE_SKIP_VALUE,
|
|
140204
140255
|
FAST_LANE_STEP_NAME: () => FAST_LANE_STEP_NAME,
|
|
140205
140256
|
FAST_LANE_STEP_REVIEW_ROUTE_VALUE: () => FAST_LANE_STEP_REVIEW_ROUTE_VALUE,
|
|
140257
|
+
FAST_MODE_BYPASS_ACTOR: () => FAST_MODE_BYPASS_ACTOR,
|
|
140206
140258
|
FEATURE_LOOP_REPAIR_TRANSITIONS: () => FEATURE_LOOP_REPAIR_TRANSITIONS,
|
|
140207
140259
|
FEATURE_LOOP_STATES: () => FEATURE_LOOP_STATES,
|
|
140208
140260
|
FEATURE_STATUSES: () => FEATURE_STATUSES,
|
|
@@ -140767,6 +140819,7 @@ __export(src_exports, {
|
|
|
140767
140819
|
computeRetrySummary: () => computeRetrySummary,
|
|
140768
140820
|
computeSkillId: () => computeSkillId,
|
|
140769
140821
|
computeSnapshotChecksum: () => computeSnapshotChecksum,
|
|
140822
|
+
computeStoredCredentialAccountFingerprint: () => computeStoredCredentialAccountFingerprint,
|
|
140770
140823
|
computeWorkflowIrPin: () => computeWorkflowIrPin,
|
|
140771
140824
|
configurationTargetKey: () => configurationTargetKey,
|
|
140772
140825
|
configureApprovalRequestTtls: () => configureApprovalRequestTtls,
|
|
@@ -141089,6 +141142,7 @@ __export(src_exports, {
|
|
|
141089
141142
|
isApprovalRequestExpired: () => isApprovalRequestExpired,
|
|
141090
141143
|
isArchivedColumnRole: () => isArchivedColumnRole,
|
|
141091
141144
|
isArchivedRemediationCarrier: () => isArchivedRemediationCarrier,
|
|
141145
|
+
isAuditedOperatorBypass: () => isAuditedOperatorBypass,
|
|
141092
141146
|
isBlockingFinding: () => isBlockingFinding,
|
|
141093
141147
|
isBranchGroupComplete: () => isBranchGroupComplete,
|
|
141094
141148
|
isBranchGroupMemberLanded: () => isBranchGroupMemberLanded,
|
|
@@ -141176,6 +141230,7 @@ __export(src_exports, {
|
|
|
141176
141230
|
isReviewColumnRole: () => isReviewColumnRole,
|
|
141177
141231
|
isRunRecord: () => isRunRecord,
|
|
141178
141232
|
isRunningAgentTask: () => isRunningAgentTask,
|
|
141233
|
+
isSameStoredCredentialMaterial: () => isSameStoredCredentialMaterial,
|
|
141179
141234
|
isSanctionedEngineBackwardMove: () => isSanctionedEngineBackwardMove,
|
|
141180
141235
|
isSandboxExperimentalEnabled: () => isSandboxExperimentalEnabled,
|
|
141181
141236
|
isSecretAccessPolicy: () => isSecretAccessPolicy,
|
|
@@ -141454,6 +141509,7 @@ __export(src_exports, {
|
|
|
141454
141509
|
renderTriagePolicyPlaceholders: () => renderTriagePolicyPlaceholders,
|
|
141455
141510
|
renderValidationCause: () => renderValidationCause,
|
|
141456
141511
|
renderValidationFailureDescription: () => renderValidationFailureDescription,
|
|
141512
|
+
requiresContentReviewProof: () => requiresContentReviewProof,
|
|
141457
141513
|
requiresPlannerConfirmation: () => requiresPlannerConfirmation,
|
|
141458
141514
|
requiresWorktrunkInstallVerification: () => requiresWorktrunkInstallVerification,
|
|
141459
141515
|
resetGhAvailabilityCache: () => resetGhAvailabilityCache,
|
|
@@ -141617,6 +141673,7 @@ __export(src_exports, {
|
|
|
141617
141673
|
resolveTitleSummarizerSettingsModel: () => resolveTitleSummarizerSettingsModel,
|
|
141618
141674
|
resolveToolOutputBudget: () => resolveToolOutputBudget,
|
|
141619
141675
|
resolveTrailingVerificationStepIndex: () => resolveTrailingVerificationStepIndex,
|
|
141676
|
+
resolveUnprovenReviewApproval: () => resolveUnprovenReviewApproval,
|
|
141620
141677
|
resolveUpdateAutomationSettings: () => resolveUpdateAutomationSettings,
|
|
141621
141678
|
resolveUpdateTargetVersion: () => resolveUpdateTargetVersion,
|
|
141622
141679
|
resolveUpdatesExternallyManaged: () => resolveUpdatesExternallyManaged,
|
|
@@ -142251,7 +142308,7 @@ var init_logger3 = __esm({
|
|
|
142251
142308
|
});
|
|
142252
142309
|
|
|
142253
142310
|
// ../engine/src/agents/agent-logger.ts
|
|
142254
|
-
import { createHash as
|
|
142311
|
+
import { createHash as createHash24 } from "node:crypto";
|
|
142255
142312
|
function truncateToolResultDetail(value) {
|
|
142256
142313
|
if (value.length <= TOOL_RESULT_DETAIL_LIMIT) return value;
|
|
142257
142314
|
return `${value.slice(0, TOOL_RESULT_DETAIL_LIMIT)}${TOOL_RESULT_DETAIL_TRUNCATION_NOTICE}`;
|
|
@@ -142359,7 +142416,7 @@ function summarizeToolArgs(name2, args) {
|
|
|
142359
142416
|
return `${key}=${clipToolArgValue(compactToolArgValue(args[key]), maximum)}`;
|
|
142360
142417
|
}).join(", ");
|
|
142361
142418
|
if (rendered.length <= TOOL_ARG_SUMMARY_MAX) return rendered;
|
|
142362
|
-
const hash3 =
|
|
142419
|
+
const hash3 = createHash24("sha256").update(fullArgsJson).digest("hex").slice(0, STRUCTURED_ARG_HASH_HEX_LEN);
|
|
142363
142420
|
const suffix = `\u2026#${hash3}`;
|
|
142364
142421
|
const keep = Math.max(0, TOOL_ARG_SUMMARY_MAX - suffix.length);
|
|
142365
142422
|
return `${rendered.slice(0, keep)}${suffix}`;
|
|
@@ -144126,6 +144183,14 @@ function resolveAiMergeRootPath(rootDir, settings) {
|
|
|
144126
144183
|
function resolveLegacyAiMergeRootPath(rootDir) {
|
|
144127
144184
|
return join58(rootDir, ".fusion", "ai-merge");
|
|
144128
144185
|
}
|
|
144186
|
+
function resolveAiMergeSearchRoots(rootDir, settings) {
|
|
144187
|
+
const roots = [
|
|
144188
|
+
resolveAiMergeRootPath(rootDir, settings),
|
|
144189
|
+
resolveLegacyAiMergeRootPath(rootDir),
|
|
144190
|
+
...settings?.worktreesDir ? [] : [join58(resolveLegacyWorktreesDirLayout(rootDir), AI_MERGE_DIRNAME)]
|
|
144191
|
+
];
|
|
144192
|
+
return [...new Set(roots)];
|
|
144193
|
+
}
|
|
144129
144194
|
function resolveWorktreesDir(rootDir, settings, workspaceContext) {
|
|
144130
144195
|
return resolveWorktreesDirLayout(rootDir, settings, workspaceContext);
|
|
144131
144196
|
}
|
|
@@ -145884,18 +145949,25 @@ function parseWorktreesFromPorcelain(porcelain) {
|
|
|
145884
145949
|
if (current.path) rows.push({ path: current.path, branch: current.branch });
|
|
145885
145950
|
return rows;
|
|
145886
145951
|
}
|
|
145952
|
+
function isRegenerableIgnoredPorcelainEntry(entry) {
|
|
145953
|
+
const path13 = entry.slice(3).replace(/\/$/, "");
|
|
145954
|
+
if (!path13 || path13.startsWith('"')) return false;
|
|
145955
|
+
const lastSegment = path13.split("/").at(-1);
|
|
145956
|
+
return lastSegment !== void 0 && REGENERABLE_IGNORED_DIR_NAMES.has(lastSegment);
|
|
145957
|
+
}
|
|
145887
145958
|
function classifyWorktreeRemovalContent(porcelain) {
|
|
145888
145959
|
const entries = porcelain.split(/\r?\n/).filter((line2) => line2.trim().length > 0);
|
|
145889
145960
|
if (entries.length === 0) return "clean";
|
|
145890
|
-
|
|
145961
|
+
if (entries.some((line2) => !line2.startsWith("!! "))) return "deliverable";
|
|
145962
|
+
return entries.every(isRegenerableIgnoredPorcelainEntry) ? "regenerable-ignored" : "ignored-only";
|
|
145891
145963
|
}
|
|
145892
145964
|
async function assertCleanForDefensiveRemoval(worktreePath) {
|
|
145893
145965
|
if (!existsSync44(worktreePath)) {
|
|
145894
|
-
return "clean";
|
|
145966
|
+
return { classification: "clean", entryCount: 0 };
|
|
145895
145967
|
}
|
|
145896
145968
|
let stdout;
|
|
145897
145969
|
try {
|
|
145898
|
-
({ stdout } = await execFileAsync6("git", ["status", "--porcelain=v1", "--ignored", "--untracked-files=normal"], {
|
|
145970
|
+
({ stdout } = await execFileAsync6("git", ["status", "--porcelain=v1", "--ignored=matching", "--untracked-files=normal"], {
|
|
145899
145971
|
cwd: worktreePath,
|
|
145900
145972
|
encoding: "utf-8",
|
|
145901
145973
|
timeout: 15e3,
|
|
@@ -145908,7 +145980,10 @@ async function assertCleanForDefensiveRemoval(worktreePath) {
|
|
|
145908
145980
|
if (classification === "deliverable") {
|
|
145909
145981
|
throw new Error(`preserving ${worktreePath}: uncommitted or ignored content present`);
|
|
145910
145982
|
}
|
|
145911
|
-
return
|
|
145983
|
+
return {
|
|
145984
|
+
classification,
|
|
145985
|
+
entryCount: stdout.split(/\r?\n/).filter((line2) => line2.trim().length > 0).length
|
|
145986
|
+
};
|
|
145912
145987
|
}
|
|
145913
145988
|
async function removeWorktree(input) {
|
|
145914
145989
|
const logger3 = {
|
|
@@ -145925,9 +146000,12 @@ async function removeWorktree(input) {
|
|
|
145925
146000
|
}
|
|
145926
146001
|
const requiresCleanWorktree = DEFENSIVE_REMOVAL_REASONS.has(input.reason);
|
|
145927
146002
|
let contentClassification;
|
|
146003
|
+
let contentEntryCount = 0;
|
|
145928
146004
|
if (requiresCleanWorktree) {
|
|
145929
146005
|
try {
|
|
145930
|
-
|
|
146006
|
+
const contentProbe = await assertCleanForDefensiveRemoval(input.worktreePath);
|
|
146007
|
+
contentClassification = contentProbe.classification;
|
|
146008
|
+
contentEntryCount = contentProbe.entryCount;
|
|
145931
146009
|
} catch (error3) {
|
|
145932
146010
|
const classification = error3 instanceof Error && error3.message.includes(": status probe failed (") ? "unverifiable" : "deliverable";
|
|
145933
146011
|
await input.audit?.git({
|
|
@@ -145944,6 +146022,17 @@ async function removeWorktree(input) {
|
|
|
145944
146022
|
throw error3;
|
|
145945
146023
|
}
|
|
145946
146024
|
if (contentClassification === "ignored-only" && !input.postLandingProof) {
|
|
146025
|
+
await input.audit?.git({
|
|
146026
|
+
type: "worktree:removal-preserved",
|
|
146027
|
+
target: input.worktreePath,
|
|
146028
|
+
metadata: {
|
|
146029
|
+
taskId: input.taskId,
|
|
146030
|
+
reason: input.reason,
|
|
146031
|
+
source: void 0,
|
|
146032
|
+
classification: "ignored-only",
|
|
146033
|
+
hasPostLandingProof: false
|
|
146034
|
+
}
|
|
146035
|
+
}).catch(() => void 0);
|
|
145947
146036
|
throw new Error(`preserving ${input.worktreePath}: uncommitted or ignored content present`);
|
|
145948
146037
|
}
|
|
145949
146038
|
}
|
|
@@ -145963,6 +146052,17 @@ async function removeWorktree(input) {
|
|
|
145963
146052
|
} catch {
|
|
145964
146053
|
}
|
|
145965
146054
|
};
|
|
146055
|
+
const recordRegenerableDiscard = async () => {
|
|
146056
|
+
if (contentClassification !== "regenerable-ignored") return;
|
|
146057
|
+
try {
|
|
146058
|
+
await input.audit?.git({
|
|
146059
|
+
type: "worktree:removal-discarded-regenerable-content",
|
|
146060
|
+
target: input.worktreePath,
|
|
146061
|
+
metadata: { taskId: input.taskId, reason: input.reason, entryCount: contentEntryCount }
|
|
146062
|
+
});
|
|
146063
|
+
} catch {
|
|
146064
|
+
}
|
|
146065
|
+
};
|
|
145966
146066
|
if (input.expectedOwnerTaskId && input.liveOwnerProbe) {
|
|
145967
146067
|
const reconciled = reconcileSelfOwnedActiveSessionForRemoval(
|
|
145968
146068
|
activeSessionRegistry,
|
|
@@ -146016,6 +146116,7 @@ async function removeWorktree(input) {
|
|
|
146016
146116
|
try {
|
|
146017
146117
|
await backend.remove(removeInput);
|
|
146018
146118
|
await recordIgnoredOnlyDiscard();
|
|
146119
|
+
await recordRegenerableDiscard();
|
|
146019
146120
|
if (input.audit) {
|
|
146020
146121
|
await input.audit.git({
|
|
146021
146122
|
type: backend.kind === "worktrunk" ? "worktree:worktrunk-remove" : "worktree:remove",
|
|
@@ -146043,6 +146144,7 @@ async function removeWorktree(input) {
|
|
|
146043
146144
|
try {
|
|
146044
146145
|
await native.remove(removeInput);
|
|
146045
146146
|
await recordIgnoredOnlyDiscard();
|
|
146147
|
+
await recordRegenerableDiscard();
|
|
146046
146148
|
await input.audit?.git({ type: "worktree:remove", target: input.worktreePath });
|
|
146047
146149
|
return { removed: true, classification: "removed" };
|
|
146048
146150
|
} catch (nativeError) {
|
|
@@ -146064,7 +146166,7 @@ function resolveWorktreeBackend(settings, deps = {}) {
|
|
|
146064
146166
|
}
|
|
146065
146167
|
return new NativeWorktreeBackend({ logger: deps.logger, settings, audit: deps.audit });
|
|
146066
146168
|
}
|
|
146067
|
-
var execAsync9, execFileAsync6, NATIVE_TIMEOUT_MS, REMOVE_TIMEOUT_MS, MAX_BUFFER3, HARMLESS_MERGE_REMOVE_ERROR_PATTERNS, WORKTRUNK_TIMEOUTS_MS, WORKTREE_BACKEND_MARKER, WorktrunkOperationError, NativeWorktreeBackend, WorktrunkWorktreeBackend, RemovalReason, ALLOWED_FORCE_REASONS, DEFENSIVE_REMOVAL_REASONS, POST_LANDING_PROOF_REASONS, InvalidForceUsageError, InvalidPostLandingProofUsageError, ActiveSessionWorktreeRemovalError;
|
|
146169
|
+
var execAsync9, execFileAsync6, NATIVE_TIMEOUT_MS, REMOVE_TIMEOUT_MS, MAX_BUFFER3, HARMLESS_MERGE_REMOVE_ERROR_PATTERNS, WORKTRUNK_TIMEOUTS_MS, WORKTREE_BACKEND_MARKER, WorktrunkOperationError, NativeWorktreeBackend, WorktrunkWorktreeBackend, RemovalReason, ALLOWED_FORCE_REASONS, DEFENSIVE_REMOVAL_REASONS, POST_LANDING_PROOF_REASONS, InvalidForceUsageError, InvalidPostLandingProofUsageError, ActiveSessionWorktreeRemovalError, REGENERABLE_IGNORED_DIR_NAMES;
|
|
146068
146170
|
var init_worktree_backend = __esm({
|
|
146069
146171
|
"../engine/src/worktree/worktree-backend.ts"() {
|
|
146070
146172
|
"use strict";
|
|
@@ -146804,6 +146906,27 @@ ${getErrorStderr(error3) ?? ""}`;
|
|
|
146804
146906
|
this.name = "ActiveSessionWorktreeRemovalError";
|
|
146805
146907
|
}
|
|
146806
146908
|
};
|
|
146909
|
+
REGENERABLE_IGNORED_DIR_NAMES = /* @__PURE__ */ new Set([
|
|
146910
|
+
"node_modules",
|
|
146911
|
+
"dist",
|
|
146912
|
+
"build",
|
|
146913
|
+
"out",
|
|
146914
|
+
"target",
|
|
146915
|
+
"bin",
|
|
146916
|
+
"obj",
|
|
146917
|
+
"coverage",
|
|
146918
|
+
".next",
|
|
146919
|
+
".nuxt",
|
|
146920
|
+
".turbo",
|
|
146921
|
+
".svelte-kit",
|
|
146922
|
+
".parcel-cache",
|
|
146923
|
+
".pytest_cache",
|
|
146924
|
+
".mypy_cache",
|
|
146925
|
+
"__pycache__",
|
|
146926
|
+
".gradle",
|
|
146927
|
+
".venv",
|
|
146928
|
+
"venv"
|
|
146929
|
+
]);
|
|
146807
146930
|
}
|
|
146808
146931
|
});
|
|
146809
146932
|
|
|
@@ -147423,7 +147546,7 @@ var init_gating_classifications = __esm({
|
|
|
147423
147546
|
});
|
|
147424
147547
|
|
|
147425
147548
|
// ../engine/src/agents/agent-action-gate.ts
|
|
147426
|
-
import { createHash as
|
|
147549
|
+
import { createHash as createHash25 } from "node:crypto";
|
|
147427
147550
|
function getExemptTools() {
|
|
147428
147551
|
if (!_exemptTools) {
|
|
147429
147552
|
_exemptTools = new Set(DEFAULT_EXEMPT_TOOLS);
|
|
@@ -147475,7 +147598,7 @@ function evaluateAgentActionGate(params) {
|
|
|
147475
147598
|
if (params.toolName === "bash") {
|
|
147476
147599
|
const command = extractShellCommand(args);
|
|
147477
147600
|
const git11 = classifyGitCommand(command);
|
|
147478
|
-
resourceId = command ? `cmd:${
|
|
147601
|
+
resourceId = command ? `cmd:${createHash25("sha256").update(command).digest("hex").slice(0, 16)}` : void 0;
|
|
147479
147602
|
if (git11?.write) {
|
|
147480
147603
|
category = "git_write";
|
|
147481
147604
|
operation = git11.operation;
|
|
@@ -149241,6 +149364,15 @@ async function withOAuthRefreshLock(authPath, providerId, refresh) {
|
|
|
149241
149364
|
await release3();
|
|
149242
149365
|
}
|
|
149243
149366
|
}
|
|
149367
|
+
async function withOAuthInstanceLoginLock(authPath, providerId, operation) {
|
|
149368
|
+
const safeProviderId = providerId.replace(/[^a-zA-Z0-9._-]/g, "_");
|
|
149369
|
+
const release3 = await import_proper_lockfile.default.lock(`${authPath}.${safeProviderId}.instance-login`, AUTH_LOCK_OPTIONS);
|
|
149370
|
+
try {
|
|
149371
|
+
return await operation();
|
|
149372
|
+
} finally {
|
|
149373
|
+
await release3();
|
|
149374
|
+
}
|
|
149375
|
+
}
|
|
149244
149376
|
function readDefaultInstanceMap(data) {
|
|
149245
149377
|
const candidate = data.__fusionDefaultInstances;
|
|
149246
149378
|
if (!candidate || typeof candidate !== "object" || Array.isArray(candidate)) return {};
|
|
@@ -149530,7 +149662,7 @@ function createFusionAuthStorage() {
|
|
|
149530
149662
|
primary.reload();
|
|
149531
149663
|
const selectPersistedRefreshCredential = () => {
|
|
149532
149664
|
const storedCredential = primary.get(storageProvider);
|
|
149533
|
-
if (refreshLockProvider !== ANTHROPIC_PROVIDER_ID2) {
|
|
149665
|
+
if (storedCredential?.type === "oauth" || refreshLockProvider !== ANTHROPIC_PROVIDER_ID2) {
|
|
149534
149666
|
return storedCredential;
|
|
149535
149667
|
}
|
|
149536
149668
|
const legacyCredential = primary.get(ANTHROPIC_PROVIDER_ID2);
|
|
@@ -149660,18 +149792,16 @@ function createFusionAuthStorage() {
|
|
|
149660
149792
|
if (rawKey) return rawKey;
|
|
149661
149793
|
}
|
|
149662
149794
|
const subscriptionLoggedOut = loggedOutProviders.has(ANTHROPIC_SUBSCRIPTION_PROVIDER_ID);
|
|
149663
|
-
const
|
|
149795
|
+
const subscriptionCredential = subscriptionLoggedOut ? void 0 : selectStoredCredential(ANTHROPIC_SUBSCRIPTION_PROVIDER_ID);
|
|
149796
|
+
if (subscriptionCredential?.type === "oauth") {
|
|
149797
|
+
const subscriptionKey = await resolveRefreshableCredentialApiKey(ANTHROPIC_SUBSCRIPTION_PROVIDER_ID, subscriptionCredential);
|
|
149798
|
+
if (subscriptionKey) return subscriptionKey;
|
|
149799
|
+
}
|
|
149800
|
+
const legacyAnthropicOAuthCredential = rawProviderLoggedOut || subscriptionCredential ? void 0 : selectStoredCredentialByType(ANTHROPIC_PROVIDER_ID2, "oauth");
|
|
149664
149801
|
if (!subscriptionLoggedOut && legacyAnthropicOAuthCredential) {
|
|
149665
149802
|
const legacyKey = await resolveRefreshableCredentialApiKey(ANTHROPIC_PROVIDER_ID2, legacyAnthropicOAuthCredential);
|
|
149666
149803
|
if (legacyKey) return legacyKey;
|
|
149667
149804
|
}
|
|
149668
|
-
if (!subscriptionLoggedOut) {
|
|
149669
|
-
const subscriptionCredential = selectStoredCredential(ANTHROPIC_SUBSCRIPTION_PROVIDER_ID);
|
|
149670
|
-
if (subscriptionCredential?.type === "oauth") {
|
|
149671
|
-
const subscriptionKey = await resolveRefreshableCredentialApiKey(ANTHROPIC_SUBSCRIPTION_PROVIDER_ID, subscriptionCredential);
|
|
149672
|
-
if (subscriptionKey) return subscriptionKey;
|
|
149673
|
-
}
|
|
149674
|
-
}
|
|
149675
149805
|
if (preferSubscription) {
|
|
149676
149806
|
const rawKey = resolveRawApiKey();
|
|
149677
149807
|
if (rawKey) return rawKey;
|
|
@@ -149848,8 +149978,15 @@ function createFusionAuthStorage() {
|
|
|
149848
149978
|
return void 0;
|
|
149849
149979
|
}
|
|
149850
149980
|
if (sourceProvider !== ANTHROPIC_SUBSCRIPTION_PROVIDER_ID) {
|
|
149851
|
-
await
|
|
149852
|
-
|
|
149981
|
+
const legacyKey = await resolveRefreshableCredentialApiKey(ANTHROPIC_PROVIDER_ID2, subscriptionCredential);
|
|
149982
|
+
primary.reload();
|
|
149983
|
+
const storedSubscription = primary.get(ANTHROPIC_SUBSCRIPTION_PROVIDER_ID);
|
|
149984
|
+
const refreshedLegacyCredential = primary.get(ANTHROPIC_PROVIDER_ID2);
|
|
149985
|
+
if (!storedSubscription && refreshedLegacyCredential?.type === "oauth") {
|
|
149986
|
+
await primary.set(ANTHROPIC_SUBSCRIPTION_PROVIDER_ID, refreshedLegacyCredential);
|
|
149987
|
+
loggedOutProviders.delete(ANTHROPIC_SUBSCRIPTION_PROVIDER_ID);
|
|
149988
|
+
}
|
|
149989
|
+
return legacyKey;
|
|
149853
149990
|
}
|
|
149854
149991
|
return resolveRefreshableCredentialApiKey(ANTHROPIC_SUBSCRIPTION_PROVIDER_ID, subscriptionCredential);
|
|
149855
149992
|
}
|
|
@@ -149894,6 +150031,9 @@ var init_auth_storage = __esm({
|
|
|
149894
150031
|
}
|
|
149895
150032
|
data = {};
|
|
149896
150033
|
modelRuntime;
|
|
150034
|
+
async withProviderInstanceLoginLock(providerId, operation) {
|
|
150035
|
+
return withOAuthInstanceLoginLock(this.authPath, providerId, operation);
|
|
150036
|
+
}
|
|
149897
150037
|
ensureFile() {
|
|
149898
150038
|
const parent = dirname26(this.authPath);
|
|
149899
150039
|
if (!existsSync45(parent)) mkdirSync7(parent, { recursive: true, mode: 448 });
|
|
@@ -150236,6 +150376,35 @@ var init_model_registry_refresh = __esm({
|
|
|
150236
150376
|
});
|
|
150237
150377
|
|
|
150238
150378
|
// ../engine/src/auth/provider-auth.ts
|
|
150379
|
+
async function withProviderInstanceLoginLock(authStorage, providerId, operation) {
|
|
150380
|
+
let locks = instanceLoginLocks.get(authStorage);
|
|
150381
|
+
if (!locks) {
|
|
150382
|
+
locks = /* @__PURE__ */ new Map();
|
|
150383
|
+
instanceLoginLocks.set(authStorage, locks);
|
|
150384
|
+
}
|
|
150385
|
+
const previous = locks.get(providerId);
|
|
150386
|
+
let release3;
|
|
150387
|
+
const gate = new Promise((resolve65) => {
|
|
150388
|
+
release3 = resolve65;
|
|
150389
|
+
});
|
|
150390
|
+
const queued = (previous ?? Promise.resolve()).catch(() => void 0).then(() => gate);
|
|
150391
|
+
locks.set(providerId, queued);
|
|
150392
|
+
await (previous ?? Promise.resolve()).catch(() => void 0);
|
|
150393
|
+
try {
|
|
150394
|
+
if (!authStorage.withProviderInstanceLoginLock) {
|
|
150395
|
+
return await operation();
|
|
150396
|
+
}
|
|
150397
|
+
return await authStorage.withProviderInstanceLoginLock(providerId, async () => {
|
|
150398
|
+
authStorage.reload();
|
|
150399
|
+
return await operation();
|
|
150400
|
+
});
|
|
150401
|
+
} finally {
|
|
150402
|
+
release3();
|
|
150403
|
+
if (locks.get(providerId) === queued) {
|
|
150404
|
+
locks.delete(providerId);
|
|
150405
|
+
}
|
|
150406
|
+
}
|
|
150407
|
+
}
|
|
150239
150408
|
function toApiKeyStorageProviderId(providerId) {
|
|
150240
150409
|
return providerId === ANTHROPIC_API_KEY_PROVIDER_ID2 ? ANTHROPIC_STORAGE_PROVIDER_ID : providerId;
|
|
150241
150410
|
}
|
|
@@ -150273,7 +150442,18 @@ function wrapAuthStorageWithApiKeyProviders(authStorage, modelRegistry, readFall
|
|
|
150273
150442
|
providerId,
|
|
150274
150443
|
callbacks
|
|
150275
150444
|
);
|
|
150276
|
-
|
|
150445
|
+
const credential = authStorage.get(providerId);
|
|
150446
|
+
if (credential?.type !== "oauth") {
|
|
150447
|
+
return credential;
|
|
150448
|
+
}
|
|
150449
|
+
const stampedCredential = {
|
|
150450
|
+
...credential,
|
|
150451
|
+
...computeStoredCredentialAccountFingerprint(credential) ? {
|
|
150452
|
+
accountFingerprint: computeStoredCredentialAccountFingerprint(credential)
|
|
150453
|
+
} : {}
|
|
150454
|
+
};
|
|
150455
|
+
await authStorage.set(providerId, stampedCredential);
|
|
150456
|
+
return stampedCredential;
|
|
150277
150457
|
}
|
|
150278
150458
|
const existingApiKey = mergedAuthStorage.get(ANTHROPIC_STORAGE_PROVIDER_ID);
|
|
150279
150459
|
await mergedAuthStorage.login(
|
|
@@ -150282,19 +150462,29 @@ function wrapAuthStorageWithApiKeyProviders(authStorage, modelRegistry, readFall
|
|
|
150282
150462
|
);
|
|
150283
150463
|
const oauthCredential = authStorage.get(ANTHROPIC_STORAGE_PROVIDER_ID);
|
|
150284
150464
|
if (oauthCredential?.type === "oauth") {
|
|
150285
|
-
|
|
150465
|
+
const stampedCredential = {
|
|
150466
|
+
...oauthCredential,
|
|
150467
|
+
...computeStoredCredentialAccountFingerprint(oauthCredential) ? {
|
|
150468
|
+
accountFingerprint: computeStoredCredentialAccountFingerprint(oauthCredential)
|
|
150469
|
+
} : {}
|
|
150470
|
+
};
|
|
150471
|
+
await mergedAuthStorage.set(ANTHROPIC_SUBSCRIPTION_STORAGE_PROVIDER_ID, stampedCredential);
|
|
150286
150472
|
if (existingApiKey?.type === "api_key") {
|
|
150287
150473
|
await mergedAuthStorage.set(ANTHROPIC_STORAGE_PROVIDER_ID, existingApiKey);
|
|
150288
150474
|
} else {
|
|
150289
150475
|
await authStorage.remove(ANTHROPIC_STORAGE_PROVIDER_ID);
|
|
150290
150476
|
}
|
|
150477
|
+
return stampedCredential;
|
|
150291
150478
|
}
|
|
150479
|
+
return void 0;
|
|
150292
150480
|
};
|
|
150293
150481
|
return {
|
|
150294
150482
|
reload: () => mergedAuthStorage.reload(),
|
|
150295
150483
|
getOAuthProviders: () => mergedAuthStorage.getOAuthProviders().map((provider) => provider.id === ANTHROPIC_STORAGE_PROVIDER_ID ? { id: ANTHROPIC_STORAGE_PROVIDER_ID, name: "Anthropic Subscription" } : { id: provider.id, name: provider.name }),
|
|
150296
150484
|
hasAuth: (provider) => provider === ANTHROPIC_STORAGE_PROVIDER_ID || provider === ANTHROPIC_SUBSCRIPTION_STORAGE_PROVIDER_ID ? Boolean(getAnthropicSubscriptionCredential()) : mergedAuthStorage.hasAuth(provider),
|
|
150297
|
-
login,
|
|
150485
|
+
login: async (providerId, callbacks) => {
|
|
150486
|
+
await login(providerId, callbacks);
|
|
150487
|
+
},
|
|
150298
150488
|
logout: async (provider) => {
|
|
150299
150489
|
if (provider !== ANTHROPIC_STORAGE_PROVIDER_ID && provider !== ANTHROPIC_SUBSCRIPTION_STORAGE_PROVIDER_ID) {
|
|
150300
150490
|
await mergedAuthStorage.logout(provider);
|
|
@@ -150378,19 +150568,33 @@ function wrapAuthStorageWithApiKeyProviders(authStorage, modelRegistry, readFall
|
|
|
150378
150568
|
},
|
|
150379
150569
|
loginInstance: async (ref, callbacks, label) => {
|
|
150380
150570
|
const providerId = ref.providerId === ANTHROPIC_STORAGE_PROVIDER_ID ? ANTHROPIC_SUBSCRIPTION_STORAGE_PROVIDER_ID : ref.providerId;
|
|
150381
|
-
|
|
150382
|
-
|
|
150383
|
-
|
|
150384
|
-
|
|
150385
|
-
|
|
150386
|
-
|
|
150387
|
-
|
|
150388
|
-
|
|
150389
|
-
|
|
150390
|
-
|
|
150391
|
-
|
|
150392
|
-
|
|
150393
|
-
|
|
150571
|
+
return withProviderInstanceLoginLock(authStorage, providerId, async () => {
|
|
150572
|
+
const target = { providerId, instanceId: ref.instanceId };
|
|
150573
|
+
const previousDefault = mergedAuthStorage.getDefaultInstance(providerId);
|
|
150574
|
+
const previousCredential = previousDefault && mergedAuthStorage.getInstance(previousDefault);
|
|
150575
|
+
const preLoginInstances = mergedAuthStorage.listInstances(providerId).map((instanceRef) => ({ ref: instanceRef, credential: mergedAuthStorage.getInstance(instanceRef) })).filter((entry) => Boolean(entry.credential));
|
|
150576
|
+
const credential = await login(providerId, callbacks);
|
|
150577
|
+
if (!credential) return;
|
|
150578
|
+
const duplicate = preLoginInstances.find(
|
|
150579
|
+
(entry) => entry.ref.instanceId !== target.instanceId && isSameStoredCredentialMaterial(credential, entry.credential)
|
|
150580
|
+
);
|
|
150581
|
+
if (duplicate) {
|
|
150582
|
+
if (previousDefault && previousCredential) {
|
|
150583
|
+
await mergedAuthStorage.setInstance(previousDefault, previousCredential);
|
|
150584
|
+
}
|
|
150585
|
+
const conflictingAccount = duplicate.credential.label || duplicate.ref.instanceId;
|
|
150586
|
+
throw new Error(
|
|
150587
|
+
`This login authorized the account already stored as ${conflictingAccount}. Sign out of the provider in your browser and retry.`
|
|
150588
|
+
);
|
|
150589
|
+
}
|
|
150590
|
+
await mergedAuthStorage.setInstance(target, { ...credential, ...label ? { label } : {} });
|
|
150591
|
+
if (previousDefault && previousCredential && previousDefault.instanceId !== target.instanceId) {
|
|
150592
|
+
await mergedAuthStorage.setInstance(previousDefault, previousCredential);
|
|
150593
|
+
} else if (!previousDefault && target.instanceId !== DEFAULT_PROVIDER_INSTANCE_ID) {
|
|
150594
|
+
await mergedAuthStorage.removeInstance({ providerId, instanceId: DEFAULT_PROVIDER_INSTANCE_ID });
|
|
150595
|
+
await mergedAuthStorage.setDefaultInstance(target);
|
|
150596
|
+
}
|
|
150597
|
+
});
|
|
150394
150598
|
},
|
|
150395
150599
|
logoutInstance: async (ref) => {
|
|
150396
150600
|
await mergedAuthStorage.removeInstance({
|
|
@@ -150634,7 +150838,7 @@ function createReadOnlyAuthFileStorage(authPaths) {
|
|
|
150634
150838
|
}
|
|
150635
150839
|
};
|
|
150636
150840
|
}
|
|
150637
|
-
var ANTHROPIC_API_KEY_PROVIDER_ID2, ANTHROPIC_STORAGE_PROVIDER_ID, ANTHROPIC_SUBSCRIPTION_STORAGE_PROVIDER_ID, BUILT_IN_API_KEY_PROVIDERS, CLI_PROVIDER_IDS;
|
|
150841
|
+
var ANTHROPIC_API_KEY_PROVIDER_ID2, ANTHROPIC_STORAGE_PROVIDER_ID, ANTHROPIC_SUBSCRIPTION_STORAGE_PROVIDER_ID, BUILT_IN_API_KEY_PROVIDERS, CLI_PROVIDER_IDS, instanceLoginLocks;
|
|
150638
150842
|
var init_provider_auth = __esm({
|
|
150639
150843
|
"../engine/src/auth/provider-auth.ts"() {
|
|
150640
150844
|
"use strict";
|
|
@@ -150654,6 +150858,7 @@ var init_provider_auth = __esm({
|
|
|
150654
150858
|
{ id: "zai", name: "Zai" }
|
|
150655
150859
|
];
|
|
150656
150860
|
CLI_PROVIDER_IDS = /* @__PURE__ */ new Set(["pi-claude-cli", "droid-cli"]);
|
|
150861
|
+
instanceLoginLocks = /* @__PURE__ */ new WeakMap();
|
|
150657
150862
|
}
|
|
150658
150863
|
});
|
|
150659
150864
|
|
|
@@ -151039,7 +151244,7 @@ var init_plan_review_continuation = __esm({
|
|
|
151039
151244
|
});
|
|
151040
151245
|
|
|
151041
151246
|
// ../engine/src/execution/hold-release.ts
|
|
151042
|
-
import { createHash as
|
|
151247
|
+
import { createHash as createHash26 } from "node:crypto";
|
|
151043
151248
|
import { readFile as readFile36 } from "node:fs/promises";
|
|
151044
151249
|
function findColumn2(ir2, columnId) {
|
|
151045
151250
|
if (ir2.version !== "v2") return void 0;
|
|
@@ -151077,9 +151282,9 @@ async function checkAndRecordUnplannedExecutionBlock(store, task, ir2) {
|
|
|
151077
151282
|
promptContent = "";
|
|
151078
151283
|
}
|
|
151079
151284
|
}
|
|
151080
|
-
const promptMarker = promptContent.length > 0 ?
|
|
151285
|
+
const promptMarker = promptContent.length > 0 ? createHash26("sha256").update(promptContent).digest("hex") : "missing";
|
|
151081
151286
|
const dependencies = [...task.dependencies ?? []].sort();
|
|
151082
|
-
const episode =
|
|
151287
|
+
const episode = createHash26("sha256").update(JSON.stringify({
|
|
151083
151288
|
planReviewNode,
|
|
151084
151289
|
promptMarker,
|
|
151085
151290
|
dependencies,
|
|
@@ -175048,6 +175253,7 @@ async function connectMcpSessionTools(servers, opts = {}) {
|
|
|
175048
175253
|
const clients = [];
|
|
175049
175254
|
const closedClients = /* @__PURE__ */ new WeakSet();
|
|
175050
175255
|
const usedToolNames = /* @__PURE__ */ new Set();
|
|
175256
|
+
const serverByToolName = /* @__PURE__ */ new Map();
|
|
175051
175257
|
let disposed = false;
|
|
175052
175258
|
const closeOnce = async (client) => {
|
|
175053
175259
|
if (closedClients.has(client)) return;
|
|
@@ -175097,7 +175303,9 @@ async function connectMcpSessionTools(servers, opts = {}) {
|
|
|
175097
175303
|
opts.logger?.log?.(connectMsg);
|
|
175098
175304
|
}
|
|
175099
175305
|
for (const tool of listedTools) {
|
|
175100
|
-
|
|
175306
|
+
const wrappedTool = wrapMcpTool(server.name, tool, client, usedToolNames);
|
|
175307
|
+
tools.push(wrappedTool);
|
|
175308
|
+
serverByToolName.set(wrappedTool.name, server.name);
|
|
175101
175309
|
}
|
|
175102
175310
|
break;
|
|
175103
175311
|
} catch (error3) {
|
|
@@ -175124,7 +175332,7 @@ async function connectMcpSessionTools(servers, opts = {}) {
|
|
|
175124
175332
|
await closeAll();
|
|
175125
175333
|
}
|
|
175126
175334
|
}
|
|
175127
|
-
return { tools, connected, skipped, dispose: closeAll };
|
|
175335
|
+
return { tools, connected, skipped, serverByToolName, dispose: closeAll };
|
|
175128
175336
|
}
|
|
175129
175337
|
function normalizeMaxAttempts(value) {
|
|
175130
175338
|
if (value === void 0 || !Number.isFinite(value)) return DEFAULT_MAX_ATTEMPTS;
|
|
@@ -178264,8 +178472,10 @@ async function createPiAgentSessionRaw(options) {
|
|
|
178264
178472
|
const createSessionWithModel = async (modelOverride) => {
|
|
178265
178473
|
let mcpToolset;
|
|
178266
178474
|
const allowReadonlyMcpTools = options.allowMcpToolsInReadonly === true;
|
|
178267
|
-
|
|
178268
|
-
|
|
178475
|
+
const readonlyMcpServerAllowlist = options.readonlyMcpServerAllowlist === void 0 ? void 0 : new Set(options.readonlyMcpServerAllowlist.map((name2) => name2.trim()).filter(Boolean));
|
|
178476
|
+
const mcpServersToConnect = isReadonly && allowReadonlyMcpTools && readonlyMcpServerAllowlist !== void 0 ? forwardedMcpServers.filter((server) => readonlyMcpServerAllowlist.has(server.name)) : forwardedMcpServers;
|
|
178477
|
+
if (mcpServersToConnect.length > 0 && (!isReadonly || allowReadonlyMcpTools)) {
|
|
178478
|
+
mcpToolset = await connectMcpSessionTools(mcpServersToConnect, {
|
|
178269
178479
|
cwd: options.cwd,
|
|
178270
178480
|
clientFactory: options.mcpClientFactory,
|
|
178271
178481
|
logger: piLog,
|
|
@@ -178276,7 +178486,8 @@ async function createPiAgentSessionRaw(options) {
|
|
|
178276
178486
|
piLog.warn(`MCP session continuing with unavailable servers: count=${bootstrapFailures.length}`);
|
|
178277
178487
|
}
|
|
178278
178488
|
} else if (forwardedMcpServers.length > 0 && isReadonly) {
|
|
178279
|
-
|
|
178489
|
+
const reason = !allowReadonlyMcpTools ? "no-readonly-opt-in" : "readonly-allowlist-no-match";
|
|
178490
|
+
piLog.log(`readonly session \u2014 MCP servers (${forwardedMcpServers.length}) skipped: reason=${reason}`);
|
|
178280
178491
|
}
|
|
178281
178492
|
const mcpReadonlyTools = new Set(mcpToolset?.tools ?? []);
|
|
178282
178493
|
const candidateCustomTools = [
|
|
@@ -178285,7 +178496,9 @@ async function createPiAgentSessionRaw(options) {
|
|
|
178285
178496
|
];
|
|
178286
178497
|
const readonlyFilteredCustomTools = isReadonly ? filterCustomToolsForReadonly(
|
|
178287
178498
|
candidateCustomTools,
|
|
178288
|
-
allowReadonlyMcpTools ? {
|
|
178499
|
+
allowReadonlyMcpTools ? {
|
|
178500
|
+
allowTool: (tool) => readonlyMcpServerAllowlist === void 0 ? mcpReadonlyTools.has(tool) : readonlyMcpServerAllowlist.has(mcpToolset?.serverByToolName?.get(tool.name) ?? "")
|
|
178501
|
+
} : {}
|
|
178289
178502
|
) : { allowed: candidateCustomTools, denied: [] };
|
|
178290
178503
|
const allowlistFilteredCustomTools = {
|
|
178291
178504
|
...readonlyFilteredCustomTools,
|
|
@@ -180297,7 +180510,7 @@ var init_retry_burned_logger = __esm({
|
|
|
180297
180510
|
|
|
180298
180511
|
// ../engine/src/merge/merge-dependency-sync.ts
|
|
180299
180512
|
import { exec as exec18 } from "node:child_process";
|
|
180300
|
-
import { createHash as
|
|
180513
|
+
import { createHash as createHash27 } from "node:crypto";
|
|
180301
180514
|
import { existsSync as existsSync49, readFileSync as readFileSync19, writeFileSync as writeFileSync6 } from "node:fs";
|
|
180302
180515
|
import { join as join67 } from "node:path";
|
|
180303
180516
|
import { promisify as promisify23 } from "node:util";
|
|
@@ -180330,7 +180543,7 @@ function computeLockfileHash(rootDir) {
|
|
|
180330
180543
|
const p2 = join67(rootDir, name2);
|
|
180331
180544
|
if (existsSync49(p2)) {
|
|
180332
180545
|
try {
|
|
180333
|
-
return
|
|
180546
|
+
return createHash27("sha256").update(readFileSync19(p2)).digest("hex");
|
|
180334
180547
|
} catch {
|
|
180335
180548
|
return null;
|
|
180336
180549
|
}
|
|
@@ -180460,7 +180673,7 @@ var init_merge_dependency_sync = __esm({
|
|
|
180460
180673
|
});
|
|
180461
180674
|
|
|
180462
180675
|
// ../engine/src/worktree/worktree-dependency-install.ts
|
|
180463
|
-
import { createHash as
|
|
180676
|
+
import { createHash as createHash28 } from "node:crypto";
|
|
180464
180677
|
import { existsSync as existsSync50, readFileSync as readFileSync20, readdirSync as readdirSync8, statSync as statSync11, writeFileSync as writeFileSync7 } from "node:fs";
|
|
180465
180678
|
import { delimiter as delimiter2, join as join68 } from "node:path";
|
|
180466
180679
|
function rootEntries(rootDir) {
|
|
@@ -180558,7 +180771,7 @@ function isCommandAvailable(binary, env = process.env) {
|
|
|
180558
180771
|
);
|
|
180559
180772
|
}
|
|
180560
180773
|
function hashParts(parts) {
|
|
180561
|
-
const hash3 =
|
|
180774
|
+
const hash3 = createHash28("sha256");
|
|
180562
180775
|
for (const [name2, value] of [...parts].sort(([left], [right]) => left.localeCompare(right))) {
|
|
180563
180776
|
hash3.update(name2).update("\0").update(value).update("\0");
|
|
180564
180777
|
}
|
|
@@ -186546,7 +186759,7 @@ var init_mission_feature_sync = __esm({
|
|
|
186546
186759
|
// ../engine/src/agent-tools.ts
|
|
186547
186760
|
import { appendFile as appendFile3, mkdir as mkdir27, readFile as readFile40, readdir as readdir11, realpath, stat as stat11, writeFile as writeFile23 } from "node:fs/promises";
|
|
186548
186761
|
import { existsSync as existsSync53 } from "node:fs";
|
|
186549
|
-
import { createHash as
|
|
186762
|
+
import { createHash as createHash29, randomUUID as randomUUID48 } from "node:crypto";
|
|
186550
186763
|
import { tmpdir as tmpdir6 } from "node:os";
|
|
186551
186764
|
import { extname as extname4, isAbsolute as isAbsolute14, join as join71, relative as relative13, resolve as resolve40, sep as sep11 } from "node:path";
|
|
186552
186765
|
import { Type as Type2 } from "@earendil-works/pi-ai";
|
|
@@ -186590,7 +186803,7 @@ async function readAgentMemoryWorkspaceLongTerm(rootDir, agentId) {
|
|
|
186590
186803
|
}
|
|
186591
186804
|
}
|
|
186592
186805
|
function qmdAgentMemoryCollectionName2(rootDir, agentId) {
|
|
186593
|
-
const hash3 =
|
|
186806
|
+
const hash3 = createHash29("sha1").update(`${rootDir}:${agentId}`).digest("hex").slice(0, 12);
|
|
186594
186807
|
return `fusion-agent-memory-${sanitizeAgentMemoryId(agentId).toLowerCase()}-${hash3}`;
|
|
186595
186808
|
}
|
|
186596
186809
|
function buildQmdAgentMemoryCollectionAddArgs(rootDir, agentId) {
|
|
@@ -186719,11 +186932,11 @@ async function refreshAgentMemoryQmdIndex(rootDir, agentMemory) {
|
|
|
186719
186932
|
return;
|
|
186720
186933
|
}
|
|
186721
186934
|
const promise = (async () => {
|
|
186722
|
-
const { execFile:
|
|
186723
|
-
const { promisify:
|
|
186724
|
-
const
|
|
186935
|
+
const { execFile: execFile47 } = await import("node:child_process");
|
|
186936
|
+
const { promisify: promisify102 } = await import("node:util");
|
|
186937
|
+
const execFileAsync41 = promisify102(execFile47);
|
|
186725
186938
|
try {
|
|
186726
|
-
await
|
|
186939
|
+
await execFileAsync41("qmd", buildQmdAgentMemoryCollectionAddArgs(rootDir, agentMemory.agentId), {
|
|
186727
186940
|
cwd: rootDir,
|
|
186728
186941
|
timeout: 4e3,
|
|
186729
186942
|
maxBuffer: 512 * 1024
|
|
@@ -186736,8 +186949,8 @@ ${stderr}`)) {
|
|
|
186736
186949
|
throw error3;
|
|
186737
186950
|
}
|
|
186738
186951
|
}
|
|
186739
|
-
await
|
|
186740
|
-
await
|
|
186952
|
+
await execFileAsync41("qmd", ["update"], { cwd: rootDir, timeout: 3e4, maxBuffer: 1024 * 1024 });
|
|
186953
|
+
await execFileAsync41("qmd", ["embed"], { cwd: rootDir, timeout: 12e4, maxBuffer: 1024 * 1024 });
|
|
186741
186954
|
})();
|
|
186742
186955
|
agentQmdRefreshState.set(key, { lastStartedAt: now, inFlight: promise });
|
|
186743
186956
|
try {
|
|
@@ -186792,10 +187005,10 @@ async function searchAgentMemoryWithQmd(rootDir, agentMemory, query, limit) {
|
|
|
186792
187005
|
}
|
|
186793
187006
|
try {
|
|
186794
187007
|
await refreshAgentMemoryQmdIndex(rootDir, agentMemory);
|
|
186795
|
-
const { execFile:
|
|
186796
|
-
const { promisify:
|
|
186797
|
-
const
|
|
186798
|
-
const { stdout } = await
|
|
187008
|
+
const { execFile: execFile47 } = await import("node:child_process");
|
|
187009
|
+
const { promisify: promisify102 } = await import("node:util");
|
|
187010
|
+
const execFileAsync41 = promisify102(execFile47);
|
|
187011
|
+
const { stdout } = await execFileAsync41("qmd", buildQmdAgentMemorySearchArgs(rootDir, agentMemory.agentId, query, limit), {
|
|
186799
187012
|
cwd: rootDir,
|
|
186800
187013
|
timeout: 4e3,
|
|
186801
187014
|
maxBuffer: 1024 * 1024
|
|
@@ -198085,7 +198298,7 @@ var init_workspace_review_remediation = __esm({
|
|
|
198085
198298
|
});
|
|
198086
198299
|
|
|
198087
198300
|
// ../engine/src/worktree/secrets-env-writer.ts
|
|
198088
|
-
import { createHash as
|
|
198301
|
+
import { createHash as createHash30 } from "node:crypto";
|
|
198089
198302
|
import { execFile as execFile14 } from "node:child_process";
|
|
198090
198303
|
import { promises as fs6 } from "node:fs";
|
|
198091
198304
|
import path3 from "node:path";
|
|
@@ -198094,7 +198307,7 @@ function isValidFilename(filename) {
|
|
|
198094
198307
|
return !!filename && !filename.includes("/") && !filename.includes("\\") && !filename.includes("..") && !filename.includes("\0") && filename !== FINGERPRINT_FILE;
|
|
198095
198308
|
}
|
|
198096
198309
|
function sha2562(content) {
|
|
198097
|
-
return
|
|
198310
|
+
return createHash30("sha256").update(Buffer.from(content, "utf8")).digest("hex");
|
|
198098
198311
|
}
|
|
198099
198312
|
function quote(value) {
|
|
198100
198313
|
return `"${value.replaceAll("\\", "\\\\").replaceAll('"', '\\"').replaceAll("\n", "\\n").replaceAll("\r", "\\r").replaceAll(" ", "\\t")}"`;
|
|
@@ -200653,7 +200866,7 @@ var init_workflow_graph_executor = __esm({
|
|
|
200653
200866
|
phase: "pre-merge",
|
|
200654
200867
|
source: "optional-group",
|
|
200655
200868
|
status: "skipped",
|
|
200656
|
-
bypassedBy:
|
|
200869
|
+
bypassedBy: FAST_MODE_BYPASS_ACTOR,
|
|
200657
200870
|
bypassedAt,
|
|
200658
200871
|
bypassReason: "Fast mode bypasses pre-merge workflow gates",
|
|
200659
200872
|
bypassedFromStatus: "absent",
|
|
@@ -200857,7 +201070,7 @@ var init_workflow_graph_executor = __esm({
|
|
|
200857
201070
|
const stepFindings = this.workflowReviewKind(node) && Array.isArray(exitContextPatch?.findings) ? exitContextPatch.findings : void 0;
|
|
200858
201071
|
const repositoryReviewOutcomes = this.workflowReviewKind(node) && Array.isArray(exitContextPatch?.repositoryReviewOutcomes) ? exitContextPatch.repositoryReviewOutcomes : void 0;
|
|
200859
201072
|
const repositoryScopeRevision = this.workflowReviewKind(node) && typeof exitContextPatch?.repositoryScopeRevision === "number" ? exitContextPatch.repositoryScopeRevision : void 0;
|
|
200860
|
-
const reviewInputFingerprint = this.workflowReviewKind(node) && typeof exitContextPatch?.reviewInputFingerprint === "string" ? exitContextPatch.reviewInputFingerprint : void 0;
|
|
201073
|
+
const reviewInputFingerprint = requiresContentReviewProof(node.id, { reviewKind: this.workflowReviewKind(node) }) && typeof exitContextPatch?.reviewInputFingerprint === "string" ? exitContextPatch.reviewInputFingerprint : void 0;
|
|
200861
201074
|
const reviewedCommitSha = this.workflowReviewKind(node) && typeof exitContextPatch?.reviewedCommitSha === "string" ? exitContextPatch.reviewedCommitSha : void 0;
|
|
200862
201075
|
const supersededFindingSourceWorkflowStepId = this.workflowReviewKind(node) && typeof exitContextPatch?.supersededFindingSourceWorkflowStepId === "string" ? exitContextPatch.supersededFindingSourceWorkflowStepId : void 0;
|
|
200863
201076
|
const supersededFindingIds = supersededFindingSourceWorkflowStepId && this.workflowReviewKind(node) && Array.isArray(exitContextPatch?.supersededFindingIds) ? exitContextPatch.supersededFindingIds.filter((id) => typeof id === "string") : void 0;
|
|
@@ -201596,7 +201809,7 @@ ${stepOutput}` : ""}`);
|
|
|
201596
201809
|
const findings = this.workflowReviewKind(node) && Array.isArray(contextPatch.findings) ? contextPatch.findings : void 0;
|
|
201597
201810
|
const repositoryReviewOutcomes = this.workflowReviewKind(node) && Array.isArray(contextPatch.repositoryReviewOutcomes) ? contextPatch.repositoryReviewOutcomes : void 0;
|
|
201598
201811
|
const repositoryScopeRevision = this.workflowReviewKind(node) && typeof contextPatch.repositoryScopeRevision === "number" ? contextPatch.repositoryScopeRevision : void 0;
|
|
201599
|
-
const reviewInputFingerprint = this.workflowReviewKind(node) && typeof contextPatch.reviewInputFingerprint === "string" ? contextPatch.reviewInputFingerprint : void 0;
|
|
201812
|
+
const reviewInputFingerprint = requiresContentReviewProof(node.id, { reviewKind: this.workflowReviewKind(node) }) && typeof contextPatch.reviewInputFingerprint === "string" ? contextPatch.reviewInputFingerprint : void 0;
|
|
201600
201813
|
const reviewedCommitSha = this.workflowReviewKind(node) && typeof contextPatch.reviewedCommitSha === "string" ? contextPatch.reviewedCommitSha : void 0;
|
|
201601
201814
|
const supersededFindingSourceWorkflowStepId = this.workflowReviewKind(node) && typeof contextPatch.supersededFindingSourceWorkflowStepId === "string" ? contextPatch.supersededFindingSourceWorkflowStepId : void 0;
|
|
201602
201815
|
const supersededFindingIds = supersededFindingSourceWorkflowStepId && this.workflowReviewKind(node) && Array.isArray(contextPatch.supersededFindingIds) ? contextPatch.supersededFindingIds.filter((id) => typeof id === "string") : void 0;
|
|
@@ -202977,17 +203190,141 @@ var init_agent_binding_pure = __esm({
|
|
|
202977
203190
|
}
|
|
202978
203191
|
});
|
|
202979
203192
|
|
|
202980
|
-
// ../engine/src/worktree
|
|
202981
|
-
import {
|
|
202982
|
-
import { execFile as execFile15 } from "node:child_process";
|
|
203193
|
+
// ../engine/src/executor/worktree-git-refs.ts
|
|
203194
|
+
import { exec as exec25, execFile as execFile15, execSync as execSync3 } from "node:child_process";
|
|
202983
203195
|
import { promisify as promisify32 } from "node:util";
|
|
203196
|
+
async function preExecutionWorktreeHasWork(worktreePath) {
|
|
203197
|
+
try {
|
|
203198
|
+
const { stdout: dirty } = await execFileAsync9("git", ["status", "--porcelain"], { cwd: worktreePath, timeout: 3e4 });
|
|
203199
|
+
if (dirty.trim()) return true;
|
|
203200
|
+
const { stdout: ahead } = await execFileAsync9("git", ["log", "--oneline", "@{upstream}..HEAD"], { cwd: worktreePath, timeout: 3e4 }).catch(async () => await execFileAsync9("git", ["log", "--oneline", "-1", "HEAD", "--not", "--remotes", "--branches=main", "--branches=master"], { cwd: worktreePath, timeout: 3e4 }));
|
|
203201
|
+
return Boolean(ahead.trim());
|
|
203202
|
+
} catch {
|
|
203203
|
+
return true;
|
|
203204
|
+
}
|
|
203205
|
+
}
|
|
203206
|
+
async function resolveContaminationBaseRef(worktreePath) {
|
|
203207
|
+
try {
|
|
203208
|
+
const { stdout } = await execAsync22(
|
|
203209
|
+
"git merge-base HEAD main 2>/dev/null || git merge-base HEAD origin/main",
|
|
203210
|
+
{ cwd: worktreePath, encoding: "utf-8" }
|
|
203211
|
+
);
|
|
203212
|
+
const ref = stdout.trim();
|
|
203213
|
+
return ref || void 0;
|
|
203214
|
+
} catch (err) {
|
|
203215
|
+
const errorMessage2 = err instanceof Error ? err.message : String(err);
|
|
203216
|
+
executorLog.warn(`Failed merge-base lookup for contamination check in ${worktreePath}: ${errorMessage2}`);
|
|
203217
|
+
return void 0;
|
|
203218
|
+
}
|
|
203219
|
+
}
|
|
203220
|
+
async function resolveDiffBaseRef(worktreePath, baseCommitSha) {
|
|
203221
|
+
if (baseCommitSha) return baseCommitSha;
|
|
203222
|
+
try {
|
|
203223
|
+
const { stdout } = await execAsync22(
|
|
203224
|
+
"git merge-base HEAD origin/main 2>/dev/null || git merge-base HEAD main",
|
|
203225
|
+
{ cwd: worktreePath, encoding: "utf-8" }
|
|
203226
|
+
);
|
|
203227
|
+
const ref = stdout.trim();
|
|
203228
|
+
if (ref) return ref;
|
|
203229
|
+
} catch (mergeBaseErr) {
|
|
203230
|
+
const mergeBaseMsg = mergeBaseErr instanceof Error ? mergeBaseErr.message : String(mergeBaseErr);
|
|
203231
|
+
executorLog.warn(`Failed merge-base lookup for diff base in ${worktreePath}, trying HEAD~1 fallback: ${mergeBaseMsg}`);
|
|
203232
|
+
}
|
|
203233
|
+
try {
|
|
203234
|
+
const { stdout } = await execAsync22("git rev-parse HEAD~1", {
|
|
203235
|
+
cwd: worktreePath,
|
|
203236
|
+
encoding: "utf-8"
|
|
203237
|
+
});
|
|
203238
|
+
return stdout.trim() || void 0;
|
|
203239
|
+
} catch {
|
|
203240
|
+
executorLog.debug(`Could not determine base commit for diff in ${worktreePath}`);
|
|
203241
|
+
return void 0;
|
|
203242
|
+
}
|
|
203243
|
+
}
|
|
203244
|
+
async function captureBaseCommitSha(store, task, worktreePath, audit, options = { isResume: false }) {
|
|
203245
|
+
try {
|
|
203246
|
+
if (options.isResume && task.baseCommitSha) {
|
|
203247
|
+
try {
|
|
203248
|
+
execSync3(`git merge-base --is-ancestor ${task.baseCommitSha} HEAD`, {
|
|
203249
|
+
cwd: worktreePath,
|
|
203250
|
+
stdio: "pipe"
|
|
203251
|
+
});
|
|
203252
|
+
executorLog.log(`${task.id}: preserved baseCommitSha ${task.baseCommitSha.slice(0, 7)} (resume)`);
|
|
203253
|
+
await audit.git({
|
|
203254
|
+
type: "commit:create",
|
|
203255
|
+
target: task.baseCommitSha,
|
|
203256
|
+
metadata: { purpose: "base", preserved: true }
|
|
203257
|
+
});
|
|
203258
|
+
return;
|
|
203259
|
+
} catch {
|
|
203260
|
+
}
|
|
203261
|
+
}
|
|
203262
|
+
const baseCommitSha = await resolveCapturedBaseCommitSha(worktreePath, {
|
|
203263
|
+
warn: (msg) => executorLog.warn(`${task.id}: ${msg}`)
|
|
203264
|
+
});
|
|
203265
|
+
if (!baseCommitSha) {
|
|
203266
|
+
throw new Error("could not resolve base commit SHA");
|
|
203267
|
+
}
|
|
203268
|
+
await store.updateTask(task.id, { baseCommitSha });
|
|
203269
|
+
executorLog.debug(`${task.id}: captured baseCommitSha ${baseCommitSha.slice(0, 7)}`);
|
|
203270
|
+
await audit.git({ type: "commit:create", target: baseCommitSha, metadata: { purpose: "base", preserved: false } });
|
|
203271
|
+
} catch (err) {
|
|
203272
|
+
const errorMessage2 = err instanceof Error ? err.message : String(err);
|
|
203273
|
+
executorLog.debug(`Failed to capture baseCommitSha for ${task.id}: ${errorMessage2}`);
|
|
203274
|
+
}
|
|
203275
|
+
}
|
|
203276
|
+
var execAsync22, execFileAsync9;
|
|
203277
|
+
var init_worktree_git_refs = __esm({
|
|
203278
|
+
"../engine/src/executor/worktree-git-refs.ts"() {
|
|
203279
|
+
"use strict";
|
|
203280
|
+
init_base_commit_capture();
|
|
203281
|
+
init_logger3();
|
|
203282
|
+
execAsync22 = promisify32(exec25);
|
|
203283
|
+
execFileAsync9 = promisify32(execFile15);
|
|
203284
|
+
}
|
|
203285
|
+
});
|
|
203286
|
+
|
|
203287
|
+
// ../engine/src/worktree/review-diff-fingerprint.ts
|
|
203288
|
+
import { createHash as createHash31 } from "node:crypto";
|
|
203289
|
+
import { execFile as execFile16 } from "node:child_process";
|
|
203290
|
+
import { promisify as promisify33 } from "node:util";
|
|
203291
|
+
function gitCaptureOptions(cwd) {
|
|
203292
|
+
return {
|
|
203293
|
+
cwd,
|
|
203294
|
+
encoding: "utf8",
|
|
203295
|
+
maxBuffer: REVIEW_DIFF_GIT_MAX_BUFFER_BYTES,
|
|
203296
|
+
timeout: REVIEW_DIFF_GIT_TIMEOUT_MS
|
|
203297
|
+
};
|
|
203298
|
+
}
|
|
203299
|
+
function isGitDiffBufferOverflow(error3) {
|
|
203300
|
+
if (typeof error3 !== "object" || error3 === null) return false;
|
|
203301
|
+
const candidate = error3;
|
|
203302
|
+
return candidate.code === "ERR_CHILD_PROCESS_STDIO_MAXBUFFER" || typeof candidate.message === "string" && candidate.message.includes("maxBuffer");
|
|
203303
|
+
}
|
|
203304
|
+
async function resolveContentReviewInputProof(worktreePath, diffBaseCommitSha) {
|
|
203305
|
+
let baseRef;
|
|
203306
|
+
try {
|
|
203307
|
+
baseRef = await resolveDiffBaseRef(worktreePath, diffBaseCommitSha);
|
|
203308
|
+
} catch {
|
|
203309
|
+
return { kind: "unprovable", reason: "no-diff-base" };
|
|
203310
|
+
}
|
|
203311
|
+
if (!baseRef) return { kind: "unprovable", reason: "no-diff-base" };
|
|
203312
|
+
const probe = await probeReviewDiffFingerprint(worktreePath, baseRef);
|
|
203313
|
+
if (probe.state === "empty") {
|
|
203314
|
+
return { kind: "fingerprint", fingerprint: EMPTY_REVIEW_DIFF_FINGERPRINT };
|
|
203315
|
+
}
|
|
203316
|
+
return probe.state === "fingerprint" ? { kind: "fingerprint", fingerprint: probe.fingerprint } : { kind: "unprovable", reason: probe.reason };
|
|
203317
|
+
}
|
|
202984
203318
|
async function probeReviewDiffFingerprint(worktreePath, baseRef, targetRef = "HEAD") {
|
|
202985
203319
|
if (!worktreePath || !baseRef) return { state: "unavailable", reason: "missing-worktree-or-base" };
|
|
202986
203320
|
try {
|
|
202987
|
-
const { stdout } = await
|
|
202988
|
-
return stdout ? { state: "fingerprint", fingerprint:
|
|
202989
|
-
} catch {
|
|
202990
|
-
return {
|
|
203321
|
+
const { stdout } = await execFileAsync10("git", ["diff", "--binary", `${baseRef}..${targetRef}`], gitCaptureOptions(worktreePath));
|
|
203322
|
+
return stdout ? { state: "fingerprint", fingerprint: createHash31("sha256").update(stdout).digest("hex") } : { state: "empty" };
|
|
203323
|
+
} catch (error3) {
|
|
203324
|
+
return {
|
|
203325
|
+
state: "unavailable",
|
|
203326
|
+
reason: isGitDiffBufferOverflow(error3) ? "git-diff-too-large" : "git-diff-failed"
|
|
203327
|
+
};
|
|
202991
203328
|
}
|
|
202992
203329
|
}
|
|
202993
203330
|
async function probeReviewChangesSinceCommit(worktreePath, reviewedCommitSha) {
|
|
@@ -202995,14 +203332,11 @@ async function probeReviewChangesSinceCommit(worktreePath, reviewedCommitSha) {
|
|
|
202995
203332
|
return { state: "unavailable", reason: "missing-worktree-or-reviewed-commit" };
|
|
202996
203333
|
}
|
|
202997
203334
|
try {
|
|
202998
|
-
await
|
|
202999
|
-
cwd: worktreePath,
|
|
203000
|
-
encoding: "utf8"
|
|
203001
|
-
});
|
|
203335
|
+
await execFileAsync10("git", ["cat-file", "-e", `${reviewedCommitSha}^{commit}`], gitCaptureOptions(worktreePath));
|
|
203002
203336
|
const [{ stdout: countOutput }, { stdout: filesOutput }, { stdout: shortstatOutput }] = await Promise.all([
|
|
203003
|
-
|
|
203004
|
-
|
|
203005
|
-
|
|
203337
|
+
execFileAsync10("git", ["rev-list", "--count", `${reviewedCommitSha}..HEAD`], gitCaptureOptions(worktreePath)),
|
|
203338
|
+
execFileAsync10("git", ["diff", "--name-only", "-z", `${reviewedCommitSha}..HEAD`], gitCaptureOptions(worktreePath)),
|
|
203339
|
+
execFileAsync10("git", ["diff", "--shortstat", `${reviewedCommitSha}..HEAD`], gitCaptureOptions(worktreePath))
|
|
203006
203340
|
]);
|
|
203007
203341
|
const commitCount = Number.parseInt(countOutput.trim(), 10);
|
|
203008
203342
|
if (!Number.isSafeInteger(commitCount) || commitCount < 0) {
|
|
@@ -203031,22 +203365,30 @@ async function computeCodeReviewInputFingerprint(worktreePath, baseRef, targetRe
|
|
|
203031
203365
|
if (result2.state === "empty") return EMPTY_REVIEW_DIFF_FINGERPRINT;
|
|
203032
203366
|
return result2.state === "fingerprint" ? result2.fingerprint : void 0;
|
|
203033
203367
|
}
|
|
203034
|
-
var
|
|
203368
|
+
var execFileAsync10, REVIEW_DIFF_GIT_MAX_BUFFER_BYTES, REVIEW_DIFF_GIT_TIMEOUT_MS, MAX_REVIEW_CHANGED_FILES, EMPTY_REVIEW_DIFF_FINGERPRINT;
|
|
203035
203369
|
var init_review_diff_fingerprint = __esm({
|
|
203036
203370
|
"../engine/src/worktree/review-diff-fingerprint.ts"() {
|
|
203037
203371
|
"use strict";
|
|
203038
|
-
|
|
203372
|
+
init_worktree_git_refs();
|
|
203373
|
+
execFileAsync10 = promisify33(execFile16);
|
|
203374
|
+
REVIEW_DIFF_GIT_MAX_BUFFER_BYTES = 10 * 1024 * 1024;
|
|
203375
|
+
REVIEW_DIFF_GIT_TIMEOUT_MS = 12e4;
|
|
203039
203376
|
MAX_REVIEW_CHANGED_FILES = 100;
|
|
203040
203377
|
EMPTY_REVIEW_DIFF_FINGERPRINT = "empty-review-input:v1";
|
|
203041
203378
|
}
|
|
203042
203379
|
});
|
|
203043
203380
|
|
|
203044
203381
|
// ../engine/src/worktree/workspace-review-evidence.ts
|
|
203045
|
-
import { execFile as
|
|
203046
|
-
import { promisify as
|
|
203382
|
+
import { execFile as execFile17 } from "node:child_process";
|
|
203383
|
+
import { promisify as promisify34 } from "node:util";
|
|
203047
203384
|
import { join as join76 } from "node:path";
|
|
203048
203385
|
async function git3(args, cwd) {
|
|
203049
|
-
const { stdout } = await
|
|
203386
|
+
const { stdout } = await execFileAsync11("git", args, {
|
|
203387
|
+
cwd,
|
|
203388
|
+
encoding: "utf8",
|
|
203389
|
+
maxBuffer: REVIEW_DIFF_GIT_MAX_BUFFER_BYTES,
|
|
203390
|
+
timeout: REVIEW_DIFF_GIT_TIMEOUT_MS
|
|
203391
|
+
});
|
|
203050
203392
|
return stdout.trim();
|
|
203051
203393
|
}
|
|
203052
203394
|
async function captureWorkspaceReviewEvidence(options) {
|
|
@@ -203099,13 +203441,60 @@ async function captureWorkspaceReviewEvidence(options) {
|
|
|
203099
203441
|
outOfScopeRepositories
|
|
203100
203442
|
};
|
|
203101
203443
|
}
|
|
203102
|
-
var
|
|
203444
|
+
var execFileAsync11;
|
|
203103
203445
|
var init_workspace_review_evidence = __esm({
|
|
203104
203446
|
"../engine/src/worktree/workspace-review-evidence.ts"() {
|
|
203105
203447
|
"use strict";
|
|
203106
203448
|
init_workspace_base_branch();
|
|
203107
203449
|
init_review_diff_fingerprint();
|
|
203108
|
-
|
|
203450
|
+
execFileAsync11 = promisify34(execFile17);
|
|
203451
|
+
}
|
|
203452
|
+
});
|
|
203453
|
+
|
|
203454
|
+
// ../engine/src/worktree/review-inline-fix-recapture.ts
|
|
203455
|
+
import { execFile as execFile18 } from "node:child_process";
|
|
203456
|
+
import { promisify as promisify35 } from "node:util";
|
|
203457
|
+
function classifyReviewInlineFixRecapture(input) {
|
|
203458
|
+
if (input.reviewKind === "plan") return { recapture: false, reason: "plan-domain" };
|
|
203459
|
+
if (input.verdict !== "APPROVE" && input.verdict !== "APPROVE_WITH_NOTES") {
|
|
203460
|
+
return { recapture: false, reason: "not-approval-verdict" };
|
|
203461
|
+
}
|
|
203462
|
+
if (!input.reviewedCommitSha || !input.currentHeadSha || !input.baseRef) {
|
|
203463
|
+
return { recapture: false, reason: "missing-anchor" };
|
|
203464
|
+
}
|
|
203465
|
+
if (input.reviewedCommitSha === input.currentHeadSha) return { recapture: false, reason: "head-unchanged" };
|
|
203466
|
+
if (input.fastForwardAdvance === void 0 || input.baseIsAncestor === void 0) {
|
|
203467
|
+
return { recapture: false, reason: "probe-unavailable" };
|
|
203468
|
+
}
|
|
203469
|
+
if (!input.fastForwardAdvance) return { recapture: false, reason: "history-rewritten" };
|
|
203470
|
+
if (!input.baseIsAncestor) return { recapture: false, reason: "base-not-ancestor" };
|
|
203471
|
+
if (!input.fingerprintProbeAvailable) return { recapture: false, reason: "probe-unavailable" };
|
|
203472
|
+
return { recapture: true, reason: "recaptured" };
|
|
203473
|
+
}
|
|
203474
|
+
async function readHeadSha(worktreePath) {
|
|
203475
|
+
if (!worktreePath) return void 0;
|
|
203476
|
+
try {
|
|
203477
|
+
const { stdout } = await execFileAsync12("git", ["rev-parse", "HEAD"], { cwd: worktreePath, encoding: "utf8" });
|
|
203478
|
+
return stdout.trim() || void 0;
|
|
203479
|
+
} catch {
|
|
203480
|
+
return void 0;
|
|
203481
|
+
}
|
|
203482
|
+
}
|
|
203483
|
+
async function isFastForwardAdvance(worktreePath, fromSha, toSha) {
|
|
203484
|
+
if (!worktreePath || !fromSha || !toSha) return void 0;
|
|
203485
|
+
try {
|
|
203486
|
+
await execFileAsync12("git", ["merge-base", "--is-ancestor", fromSha, toSha], { cwd: worktreePath, encoding: "utf8" });
|
|
203487
|
+
return true;
|
|
203488
|
+
} catch (error3) {
|
|
203489
|
+
const code = error3?.code;
|
|
203490
|
+
return code === 1 ? false : void 0;
|
|
203491
|
+
}
|
|
203492
|
+
}
|
|
203493
|
+
var execFileAsync12;
|
|
203494
|
+
var init_review_inline_fix_recapture = __esm({
|
|
203495
|
+
"../engine/src/worktree/review-inline-fix-recapture.ts"() {
|
|
203496
|
+
"use strict";
|
|
203497
|
+
execFileAsync12 = promisify35(execFile18);
|
|
203109
203498
|
}
|
|
203110
203499
|
});
|
|
203111
203500
|
|
|
@@ -203295,8 +203684,8 @@ var init_workspace_zero_acquire = __esm({
|
|
|
203295
203684
|
});
|
|
203296
203685
|
|
|
203297
203686
|
// ../engine/src/execution/branch-attribution.ts
|
|
203298
|
-
import { exec as
|
|
203299
|
-
import { promisify as
|
|
203687
|
+
import { exec as exec26 } from "node:child_process";
|
|
203688
|
+
import { promisify as promisify36 } from "node:util";
|
|
203300
203689
|
function quoteShellArg6(value) {
|
|
203301
203690
|
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
203302
203691
|
}
|
|
@@ -203334,7 +203723,7 @@ function taskIdsMatch(a, b3) {
|
|
|
203334
203723
|
return a.toUpperCase() === b3.toUpperCase();
|
|
203335
203724
|
}
|
|
203336
203725
|
async function collectOwnTaskCommitsForRange(opts) {
|
|
203337
|
-
const execImpl = opts.execAsyncImpl ??
|
|
203726
|
+
const execImpl = opts.execAsyncImpl ?? execAsync23;
|
|
203338
203727
|
let logOutput;
|
|
203339
203728
|
try {
|
|
203340
203729
|
const result2 = await execImpl(
|
|
@@ -203375,7 +203764,7 @@ async function collectOwnTaskCommitsForRange(opts) {
|
|
|
203375
203764
|
return { ownCommitCount: ownCommitShas.length, ownCommitShas };
|
|
203376
203765
|
}
|
|
203377
203766
|
async function filterFilesToOwnTaskCommits(opts) {
|
|
203378
|
-
const execImpl = opts.execAsyncImpl ??
|
|
203767
|
+
const execImpl = opts.execAsyncImpl ?? execAsync23;
|
|
203379
203768
|
const runGit10 = async (command) => {
|
|
203380
203769
|
try {
|
|
203381
203770
|
const { stdout } = await execImpl(command, {
|
|
@@ -203441,11 +203830,11 @@ async function filterFilesToOwnTaskCommits(opts) {
|
|
|
203441
203830
|
commitAttributions
|
|
203442
203831
|
};
|
|
203443
203832
|
}
|
|
203444
|
-
var
|
|
203833
|
+
var execAsync23, GIT_TIMEOUT_MS5, GIT_MAX_BUFFER2, BranchAttributionError, SilentNoOpAttributionMismatchError;
|
|
203445
203834
|
var init_branch_attribution = __esm({
|
|
203446
203835
|
"../engine/src/execution/branch-attribution.ts"() {
|
|
203447
203836
|
"use strict";
|
|
203448
|
-
|
|
203837
|
+
execAsync23 = promisify36(exec26);
|
|
203449
203838
|
GIT_TIMEOUT_MS5 = 3e4;
|
|
203450
203839
|
GIT_MAX_BUFFER2 = 10 * 1024 * 1024;
|
|
203451
203840
|
BranchAttributionError = class extends Error {
|
|
@@ -203479,103 +203868,9 @@ var init_branch_attribution = __esm({
|
|
|
203479
203868
|
}
|
|
203480
203869
|
});
|
|
203481
203870
|
|
|
203482
|
-
// ../engine/src/executor/worktree-git-refs.ts
|
|
203483
|
-
import { exec as exec26, execFile as execFile17, execSync as execSync3 } from "node:child_process";
|
|
203484
|
-
import { promisify as promisify35 } from "node:util";
|
|
203485
|
-
async function preExecutionWorktreeHasWork(worktreePath) {
|
|
203486
|
-
try {
|
|
203487
|
-
const { stdout: dirty } = await execFileAsync11("git", ["status", "--porcelain"], { cwd: worktreePath, timeout: 3e4 });
|
|
203488
|
-
if (dirty.trim()) return true;
|
|
203489
|
-
const { stdout: ahead } = await execFileAsync11("git", ["log", "--oneline", "@{upstream}..HEAD"], { cwd: worktreePath, timeout: 3e4 }).catch(async () => await execFileAsync11("git", ["log", "--oneline", "-1", "HEAD", "--not", "--remotes", "--branches=main", "--branches=master"], { cwd: worktreePath, timeout: 3e4 }));
|
|
203490
|
-
return Boolean(ahead.trim());
|
|
203491
|
-
} catch {
|
|
203492
|
-
return true;
|
|
203493
|
-
}
|
|
203494
|
-
}
|
|
203495
|
-
async function resolveContaminationBaseRef(worktreePath) {
|
|
203496
|
-
try {
|
|
203497
|
-
const { stdout } = await execAsync23(
|
|
203498
|
-
"git merge-base HEAD main 2>/dev/null || git merge-base HEAD origin/main",
|
|
203499
|
-
{ cwd: worktreePath, encoding: "utf-8" }
|
|
203500
|
-
);
|
|
203501
|
-
const ref = stdout.trim();
|
|
203502
|
-
return ref || void 0;
|
|
203503
|
-
} catch (err) {
|
|
203504
|
-
const errorMessage2 = err instanceof Error ? err.message : String(err);
|
|
203505
|
-
executorLog.warn(`Failed merge-base lookup for contamination check in ${worktreePath}: ${errorMessage2}`);
|
|
203506
|
-
return void 0;
|
|
203507
|
-
}
|
|
203508
|
-
}
|
|
203509
|
-
async function resolveDiffBaseRef(worktreePath, baseCommitSha) {
|
|
203510
|
-
if (baseCommitSha) return baseCommitSha;
|
|
203511
|
-
try {
|
|
203512
|
-
const { stdout } = await execAsync23(
|
|
203513
|
-
"git merge-base HEAD origin/main 2>/dev/null || git merge-base HEAD main",
|
|
203514
|
-
{ cwd: worktreePath, encoding: "utf-8" }
|
|
203515
|
-
);
|
|
203516
|
-
const ref = stdout.trim();
|
|
203517
|
-
if (ref) return ref;
|
|
203518
|
-
} catch (mergeBaseErr) {
|
|
203519
|
-
const mergeBaseMsg = mergeBaseErr instanceof Error ? mergeBaseErr.message : String(mergeBaseErr);
|
|
203520
|
-
executorLog.warn(`Failed merge-base lookup for diff base in ${worktreePath}, trying HEAD~1 fallback: ${mergeBaseMsg}`);
|
|
203521
|
-
}
|
|
203522
|
-
try {
|
|
203523
|
-
const { stdout } = await execAsync23("git rev-parse HEAD~1", {
|
|
203524
|
-
cwd: worktreePath,
|
|
203525
|
-
encoding: "utf-8"
|
|
203526
|
-
});
|
|
203527
|
-
return stdout.trim() || void 0;
|
|
203528
|
-
} catch {
|
|
203529
|
-
executorLog.debug(`Could not determine base commit for diff in ${worktreePath}`);
|
|
203530
|
-
return void 0;
|
|
203531
|
-
}
|
|
203532
|
-
}
|
|
203533
|
-
async function captureBaseCommitSha(store, task, worktreePath, audit, options = { isResume: false }) {
|
|
203534
|
-
try {
|
|
203535
|
-
if (options.isResume && task.baseCommitSha) {
|
|
203536
|
-
try {
|
|
203537
|
-
execSync3(`git merge-base --is-ancestor ${task.baseCommitSha} HEAD`, {
|
|
203538
|
-
cwd: worktreePath,
|
|
203539
|
-
stdio: "pipe"
|
|
203540
|
-
});
|
|
203541
|
-
executorLog.log(`${task.id}: preserved baseCommitSha ${task.baseCommitSha.slice(0, 7)} (resume)`);
|
|
203542
|
-
await audit.git({
|
|
203543
|
-
type: "commit:create",
|
|
203544
|
-
target: task.baseCommitSha,
|
|
203545
|
-
metadata: { purpose: "base", preserved: true }
|
|
203546
|
-
});
|
|
203547
|
-
return;
|
|
203548
|
-
} catch {
|
|
203549
|
-
}
|
|
203550
|
-
}
|
|
203551
|
-
const baseCommitSha = await resolveCapturedBaseCommitSha(worktreePath, {
|
|
203552
|
-
warn: (msg) => executorLog.warn(`${task.id}: ${msg}`)
|
|
203553
|
-
});
|
|
203554
|
-
if (!baseCommitSha) {
|
|
203555
|
-
throw new Error("could not resolve base commit SHA");
|
|
203556
|
-
}
|
|
203557
|
-
await store.updateTask(task.id, { baseCommitSha });
|
|
203558
|
-
executorLog.debug(`${task.id}: captured baseCommitSha ${baseCommitSha.slice(0, 7)}`);
|
|
203559
|
-
await audit.git({ type: "commit:create", target: baseCommitSha, metadata: { purpose: "base", preserved: false } });
|
|
203560
|
-
} catch (err) {
|
|
203561
|
-
const errorMessage2 = err instanceof Error ? err.message : String(err);
|
|
203562
|
-
executorLog.debug(`Failed to capture baseCommitSha for ${task.id}: ${errorMessage2}`);
|
|
203563
|
-
}
|
|
203564
|
-
}
|
|
203565
|
-
var execAsync23, execFileAsync11;
|
|
203566
|
-
var init_worktree_git_refs = __esm({
|
|
203567
|
-
"../engine/src/executor/worktree-git-refs.ts"() {
|
|
203568
|
-
"use strict";
|
|
203569
|
-
init_base_commit_capture();
|
|
203570
|
-
init_logger3();
|
|
203571
|
-
execAsync23 = promisify35(exec26);
|
|
203572
|
-
execFileAsync11 = promisify35(execFile17);
|
|
203573
|
-
}
|
|
203574
|
-
});
|
|
203575
|
-
|
|
203576
203871
|
// ../engine/src/executor/worktree-capture-modified-files.ts
|
|
203577
203872
|
import { exec as exec27 } from "node:child_process";
|
|
203578
|
-
import { promisify as
|
|
203873
|
+
import { promisify as promisify37 } from "node:util";
|
|
203579
203874
|
async function captureModifiedFiles(worktreePath, baseCommitSha, taskId, audit, source = "unspecified") {
|
|
203580
203875
|
try {
|
|
203581
203876
|
const baseRef = await resolveDiffBaseRef(worktreePath, baseCommitSha);
|
|
@@ -203661,7 +203956,7 @@ var init_worktree_capture_modified_files = __esm({
|
|
|
203661
203956
|
init_branch_attribution();
|
|
203662
203957
|
init_logger3();
|
|
203663
203958
|
init_worktree_git_refs();
|
|
203664
|
-
execAsync24 =
|
|
203959
|
+
execAsync24 = promisify37(exec27);
|
|
203665
203960
|
}
|
|
203666
203961
|
});
|
|
203667
203962
|
|
|
@@ -203826,6 +204121,27 @@ ${result2.review}`);
|
|
|
203826
204121
|
summarySections.push(`[${repoRel}] ${result2.verdict}: ${result2.summary}`);
|
|
203827
204122
|
}
|
|
203828
204123
|
const aggregateVerdict = reviewedResults.some(({ result: result2 }) => result2.verdict === "RETHINK") ? "RETHINK" : reviewedResults.some(({ result: result2 }) => result2.verdict === "REVISE") ? "REVISE" : reviewedResults.some(({ result: result2 }) => !isApprovalFamilyVerdict(result2.verdict)) ? "UNAVAILABLE" : "APPROVE";
|
|
204124
|
+
let publishedModifiedFiles = modifiedFiles;
|
|
204125
|
+
if (isApprovalFamilyVerdict(aggregateVerdict) && evidence && options.workspaceRootDir) {
|
|
204126
|
+
try {
|
|
204127
|
+
const refreshed = await captureWorkspaceReviewEvidence({ task, workspaceRootDir: options.workspaceRootDir, settings: options.settings ?? {} });
|
|
204128
|
+
if (refreshed.outOfScopeRepositories.size > 0) {
|
|
204129
|
+
return { verdict: "UNAVAILABLE", retryable: false, review: "Workspace Code Review cannot approve changes outside confirmed scope after review.", summary: "Unavailable: changes outside confirmed scope after review", repositoryScopeRevision };
|
|
204130
|
+
}
|
|
204131
|
+
for (const updated of refreshed.repositories) {
|
|
204132
|
+
const original = evidence.repositories.find((candidate) => candidate.repository === updated.repository);
|
|
204133
|
+
const worktreePath = workspaceWorktrees[updated.repository]?.worktreePath;
|
|
204134
|
+
const outcome = repositoryReviewOutcomes.find((candidate) => candidate.repository === updated.repository && candidate.status === "REVIEWED");
|
|
204135
|
+
if (!original || !worktreePath || !updated.fingerprint || !outcome || !repositoryScope.has(updated.repository)) continue;
|
|
204136
|
+
if (await isFastForwardAdvance(worktreePath, original.branch, updated.branch)) {
|
|
204137
|
+
repositoryDiffFingerprints[updated.repository] = updated.fingerprint;
|
|
204138
|
+
outcome.fingerprint = updated.fingerprint;
|
|
204139
|
+
}
|
|
204140
|
+
}
|
|
204141
|
+
publishedModifiedFiles = refreshed.modifiedFiles;
|
|
204142
|
+
} catch {
|
|
204143
|
+
}
|
|
204144
|
+
}
|
|
203829
204145
|
const blockingRepositories = reviewedResults.filter(({ result: result2 }) => !isApprovalFamilyVerdict(result2.verdict)).map(({ repository }) => repository);
|
|
203830
204146
|
const blockingSummary = blockingRepositories.length > 0 ? `blocking repositories: ${blockingRepositories.join(", ")}` : `all ${repoKeys.length} modified in-scope repositories approved`;
|
|
203831
204147
|
const coverageNotice = noVerdictRepositories.length > 0 ? `
|
|
@@ -203837,7 +204153,7 @@ Not covered by a verdict: ${noVerdictRepositories.join(", ")}.` : "";
|
|
|
203837
204153
|
${reviewSections.join("\n\n")}`,
|
|
203838
204154
|
summary: `${aggregateVerdict} \u2014 ${blockingSummary} \u2014 ${summarySections.join(" | ")}`,
|
|
203839
204155
|
repositoryDiffFingerprints,
|
|
203840
|
-
repositoryModifiedFiles:
|
|
204156
|
+
repositoryModifiedFiles: publishedModifiedFiles,
|
|
203841
204157
|
repositoryReviewOutcomes,
|
|
203842
204158
|
...findings.length > 0 ? { findings } : {},
|
|
203843
204159
|
repositoryScopeRevision
|
|
@@ -203848,6 +204164,7 @@ var init_workspace_review_per_repo = __esm({
|
|
|
203848
204164
|
"../engine/src/executor/workspace-review-per-repo.ts"() {
|
|
203849
204165
|
"use strict";
|
|
203850
204166
|
init_workspace_review_evidence();
|
|
204167
|
+
init_review_inline_fix_recapture();
|
|
203851
204168
|
init_workspace_zero_acquire();
|
|
203852
204169
|
init_worktree_capture_modified_files();
|
|
203853
204170
|
hasRepositoryPrefix = (value, repoRel, separator) => value === repoRel || value?.startsWith(`${repoRel}${separator}`) === true;
|
|
@@ -205212,6 +205529,8 @@ async function runGraphCustomNode(deps, node, nodeTask, settings, columnBinding,
|
|
|
205212
205529
|
}
|
|
205213
205530
|
const optionalGroupId = typeof graphContext?.[WORKFLOW_OPTIONAL_GROUP_CONTEXT_KEY] === "string" ? graphContext[WORKFLOW_OPTIONAL_GROUP_CONTEXT_KEY] : void 0;
|
|
205214
205531
|
const declaredReviewKind = cfg.reviewKind === "plan" || cfg.reviewKind === "code" ? cfg.reviewKind : graphContext?.[WORKFLOW_REVIEW_KIND_CONTEXT_KEY] === "plan" || graphContext?.[WORKFLOW_REVIEW_KIND_CONTEXT_KEY] === "code" ? graphContext[WORKFLOW_REVIEW_KIND_CONTEXT_KEY] : void 0;
|
|
205532
|
+
const effectiveStepId = optionalGroupId ?? node.id;
|
|
205533
|
+
const isContentBindingStep = requiresContentReviewProof(effectiveStepId, { reviewKind: declaredReviewKind });
|
|
205215
205534
|
if (isFastExecutionMode(live) && graphContext?.["workflow:fast-lane-active"] === true && isFastLaneSkippableCustomNode(node, { optionalGroupId })) {
|
|
205216
205535
|
executorLog.debug(`${live.id}: fast mode \u2014 skipping custom graph node '${node.id}'`);
|
|
205217
205536
|
await deps.store.logEntry(
|
|
@@ -205406,6 +205725,7 @@ ${prompt}`;
|
|
|
205406
205725
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
205407
205726
|
const stepSkillName = executorKind === "skill" && typeof cfg.skillName === "string" && cfg.skillName.trim() ? cfg.skillName.trim() : void 0;
|
|
205408
205727
|
const stepThinkingLevel = typeof cfg.thinkingLevel === "string" && WORKFLOW_THINKING_LEVEL_SET2.has(cfg.thinkingLevel) ? cfg.thinkingLevel : void 0;
|
|
205728
|
+
const readonlyMcpServers = Array.isArray(cfg.readonlyMcpServers) ? [...new Set(cfg.readonlyMcpServers.filter((name2) => typeof name2 === "string").map((name2) => name2.trim()).filter(Boolean))] : [];
|
|
205409
205729
|
const step = {
|
|
205410
205730
|
id: `graph:${node.id}`,
|
|
205411
205731
|
name: typeof cfg.name === "string" && cfg.name.trim() ? cfg.name : node.id,
|
|
@@ -205422,7 +205742,8 @@ ${prompt}`;
|
|
|
205422
205742
|
...stepSkillName ? { skillName: stepSkillName } : {},
|
|
205423
205743
|
...cfg.requiresBrowser === true ? { requiresBrowser: true } : {},
|
|
205424
205744
|
...modelProvider && modelId ? { modelProvider, modelId } : {},
|
|
205425
|
-
...stepThinkingLevel ? { thinkingLevel: stepThinkingLevel } : {}
|
|
205745
|
+
...stepThinkingLevel ? { thinkingLevel: stepThinkingLevel } : {},
|
|
205746
|
+
...readonlyMcpServers.length > 0 ? { readonlyMcpServers } : {}
|
|
205426
205747
|
};
|
|
205427
205748
|
if (cfg.summaryTarget === "task") {
|
|
205428
205749
|
step.summaryTarget = "task";
|
|
@@ -205536,12 +205857,36 @@ ${prompt}`;
|
|
|
205536
205857
|
outcome = buildWorkspaceReviewOutcome(aggregate, { superseded: reviewSuperseded });
|
|
205537
205858
|
}
|
|
205538
205859
|
} else {
|
|
205539
|
-
|
|
205540
|
-
|
|
205541
|
-
|
|
205542
|
-
|
|
205543
|
-
|
|
205544
|
-
|
|
205860
|
+
const dispatchSingularStep = async (reviewInputFingerprint) => {
|
|
205861
|
+
if (mode === "script") {
|
|
205862
|
+
const scriptOutcome = await deps.executeScriptWorkflowStep(live, step, worktreePath, settings, nodeEnv);
|
|
205863
|
+
return reviewInputFingerprint === void 0 ? scriptOutcome : { ...scriptOutcome, reviewInputFingerprint };
|
|
205864
|
+
}
|
|
205865
|
+
return deps.executeWorkflowStep(live, step, worktreePath, settings, nodeEnv, {
|
|
205866
|
+
unattended,
|
|
205867
|
+
principalAgentId,
|
|
205868
|
+
outputLanguage,
|
|
205869
|
+
...nodeSessionBoundary ? { sessionBoundary: nodeSessionBoundary } : {},
|
|
205870
|
+
...reviewInputFingerprint !== void 0 ? { reviewInputFingerprint } : {}
|
|
205871
|
+
});
|
|
205872
|
+
};
|
|
205873
|
+
if (isContentBindingStep && !workspaceConfig) {
|
|
205874
|
+
const proof = await resolveContentReviewInputProof(worktreePath, executionTarget.baseCommitSha);
|
|
205875
|
+
if (proof.kind === "unprovable") {
|
|
205876
|
+
const diagnostic = `${step.name} review input is unprovable (${proof.reason}); reviewer dispatch refused.`;
|
|
205877
|
+
await deps.store.logEntry(
|
|
205878
|
+
live.id,
|
|
205879
|
+
`[pre-merge] ${diagnostic}`,
|
|
205880
|
+
void 0,
|
|
205881
|
+
deps.getRunContextFor(live.id)
|
|
205882
|
+
);
|
|
205883
|
+
outcome = { success: false, error: diagnostic, failureValue: "review-input-unprovable" };
|
|
205884
|
+
} else {
|
|
205885
|
+
outcome = await dispatchSingularStep(proof.fingerprint);
|
|
205886
|
+
}
|
|
205887
|
+
} else {
|
|
205888
|
+
outcome = await dispatchSingularStep();
|
|
205889
|
+
}
|
|
205545
205890
|
}
|
|
205546
205891
|
if (declaredReviewKind && typeof outcome.output === "string") {
|
|
205547
205892
|
const rawReviewOutput = outcome.output;
|
|
@@ -205628,6 +205973,7 @@ var init_run_graph_custom_node = __esm({
|
|
|
205628
205973
|
init_create_authoritative_workflow_seams();
|
|
205629
205974
|
init_verification_gate();
|
|
205630
205975
|
init_worktree_dependency_install();
|
|
205976
|
+
init_review_diff_fingerprint();
|
|
205631
205977
|
WORKFLOW_THINKING_LEVEL_SET2 = new Set(THINKING_LEVELS);
|
|
205632
205978
|
WORKFLOW_STEP_NOT_RUN_REASON_SET2 = new Set(WORKFLOW_STEP_NOT_RUN_REASONS);
|
|
205633
205979
|
WORKSPACE_REPO_REVIEW_NO_NOTES_NOTICE = "The repository reviewer recorded no notes for this verdict.";
|
|
@@ -207687,7 +208033,7 @@ var init_agent_heartbeat_error_recovery = __esm({
|
|
|
207687
208033
|
|
|
207688
208034
|
// ../engine/src/agent-heartbeat.ts
|
|
207689
208035
|
import { Type as Type3 } from "@earendil-works/pi-ai";
|
|
207690
|
-
import { createHash as
|
|
208036
|
+
import { createHash as createHash32 } from "node:crypto";
|
|
207691
208037
|
async function resolveHeartbeatReboundColumn(taskStore, taskId) {
|
|
207692
208038
|
try {
|
|
207693
208039
|
return resolveReboundTarget(await resolveWorkflowIrForTask(taskStore, taskId)) ?? "todo";
|
|
@@ -207842,7 +208188,7 @@ function truncatePrompt(text3, maxChars) {
|
|
|
207842
208188
|
... (truncated, ${text3.length} chars)`;
|
|
207843
208189
|
}
|
|
207844
208190
|
function shortContentHash(value) {
|
|
207845
|
-
return
|
|
208191
|
+
return createHash32("sha256").update(value).digest("hex").slice(0, 8);
|
|
207846
208192
|
}
|
|
207847
208193
|
function buildIdentitySnapshot(args) {
|
|
207848
208194
|
const { agent, resolvedInstructions, workspaceMemory } = args;
|
|
@@ -212275,6 +212621,91 @@ var init_auto_merge_finalization = __esm({
|
|
|
212275
212621
|
}
|
|
212276
212622
|
});
|
|
212277
212623
|
|
|
212624
|
+
// ../engine/src/merge/merge-content-capture.ts
|
|
212625
|
+
async function captureMergeContentDescriptor(task, deps) {
|
|
212626
|
+
if (describeMergeContentShape(task) === "workspace") {
|
|
212627
|
+
try {
|
|
212628
|
+
const evidence = await captureWorkspaceReviewEvidence({
|
|
212629
|
+
task,
|
|
212630
|
+
workspaceRootDir: deps.workspaceRootDir,
|
|
212631
|
+
settings: deps.settings
|
|
212632
|
+
});
|
|
212633
|
+
return {
|
|
212634
|
+
kind: "workspace",
|
|
212635
|
+
repositories: {
|
|
212636
|
+
state: "captured",
|
|
212637
|
+
fingerprints: Object.fromEntries(evidence.repositories.filter((repository) => repository.fingerprint).map((repository) => [repository.repository, repository.fingerprint])),
|
|
212638
|
+
inScopeModified: [...evidence.modifiedRepositories].sort()
|
|
212639
|
+
}
|
|
212640
|
+
};
|
|
212641
|
+
} catch {
|
|
212642
|
+
return { kind: "workspace", repositories: { state: "unavailable", reason: "workspace-evidence-capture-failed" } };
|
|
212643
|
+
}
|
|
212644
|
+
}
|
|
212645
|
+
const baseRef = task.worktree ? await resolveDiffBaseRef(task.worktree, task.baseCommitSha) : void 0;
|
|
212646
|
+
const probe = await probeReviewDiffFingerprint(task.worktree, baseRef);
|
|
212647
|
+
return { kind: "singular", diff: probe };
|
|
212648
|
+
}
|
|
212649
|
+
var init_merge_content_capture = __esm({
|
|
212650
|
+
"../engine/src/merge/merge-content-capture.ts"() {
|
|
212651
|
+
"use strict";
|
|
212652
|
+
init_src2();
|
|
212653
|
+
init_worktree_git_refs();
|
|
212654
|
+
init_review_diff_fingerprint();
|
|
212655
|
+
init_workspace_review_evidence();
|
|
212656
|
+
}
|
|
212657
|
+
});
|
|
212658
|
+
|
|
212659
|
+
// ../engine/src/merge/stale-content-review-reroute.ts
|
|
212660
|
+
function isContentReviewNode(node) {
|
|
212661
|
+
if (node.kind !== "optional-group" && node.kind !== "step-review") return false;
|
|
212662
|
+
const name2 = typeof node.config?.name === "string" ? node.config.name : "";
|
|
212663
|
+
return node.id === "code-review" || node.config?.reviewKind === "code" || /code review/i.test(name2);
|
|
212664
|
+
}
|
|
212665
|
+
async function rerouteSingularStaleContentToReview(store, task, options) {
|
|
212666
|
+
const mergeContent = options.mergeContent;
|
|
212667
|
+
if (mergeContent.kind !== "singular" || task.workspaceWorktrees !== void 0) {
|
|
212668
|
+
return { rerouted: false, reason: "not-singular" };
|
|
212669
|
+
}
|
|
212670
|
+
if (task.paused || task.userPaused || task.deletedAt || task.autoMerge === false) {
|
|
212671
|
+
return { rerouted: false, reason: "operator-held" };
|
|
212672
|
+
}
|
|
212673
|
+
if (mergeContent.diff.state !== "fingerprint") return { rerouted: false, reason: "no-progress" };
|
|
212674
|
+
const currentFingerprint = mergeContent.diff.fingerprint;
|
|
212675
|
+
const ir2 = await resolveWorkflowIrForTask(store, task.id);
|
|
212676
|
+
const selection = store.getTaskWorkflowSelectionAsync ? await store.getTaskWorkflowSelectionAsync(task.id) : store.getTaskWorkflowSelection(task.id);
|
|
212677
|
+
const selected = selection?.stepIds ?? [];
|
|
212678
|
+
const nodes2 = ir2.nodes.filter((node2) => {
|
|
212679
|
+
if (!isContentReviewNode(node2) || !options.requiredPreMergeStepIds.has(node2.id)) return false;
|
|
212680
|
+
return node2.config?.defaultOn === true || selected.includes(node2.id);
|
|
212681
|
+
});
|
|
212682
|
+
const node = nodes2.find((candidate) => {
|
|
212683
|
+
const latest = task.workflowStepResults?.filter((result3) => result3.workflowStepId === candidate.id).at(-1);
|
|
212684
|
+
return latest?.reviewInputFingerprint !== currentFingerprint;
|
|
212685
|
+
});
|
|
212686
|
+
if (!node) return { rerouted: false, reason: nodes2.length ? "no-progress" : "no-review-route" };
|
|
212687
|
+
const items = await store.listWorkflowWorkItemsForTask(task.id);
|
|
212688
|
+
const result2 = await store.seedWorkspaceCodeReviewContinuationIfIdle({
|
|
212689
|
+
taskId: task.id,
|
|
212690
|
+
nodeId: node.id,
|
|
212691
|
+
kind: "task",
|
|
212692
|
+
state: "runnable",
|
|
212693
|
+
runId: `${task.id}:stale-content-review-reroute:${node.id}:${items.length}`,
|
|
212694
|
+
stableWorkflowRunId: `${task.id}:${ir2.name}`,
|
|
212695
|
+
continuationSequence: items.length,
|
|
212696
|
+
sourceColumn: task.column,
|
|
212697
|
+
targetColumn: node.column ?? task.column,
|
|
212698
|
+
irHash: computeWorkflowIrPin(ir2, node.id).irHash
|
|
212699
|
+
});
|
|
212700
|
+
return result2.seeded ? { rerouted: true, reason: "seeded", nodeId: node.id, workflowStepId: node.id } : { rerouted: false, reason: "active-continuation", nodeId: node.id, workflowStepId: node.id };
|
|
212701
|
+
}
|
|
212702
|
+
var init_stale_content_review_reroute = __esm({
|
|
212703
|
+
"../engine/src/merge/stale-content-review-reroute.ts"() {
|
|
212704
|
+
"use strict";
|
|
212705
|
+
init_src2();
|
|
212706
|
+
}
|
|
212707
|
+
});
|
|
212708
|
+
|
|
212278
212709
|
// ../engine/src/healing/auto-recovery.ts
|
|
212279
212710
|
function actionForMode(mode, failureClass) {
|
|
212280
212711
|
if (mode === "off") return "pause";
|
|
@@ -212431,10 +212862,10 @@ var init_stranded_continuation_reclaim = __esm({
|
|
|
212431
212862
|
});
|
|
212432
212863
|
|
|
212433
212864
|
// ../engine/src/merge/workspace-land-predicate.ts
|
|
212434
|
-
import { execFile as
|
|
212435
|
-
import { promisify as
|
|
212865
|
+
import { execFile as execFile19 } from "node:child_process";
|
|
212866
|
+
import { promisify as promisify38 } from "node:util";
|
|
212436
212867
|
async function git4(args, cwd, opts = {}) {
|
|
212437
|
-
const { stdout } = await
|
|
212868
|
+
const { stdout } = await execFileAsync13("git", args, {
|
|
212438
212869
|
cwd,
|
|
212439
212870
|
encoding: "utf-8",
|
|
212440
212871
|
timeout: opts.timeout ?? 12e4,
|
|
@@ -212513,11 +212944,11 @@ async function isRepoLanded(repoRootDir, integrationBranch, landedSha, taskId, b
|
|
|
212513
212944
|
await findProvenLandedCommit(repoRootDir, integrationBranch, landedSha, taskId, branch, revertBoundarySha, taskCreatedAt)
|
|
212514
212945
|
);
|
|
212515
212946
|
}
|
|
212516
|
-
var
|
|
212947
|
+
var execFileAsync13, FUSION_TASK_ID_TRAILER_KEY2, TRAILER_SCAN_CLOCK_SKEW_MS, UNBOUNDED_TRAILER_SCAN_WINDOW_MS, UNBOUNDED_TRAILER_SCAN_MAX_COMMITS;
|
|
212517
212948
|
var init_workspace_land_predicate = __esm({
|
|
212518
212949
|
"../engine/src/merge/workspace-land-predicate.ts"() {
|
|
212519
212950
|
"use strict";
|
|
212520
|
-
|
|
212951
|
+
execFileAsync13 = promisify38(execFile19);
|
|
212521
212952
|
FUSION_TASK_ID_TRAILER_KEY2 = "Fusion-Task-Id";
|
|
212522
212953
|
TRAILER_SCAN_CLOCK_SKEW_MS = 24 * 60 * 60 * 1e3;
|
|
212523
212954
|
UNBOUNDED_TRAILER_SCAN_WINDOW_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
@@ -212542,7 +212973,7 @@ var init_workspace_land_failure = __esm({
|
|
|
212542
212973
|
|
|
212543
212974
|
// ../engine/src/merge/already-merged-detector.ts
|
|
212544
212975
|
import { exec as exec28, execSync as execSync4 } from "node:child_process";
|
|
212545
|
-
import { promisify as
|
|
212976
|
+
import { promisify as promisify39 } from "node:util";
|
|
212546
212977
|
function shellQuote(value) {
|
|
212547
212978
|
return `'${value.replace(/'/g, "'\\''")}'`;
|
|
212548
212979
|
}
|
|
@@ -212818,7 +213249,7 @@ var init_already_merged_detector = __esm({
|
|
|
212818
213249
|
"../engine/src/merge/already-merged-detector.ts"() {
|
|
212819
213250
|
"use strict";
|
|
212820
213251
|
init_worktree_names();
|
|
212821
|
-
execAsync25 =
|
|
213252
|
+
execAsync25 = promisify39(exec28);
|
|
212822
213253
|
}
|
|
212823
213254
|
});
|
|
212824
213255
|
|
|
@@ -212950,10 +213381,10 @@ var init_review_empty_content_close = __esm({
|
|
|
212950
213381
|
});
|
|
212951
213382
|
|
|
212952
213383
|
// ../engine/src/merge/merger-ref-update-advance.ts
|
|
212953
|
-
import { execFile as
|
|
212954
|
-
import { promisify as
|
|
213384
|
+
import { execFile as execFile20 } from "node:child_process";
|
|
213385
|
+
import { promisify as promisify40 } from "node:util";
|
|
212955
213386
|
async function runGit3(args, cwd) {
|
|
212956
|
-
return await
|
|
213387
|
+
return await execFileAsync14("git", args, {
|
|
212957
213388
|
cwd,
|
|
212958
213389
|
encoding: "utf-8",
|
|
212959
213390
|
timeout: 3e4
|
|
@@ -213100,11 +213531,11 @@ async function advanceIntegrationBranchRef(args) {
|
|
|
213100
213531
|
};
|
|
213101
213532
|
}
|
|
213102
213533
|
}
|
|
213103
|
-
var
|
|
213534
|
+
var execFileAsync14, testHooks, IntegrationBranchConcurrentAdvanceError;
|
|
213104
213535
|
var init_merger_ref_update_advance = __esm({
|
|
213105
213536
|
"../engine/src/merge/merger-ref-update-advance.ts"() {
|
|
213106
213537
|
"use strict";
|
|
213107
|
-
|
|
213538
|
+
execFileAsync14 = promisify40(execFile20);
|
|
213108
213539
|
testHooks = {
|
|
213109
213540
|
runGit: runGit3
|
|
213110
213541
|
};
|
|
@@ -213132,7 +213563,7 @@ var init_merger_ref_update_advance = __esm({
|
|
|
213132
213563
|
|
|
213133
213564
|
// ../engine/src/merge/group-merge-coordinator.ts
|
|
213134
213565
|
import * as childProcess2 from "node:child_process";
|
|
213135
|
-
import { promisify as
|
|
213566
|
+
import { promisify as promisify41 } from "node:util";
|
|
213136
213567
|
function evaluateBranchGroupCompletion(input) {
|
|
213137
213568
|
const landedMemberIds = [];
|
|
213138
213569
|
const pendingMemberIds = [];
|
|
@@ -213172,10 +213603,10 @@ function evaluateBranchGroupPromotion(input) {
|
|
|
213172
213603
|
}
|
|
213173
213604
|
async function ensureGroupBranchExists(rootDir, branchName, startPoint) {
|
|
213174
213605
|
try {
|
|
213175
|
-
await
|
|
213606
|
+
await execFileAsync15("git", ["show-ref", "--verify", "--quiet", `refs/heads/${branchName}`], { cwd: rootDir });
|
|
213176
213607
|
return;
|
|
213177
213608
|
} catch {
|
|
213178
|
-
await
|
|
213609
|
+
await execFileAsync15("git", ["branch", branchName, startPoint], { cwd: rootDir });
|
|
213179
213610
|
}
|
|
213180
213611
|
}
|
|
213181
213612
|
function throwIfPromotionAborted(signal) {
|
|
@@ -213280,14 +213711,14 @@ async function promoteBranchGroupInner(input) {
|
|
|
213280
213711
|
if (!needsPrRepair && !isPrMode) {
|
|
213281
213712
|
throwIfPromotionAborted(input.signal);
|
|
213282
213713
|
await ensureGroupBranchExists(input.rootDir, group.branchName, integrationBranch);
|
|
213283
|
-
const currentBranch2 = (await
|
|
213714
|
+
const currentBranch2 = (await execFileAsync15("git", ["rev-parse", "--abbrev-ref", "HEAD"], { cwd: input.rootDir })).stdout.trim();
|
|
213284
213715
|
try {
|
|
213285
213716
|
throwIfPromotionAborted(input.signal);
|
|
213286
|
-
await
|
|
213717
|
+
await execFileAsync15("git", ["checkout", integrationBranch], { cwd: input.rootDir, signal: input.signal });
|
|
213287
213718
|
throwIfPromotionAborted(input.signal);
|
|
213288
|
-
await
|
|
213719
|
+
await execFileAsync15("git", ["merge", "--no-ff", "--no-edit", group.branchName], { cwd: input.rootDir, signal: input.signal });
|
|
213289
213720
|
} finally {
|
|
213290
|
-
await
|
|
213721
|
+
await execFileAsync15("git", ["checkout", currentBranch2], { cwd: input.rootDir });
|
|
213291
213722
|
}
|
|
213292
213723
|
}
|
|
213293
213724
|
let prNumber = group.prNumber;
|
|
@@ -213411,20 +213842,20 @@ async function resolveBranchGroupMergeRouting(input) {
|
|
|
213411
213842
|
)
|
|
213412
213843
|
};
|
|
213413
213844
|
}
|
|
213414
|
-
var
|
|
213845
|
+
var execFileAsync15, promotionLocks;
|
|
213415
213846
|
var init_group_merge_coordinator = __esm({
|
|
213416
213847
|
"../engine/src/merge/group-merge-coordinator.ts"() {
|
|
213417
213848
|
"use strict";
|
|
213418
213849
|
init_src2();
|
|
213419
213850
|
init_integration_branch();
|
|
213420
|
-
|
|
213851
|
+
execFileAsync15 = (file, args, opts) => promisify41(childProcess2.execFile)(file, args, opts);
|
|
213421
213852
|
promotionLocks = /* @__PURE__ */ new Map();
|
|
213422
213853
|
}
|
|
213423
213854
|
});
|
|
213424
213855
|
|
|
213425
213856
|
// ../engine/src/merge/merger-bare-subject.ts
|
|
213426
213857
|
import { exec as exec29 } from "node:child_process";
|
|
213427
|
-
import { promisify as
|
|
213858
|
+
import { promisify as promisify42 } from "node:util";
|
|
213428
213859
|
function quoteArg(value) {
|
|
213429
213860
|
return `'${value.replace(/'/g, "'\\''")}'`;
|
|
213430
213861
|
}
|
|
@@ -213464,7 +213895,7 @@ var init_merger_bare_subject = __esm({
|
|
|
213464
213895
|
"use strict";
|
|
213465
213896
|
init_src2();
|
|
213466
213897
|
init_logger3();
|
|
213467
|
-
execAsync26 =
|
|
213898
|
+
execAsync26 = promisify42(exec29);
|
|
213468
213899
|
BARE_MERGE_SUBJECT_RE = /^[a-z]+(?:\([^)]+\))?!?:\s*merge\s+\S+\s*$/i;
|
|
213469
213900
|
}
|
|
213470
213901
|
});
|
|
@@ -213472,7 +213903,7 @@ var init_merger_bare_subject = __esm({
|
|
|
213472
213903
|
// ../engine/src/recovery/foreign-only-contamination.ts
|
|
213473
213904
|
import { exec as exec30 } from "node:child_process";
|
|
213474
213905
|
import { existsSync as existsSync62 } from "node:fs";
|
|
213475
|
-
import { promisify as
|
|
213906
|
+
import { promisify as promisify43 } from "node:util";
|
|
213476
213907
|
function quote3(value) {
|
|
213477
213908
|
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
213478
213909
|
}
|
|
@@ -213580,7 +214011,7 @@ var init_foreign_only_contamination = __esm({
|
|
|
213580
214011
|
init_lifecycle_move();
|
|
213581
214012
|
init_branch_conflicts();
|
|
213582
214013
|
init_worktree_pool();
|
|
213583
|
-
execAsync27 =
|
|
214014
|
+
execAsync27 = promisify43(exec30);
|
|
213584
214015
|
GIT_TIMEOUT_MS6 = 3e4;
|
|
213585
214016
|
GIT_MAX_BUFFER3 = 10 * 1024 * 1024;
|
|
213586
214017
|
}
|
|
@@ -213677,7 +214108,7 @@ var init_surfacing_sweeps = __esm({
|
|
|
213677
214108
|
});
|
|
213678
214109
|
|
|
213679
214110
|
// ../engine/src/self-healing-git-evidence.ts
|
|
213680
|
-
import { promisify as
|
|
214111
|
+
import { promisify as promisify44 } from "node:util";
|
|
213681
214112
|
import { exec as exec31 } from "node:child_process";
|
|
213682
214113
|
function classifyBranchProbeError(error3) {
|
|
213683
214114
|
if (typeof error3 === "object" && error3 !== null && "code" in error3 && error3.code === 1 && !error3.killed && (error3.signal === null || error3.signal === void 0)) {
|
|
@@ -213721,7 +214152,7 @@ var init_self_healing_git_evidence = __esm({
|
|
|
213721
214152
|
init_already_merged_detector();
|
|
213722
214153
|
init_logger3();
|
|
213723
214154
|
log32 = createLogger2("self-healing");
|
|
213724
|
-
execAsync28 =
|
|
214155
|
+
execAsync28 = promisify44(exec31);
|
|
213725
214156
|
SelfHealingGitEvidence = class {
|
|
213726
214157
|
async findLandedTaskCommit(task, options) {
|
|
213727
214158
|
const rebaseBaseSha = task.mergeDetails?.rebaseBaseSha;
|
|
@@ -214083,12 +214514,12 @@ var init_self_healing_constants = __esm({
|
|
|
214083
214514
|
});
|
|
214084
214515
|
|
|
214085
214516
|
// ../engine/src/healing/self-healing-branch.ts
|
|
214086
|
-
import { promisify as
|
|
214087
|
-
import { execFile as
|
|
214517
|
+
import { promisify as promisify45 } from "node:util";
|
|
214518
|
+
import { execFile as execFile22 } from "node:child_process";
|
|
214088
214519
|
async function isBranchAheadOfBase(task, rootDir, preferredBaseRef) {
|
|
214089
214520
|
const branchName = resolveTaskWorkingBranch(task);
|
|
214090
214521
|
try {
|
|
214091
|
-
await
|
|
214522
|
+
await execFileAsync16("git", ["rev-parse", "--verify", branchName], {
|
|
214092
214523
|
cwd: rootDir,
|
|
214093
214524
|
timeout: 3e4
|
|
214094
214525
|
});
|
|
@@ -214098,14 +214529,14 @@ async function isBranchAheadOfBase(task, rootDir, preferredBaseRef) {
|
|
|
214098
214529
|
const requestedBaseRef = preferredBaseRef || task.mergeDetails?.mergeTargetBranch || await resolveIntegrationBranch(rootDir, void 0);
|
|
214099
214530
|
let resolvedBaseRef = requestedBaseRef;
|
|
214100
214531
|
try {
|
|
214101
|
-
await
|
|
214532
|
+
await execFileAsync16("git", ["rev-parse", "--verify", requestedBaseRef], {
|
|
214102
214533
|
cwd: rootDir,
|
|
214103
214534
|
timeout: 3e4
|
|
214104
214535
|
});
|
|
214105
214536
|
} catch {
|
|
214106
214537
|
const remoteRef = `origin/${requestedBaseRef}`;
|
|
214107
214538
|
try {
|
|
214108
|
-
await
|
|
214539
|
+
await execFileAsync16("git", ["rev-parse", "--verify", remoteRef], {
|
|
214109
214540
|
cwd: rootDir,
|
|
214110
214541
|
timeout: 3e4
|
|
214111
214542
|
});
|
|
@@ -214115,7 +214546,7 @@ async function isBranchAheadOfBase(task, rootDir, preferredBaseRef) {
|
|
|
214115
214546
|
}
|
|
214116
214547
|
}
|
|
214117
214548
|
try {
|
|
214118
|
-
const { stdout } = await
|
|
214549
|
+
const { stdout } = await execFileAsync16(
|
|
214119
214550
|
"git",
|
|
214120
214551
|
["rev-list", "--count", `${resolvedBaseRef}..${branchName}`],
|
|
214121
214552
|
{ cwd: rootDir, timeout: 3e4 }
|
|
@@ -214133,7 +214564,7 @@ async function isBranchAheadOfBase(task, rootDir, preferredBaseRef) {
|
|
|
214133
214564
|
return null;
|
|
214134
214565
|
}
|
|
214135
214566
|
}
|
|
214136
|
-
var log33,
|
|
214567
|
+
var log33, execFileAsync16;
|
|
214137
214568
|
var init_self_healing_branch = __esm({
|
|
214138
214569
|
"../engine/src/healing/self-healing-branch.ts"() {
|
|
214139
214570
|
"use strict";
|
|
@@ -214141,7 +214572,7 @@ var init_self_healing_branch = __esm({
|
|
|
214141
214572
|
init_integration_branch();
|
|
214142
214573
|
init_logger3();
|
|
214143
214574
|
log33 = createLogger2("self-healing");
|
|
214144
|
-
|
|
214575
|
+
execFileAsync16 = promisify45(execFile22);
|
|
214145
214576
|
}
|
|
214146
214577
|
});
|
|
214147
214578
|
|
|
@@ -214978,7 +215409,7 @@ var init_merger_workspace_test_commands = __esm({
|
|
|
214978
215409
|
});
|
|
214979
215410
|
|
|
214980
215411
|
// ../engine/src/merge/merger-file-scope.ts
|
|
214981
|
-
import { promisify as
|
|
215412
|
+
import { promisify as promisify46 } from "node:util";
|
|
214982
215413
|
import { exec as exec32 } from "node:child_process";
|
|
214983
215414
|
function parseDiffStat(diffStat) {
|
|
214984
215415
|
const entries = [];
|
|
@@ -215190,7 +215621,7 @@ var init_merger_file_scope = __esm({
|
|
|
215190
215621
|
init_merger_glob();
|
|
215191
215622
|
init_logger3();
|
|
215192
215623
|
init_merge_trait();
|
|
215193
|
-
execAsync29 =
|
|
215624
|
+
execAsync29 = promisify46(exec32);
|
|
215194
215625
|
FileScopeViolationError = class extends Error {
|
|
215195
215626
|
taskId;
|
|
215196
215627
|
stagedFiles;
|
|
@@ -215250,7 +215681,7 @@ var init_merger_errors = __esm({
|
|
|
215250
215681
|
});
|
|
215251
215682
|
|
|
215252
215683
|
// ../engine/src/merge/merger-owned-landed.ts
|
|
215253
|
-
import { promisify as
|
|
215684
|
+
import { promisify as promisify47 } from "node:util";
|
|
215254
215685
|
import * as childProcess3 from "node:child_process";
|
|
215255
215686
|
function escapeRegexForOwnership(value) {
|
|
215256
215687
|
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
@@ -215267,8 +215698,8 @@ function commitOwnedByTask2(taskId, subject, body) {
|
|
|
215267
215698
|
async function findOwnedLandedCommitForTask(rootDir, task) {
|
|
215268
215699
|
const tryHydrate = async (sha) => {
|
|
215269
215700
|
try {
|
|
215270
|
-
await
|
|
215271
|
-
const { stdout } = await
|
|
215701
|
+
await execFileAsync17("git", ["merge-base", "--is-ancestor", sha, "HEAD"], { cwd: rootDir });
|
|
215702
|
+
const { stdout } = await execFileAsync17("git", ["log", "-1", "--format=%H%x1f%s%x1f%b", sha], {
|
|
215272
215703
|
cwd: rootDir,
|
|
215273
215704
|
encoding: "utf-8"
|
|
215274
215705
|
});
|
|
@@ -215276,7 +215707,7 @@ async function findOwnedLandedCommitForTask(rootDir, task) {
|
|
|
215276
215707
|
if (!resolvedSha || !commitOwnedByTask2(task.id, subject, body)) return null;
|
|
215277
215708
|
const owned = { sha: resolvedSha, subject };
|
|
215278
215709
|
try {
|
|
215279
|
-
const { stdout: statsOut } = await
|
|
215710
|
+
const { stdout: statsOut } = await execFileAsync17("git", ["show", "--shortstat", "--format=", resolvedSha], {
|
|
215280
215711
|
cwd: rootDir,
|
|
215281
215712
|
encoding: "utf-8"
|
|
215282
215713
|
});
|
|
@@ -215299,7 +215730,7 @@ async function findOwnedLandedCommitForTask(rootDir, task) {
|
|
|
215299
215730
|
];
|
|
215300
215731
|
for (const args of searches) {
|
|
215301
215732
|
try {
|
|
215302
|
-
const { stdout } = await
|
|
215733
|
+
const { stdout } = await execFileAsync17("git", args, { cwd: rootDir, encoding: "utf-8" });
|
|
215303
215734
|
const first = stdout.trim().split("\n").find(Boolean);
|
|
215304
215735
|
if (!first) continue;
|
|
215305
215736
|
const [sha] = first.split("");
|
|
@@ -215320,14 +215751,14 @@ async function classifyOwnedLandedEvidence(rootDir, task, opts) {
|
|
|
215320
215751
|
const ownedCommit = await findOwnedLandedCommitForTask(rootDir, task);
|
|
215321
215752
|
if (ownedCommit) {
|
|
215322
215753
|
try {
|
|
215323
|
-
await
|
|
215754
|
+
await execFileAsync17("git", ["merge-base", "--is-ancestor", ownedCommit.sha, mergeTargetBranch], { cwd: rootDir });
|
|
215324
215755
|
return { kind: "owned-commit", commit: ownedCommit };
|
|
215325
215756
|
} catch {
|
|
215326
215757
|
}
|
|
215327
215758
|
}
|
|
215328
215759
|
let aheadCount = null;
|
|
215329
215760
|
try {
|
|
215330
|
-
const { stdout } = await
|
|
215761
|
+
const { stdout } = await execFileAsync17("git", ["rev-list", "--count", `${mergeTargetBranch}..${branch}`], {
|
|
215331
215762
|
cwd: rootDir,
|
|
215332
215763
|
encoding: "utf-8"
|
|
215333
215764
|
});
|
|
@@ -215339,7 +215770,7 @@ async function classifyOwnedLandedEvidence(rootDir, task, opts) {
|
|
|
215339
215770
|
let baseReachableFromTarget = false;
|
|
215340
215771
|
if (task.baseCommitSha) {
|
|
215341
215772
|
try {
|
|
215342
|
-
await
|
|
215773
|
+
await execFileAsync17("git", ["merge-base", "--is-ancestor", task.baseCommitSha, mergeTargetBranch], { cwd: rootDir });
|
|
215343
215774
|
baseReachableFromTarget = true;
|
|
215344
215775
|
} catch {
|
|
215345
215776
|
baseReachableFromTarget = false;
|
|
@@ -215350,7 +215781,7 @@ async function classifyOwnedLandedEvidence(rootDir, task, opts) {
|
|
|
215350
215781
|
}
|
|
215351
215782
|
if (aheadCount !== null && aheadCount > 0) {
|
|
215352
215783
|
try {
|
|
215353
|
-
const { stdout: mergeBaseOut } = await
|
|
215784
|
+
const { stdout: mergeBaseOut } = await execFileAsync17(
|
|
215354
215785
|
"git",
|
|
215355
215786
|
["merge-base", mergeTargetBranch, branch],
|
|
215356
215787
|
{ cwd: rootDir, encoding: "utf-8" }
|
|
@@ -215359,7 +215790,7 @@ async function classifyOwnedLandedEvidence(rootDir, task, opts) {
|
|
|
215359
215790
|
if (mergeBase) {
|
|
215360
215791
|
let ownDiffEmpty = false;
|
|
215361
215792
|
try {
|
|
215362
|
-
await
|
|
215793
|
+
await execFileAsync17(
|
|
215363
215794
|
"git",
|
|
215364
215795
|
["diff", "--quiet", `${mergeBase}..${branch}`],
|
|
215365
215796
|
{ cwd: rootDir }
|
|
@@ -215372,7 +215803,7 @@ async function classifyOwnedLandedEvidence(rootDir, task, opts) {
|
|
|
215372
215803
|
let mergeBaseReachable = baseReachableFromTarget;
|
|
215373
215804
|
if (!mergeBaseReachable) {
|
|
215374
215805
|
try {
|
|
215375
|
-
await
|
|
215806
|
+
await execFileAsync17(
|
|
215376
215807
|
"git",
|
|
215377
215808
|
["merge-base", "--is-ancestor", mergeBase, mergeTargetBranch],
|
|
215378
215809
|
{ cwd: rootDir }
|
|
@@ -215392,7 +215823,7 @@ async function classifyOwnedLandedEvidence(rootDir, task, opts) {
|
|
|
215392
215823
|
}
|
|
215393
215824
|
let branchExists = false;
|
|
215394
215825
|
try {
|
|
215395
|
-
await
|
|
215826
|
+
await execFileAsync17("git", ["show-ref", "--verify", "--quiet", `refs/heads/${branch}`], { cwd: rootDir });
|
|
215396
215827
|
branchExists = true;
|
|
215397
215828
|
} catch {
|
|
215398
215829
|
branchExists = false;
|
|
@@ -215410,7 +215841,7 @@ async function classifyOwnedLandedEvidence(rootDir, task, opts) {
|
|
|
215410
215841
|
}
|
|
215411
215842
|
if (task.baseCommitSha && !baseReachableFromTarget) {
|
|
215412
215843
|
try {
|
|
215413
|
-
const { stdout } = await
|
|
215844
|
+
const { stdout } = await execFileAsync17("git", ["for-each-ref", "--format=%(refname:short)", "refs/heads/fusion"], {
|
|
215414
215845
|
cwd: rootDir,
|
|
215415
215846
|
encoding: "utf-8"
|
|
215416
215847
|
});
|
|
@@ -215418,7 +215849,7 @@ async function classifyOwnedLandedEvidence(rootDir, task, opts) {
|
|
|
215418
215849
|
for (const ref of refs) {
|
|
215419
215850
|
if (ref === branch) continue;
|
|
215420
215851
|
try {
|
|
215421
|
-
await
|
|
215852
|
+
await execFileAsync17("git", ["merge-base", "--is-ancestor", task.baseCommitSha, ref], { cwd: rootDir });
|
|
215422
215853
|
return {
|
|
215423
215854
|
kind: "unproven",
|
|
215424
215855
|
reason: "foreign-start-point",
|
|
@@ -215432,7 +215863,7 @@ async function classifyOwnedLandedEvidence(rootDir, task, opts) {
|
|
|
215432
215863
|
}
|
|
215433
215864
|
if (aheadCount !== null && aheadCount > 0) {
|
|
215434
215865
|
try {
|
|
215435
|
-
const { stdout } = await
|
|
215866
|
+
const { stdout } = await execFileAsync17("git", ["log", "--format=%s%x1f%b", `${mergeTargetBranch}..${branch}`], {
|
|
215436
215867
|
cwd: rootDir,
|
|
215437
215868
|
encoding: "utf-8"
|
|
215438
215869
|
});
|
|
@@ -215473,20 +215904,20 @@ async function classifyOwnedLandedEvidence(rootDir, task, opts) {
|
|
|
215473
215904
|
}
|
|
215474
215905
|
};
|
|
215475
215906
|
}
|
|
215476
|
-
var
|
|
215907
|
+
var execFileAsync17, FUSION_TASK_ID_TRAILER_KEY3;
|
|
215477
215908
|
var init_merger_owned_landed = __esm({
|
|
215478
215909
|
"../engine/src/merge/merger-owned-landed.ts"() {
|
|
215479
215910
|
"use strict";
|
|
215480
215911
|
init_merger_file_scope();
|
|
215481
215912
|
init_worktree_names();
|
|
215482
|
-
|
|
215913
|
+
execFileAsync17 = (file, args, opts) => promisify47(childProcess3.execFile)(file, args, opts);
|
|
215483
215914
|
FUSION_TASK_ID_TRAILER_KEY3 = "Fusion-Task-Id";
|
|
215484
215915
|
}
|
|
215485
215916
|
});
|
|
215486
215917
|
|
|
215487
215918
|
// ../engine/src/merge/merger-conflict-resolution.ts
|
|
215488
|
-
import { promisify as
|
|
215489
|
-
import { exec as exec33, execFile as
|
|
215919
|
+
import { promisify as promisify48 } from "node:util";
|
|
215920
|
+
import { exec as exec33, execFile as execFile24 } from "node:child_process";
|
|
215490
215921
|
async function getConflictedFiles(cwd) {
|
|
215491
215922
|
try {
|
|
215492
215923
|
const { stdout } = await execAsync30("git diff --name-only --diff-filter=U", {
|
|
@@ -215502,7 +215933,7 @@ async function getConflictedFiles(cwd) {
|
|
|
215502
215933
|
}
|
|
215503
215934
|
async function isTrivialWhitespaceConflict(filePath, cwd) {
|
|
215504
215935
|
try {
|
|
215505
|
-
const { stdout } = await
|
|
215936
|
+
const { stdout } = await execFileAsync18(
|
|
215506
215937
|
"git",
|
|
215507
215938
|
["diff", "-p", "-w", `:2:${filePath}`, `:3:${filePath}`],
|
|
215508
215939
|
{ cwd, encoding: "utf-8" }
|
|
@@ -215538,8 +215969,8 @@ async function classifyConflict(filePath, cwd) {
|
|
|
215538
215969
|
}
|
|
215539
215970
|
async function resolveWithOurs(filePath, cwd) {
|
|
215540
215971
|
try {
|
|
215541
|
-
await
|
|
215542
|
-
await
|
|
215972
|
+
await execFileAsync18("git", ["checkout", "--ours", "--", filePath], { cwd });
|
|
215973
|
+
await execFileAsync18("git", ["add", "--", filePath], { cwd });
|
|
215543
215974
|
mergerLog.debug(`Auto-resolved ${filePath} using --ours`);
|
|
215544
215975
|
} catch (error3) {
|
|
215545
215976
|
throw new Error(`Failed to auto-resolve ${filePath} with ours: ${error3}`);
|
|
@@ -215547,8 +215978,8 @@ async function resolveWithOurs(filePath, cwd) {
|
|
|
215547
215978
|
}
|
|
215548
215979
|
async function resolveWithTheirs(filePath, cwd) {
|
|
215549
215980
|
try {
|
|
215550
|
-
await
|
|
215551
|
-
await
|
|
215981
|
+
await execFileAsync18("git", ["checkout", "--theirs", "--", filePath], { cwd });
|
|
215982
|
+
await execFileAsync18("git", ["add", "--", filePath], { cwd });
|
|
215552
215983
|
mergerLog.debug(`Auto-resolved ${filePath} using --theirs`);
|
|
215553
215984
|
} catch (error3) {
|
|
215554
215985
|
throw new Error(`Failed to auto-resolve ${filePath} with theirs: ${error3}`);
|
|
@@ -215556,8 +215987,8 @@ async function resolveWithTheirs(filePath, cwd) {
|
|
|
215556
215987
|
}
|
|
215557
215988
|
async function resolveTrivialWhitespace(filePath, cwd) {
|
|
215558
215989
|
try {
|
|
215559
|
-
await
|
|
215560
|
-
await
|
|
215990
|
+
await execFileAsync18("git", ["checkout", "--ours", "--", filePath], { cwd });
|
|
215991
|
+
await execFileAsync18("git", ["add", "--", filePath], { cwd });
|
|
215561
215992
|
mergerLog.debug(`Auto-resolved ${filePath} (trivial whitespace)`);
|
|
215562
215993
|
} catch (error3) {
|
|
215563
215994
|
throw new Error(`Failed to auto-resolve ${filePath} trivial conflict: ${error3}`);
|
|
@@ -215603,14 +216034,14 @@ async function resolveConflicts(categories2, rootDir) {
|
|
|
215603
216034
|
}
|
|
215604
216035
|
return remainingComplex;
|
|
215605
216036
|
}
|
|
215606
|
-
var execAsync30,
|
|
216037
|
+
var execAsync30, execFileAsync18;
|
|
215607
216038
|
var init_merger_conflict_resolution = __esm({
|
|
215608
216039
|
"../engine/src/merge/merger-conflict-resolution.ts"() {
|
|
215609
216040
|
"use strict";
|
|
215610
216041
|
init_merger_glob();
|
|
215611
216042
|
init_logger3();
|
|
215612
|
-
execAsync30 =
|
|
215613
|
-
|
|
216043
|
+
execAsync30 = promisify48(exec33);
|
|
216044
|
+
execFileAsync18 = (file, args, opts) => promisify48(execFile24)(file, args, opts);
|
|
215614
216045
|
}
|
|
215615
216046
|
});
|
|
215616
216047
|
|
|
@@ -215734,8 +216165,8 @@ var init_merger_autostash_labels = __esm({
|
|
|
215734
216165
|
});
|
|
215735
216166
|
|
|
215736
216167
|
// ../engine/src/merge/merger-squash-audit.ts
|
|
215737
|
-
import { execFile as
|
|
215738
|
-
import { promisify as
|
|
216168
|
+
import { execFile as execFile25 } from "node:child_process";
|
|
216169
|
+
import { promisify as promisify49 } from "node:util";
|
|
215739
216170
|
async function auditSquashMerge(input) {
|
|
215740
216171
|
const normalizedLookback = normalizeMergeOverlapLookback(input.lookback);
|
|
215741
216172
|
if (input.strategy === "rebase") {
|
|
@@ -215853,7 +216284,7 @@ async function collectTouchedFileOverlaps(rootDir, touchedFiles, recentMainCommi
|
|
|
215853
216284
|
return touchedFileOverlaps;
|
|
215854
216285
|
}
|
|
215855
216286
|
async function git5(rootDir, args) {
|
|
215856
|
-
const { stdout } = await
|
|
216287
|
+
const { stdout } = await execFileAsync19("git", args, {
|
|
215857
216288
|
cwd: rootDir,
|
|
215858
216289
|
encoding: "utf-8",
|
|
215859
216290
|
maxBuffer: GIT_OUTPUT_MAX_BUFFER
|
|
@@ -215886,19 +216317,19 @@ function normalizeMergeOverlapLookback(value) {
|
|
|
215886
216317
|
}
|
|
215887
216318
|
return Math.trunc(value);
|
|
215888
216319
|
}
|
|
215889
|
-
var
|
|
216320
|
+
var execFileAsync19, MERGER_MAIN_OVERLAP_LOOKBACK_COMMITS, GIT_OUTPUT_MAX_BUFFER;
|
|
215890
216321
|
var init_merger_squash_audit = __esm({
|
|
215891
216322
|
"../engine/src/merge/merger-squash-audit.ts"() {
|
|
215892
216323
|
"use strict";
|
|
215893
|
-
|
|
216324
|
+
execFileAsync19 = promisify49(execFile25);
|
|
215894
216325
|
MERGER_MAIN_OVERLAP_LOOKBACK_COMMITS = 30;
|
|
215895
216326
|
GIT_OUTPUT_MAX_BUFFER = 10 * 1024 * 1024;
|
|
215896
216327
|
}
|
|
215897
216328
|
});
|
|
215898
216329
|
|
|
215899
216330
|
// ../engine/src/merge/merger-overlap-guard.ts
|
|
215900
|
-
import { execFile as
|
|
215901
|
-
import { promisify as
|
|
216331
|
+
import { execFile as execFile26 } from "node:child_process";
|
|
216332
|
+
import { promisify as promisify50 } from "node:util";
|
|
215902
216333
|
async function getBranchTouchedFiles({
|
|
215903
216334
|
rootDir,
|
|
215904
216335
|
branch,
|
|
@@ -215974,7 +216405,7 @@ async function restoreBranchWinsFiles({
|
|
|
215974
216405
|
}
|
|
215975
216406
|
async function gitLines(rootDir, args, context2) {
|
|
215976
216407
|
try {
|
|
215977
|
-
const { stdout } = await
|
|
216408
|
+
const { stdout } = await execFileAsync20("git", args, {
|
|
215978
216409
|
cwd: rootDir,
|
|
215979
216410
|
encoding: "utf-8",
|
|
215980
216411
|
maxBuffer: GIT_OUTPUT_MAX_BUFFER2
|
|
@@ -215992,7 +216423,7 @@ function normalizeLines3(value) {
|
|
|
215992
216423
|
}
|
|
215993
216424
|
async function gitRun(rootDir, args, context2) {
|
|
215994
216425
|
try {
|
|
215995
|
-
await
|
|
216426
|
+
await execFileAsync20("git", args, {
|
|
215996
216427
|
cwd: rootDir,
|
|
215997
216428
|
encoding: "utf-8",
|
|
215998
216429
|
maxBuffer: GIT_OUTPUT_MAX_BUFFER2
|
|
@@ -216004,7 +216435,7 @@ async function gitRun(rootDir, args, context2) {
|
|
|
216004
216435
|
}
|
|
216005
216436
|
async function gitExitCode2(rootDir, args) {
|
|
216006
216437
|
try {
|
|
216007
|
-
await
|
|
216438
|
+
await execFileAsync20("git", args, {
|
|
216008
216439
|
cwd: rootDir,
|
|
216009
216440
|
encoding: "utf-8",
|
|
216010
216441
|
maxBuffer: GIT_OUTPUT_MAX_BUFFER2
|
|
@@ -216017,20 +216448,20 @@ async function gitExitCode2(rootDir, args) {
|
|
|
216017
216448
|
function formatErrorMessage(error3) {
|
|
216018
216449
|
return error3 instanceof Error ? error3.message : String(error3);
|
|
216019
216450
|
}
|
|
216020
|
-
var
|
|
216451
|
+
var execFileAsync20, GIT_OUTPUT_MAX_BUFFER2;
|
|
216021
216452
|
var init_merger_overlap_guard = __esm({
|
|
216022
216453
|
"../engine/src/merge/merger-overlap-guard.ts"() {
|
|
216023
216454
|
"use strict";
|
|
216024
216455
|
init_logger3();
|
|
216025
216456
|
init_merger_squash_audit();
|
|
216026
|
-
|
|
216457
|
+
execFileAsync20 = promisify50(execFile26);
|
|
216027
216458
|
GIT_OUTPUT_MAX_BUFFER2 = 10 * 1024 * 1024;
|
|
216028
216459
|
}
|
|
216029
216460
|
});
|
|
216030
216461
|
|
|
216031
216462
|
// ../engine/src/merge/merger-auto-prerebase.ts
|
|
216032
216463
|
import { exec as exec34 } from "node:child_process";
|
|
216033
|
-
import { promisify as
|
|
216464
|
+
import { promisify as promisify51 } from "node:util";
|
|
216034
216465
|
async function probeDivergence(opts) {
|
|
216035
216466
|
const mainRef = opts.mainRef ?? "HEAD";
|
|
216036
216467
|
const range = `${opts.baseCommitSha}..${mainRef}`;
|
|
@@ -216117,13 +216548,13 @@ var execAsync31;
|
|
|
216117
216548
|
var init_merger_auto_prerebase = __esm({
|
|
216118
216549
|
"../engine/src/merge/merger-auto-prerebase.ts"() {
|
|
216119
216550
|
"use strict";
|
|
216120
|
-
execAsync31 =
|
|
216551
|
+
execAsync31 = promisify51(exec34);
|
|
216121
216552
|
}
|
|
216122
216553
|
});
|
|
216123
216554
|
|
|
216124
216555
|
// ../engine/src/execution/branch-autocorrect.ts
|
|
216125
216556
|
import { exec as exec35 } from "node:child_process";
|
|
216126
|
-
import { promisify as
|
|
216557
|
+
import { promisify as promisify52 } from "node:util";
|
|
216127
216558
|
function quoteShellArg7(value) {
|
|
216128
216559
|
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
216129
216560
|
}
|
|
@@ -216192,7 +216623,7 @@ var execAsync32, GIT_TIMEOUT_MS7, GIT_MAX_BUFFER4;
|
|
|
216192
216623
|
var init_branch_autocorrect = __esm({
|
|
216193
216624
|
"../engine/src/execution/branch-autocorrect.ts"() {
|
|
216194
216625
|
"use strict";
|
|
216195
|
-
execAsync32 =
|
|
216626
|
+
execAsync32 = promisify52(exec35);
|
|
216196
216627
|
GIT_TIMEOUT_MS7 = 1e4;
|
|
216197
216628
|
GIT_MAX_BUFFER4 = 1024 * 1024;
|
|
216198
216629
|
}
|
|
@@ -216656,9 +217087,9 @@ var init_mesh_lease_manager = __esm({
|
|
|
216656
217087
|
});
|
|
216657
217088
|
|
|
216658
217089
|
// ../engine/src/merge/merger-integration-worktree.ts
|
|
216659
|
-
import { createHash as
|
|
216660
|
-
import { exec as exec36, execFile as
|
|
216661
|
-
import { promisify as
|
|
217090
|
+
import { createHash as createHash33 } from "node:crypto";
|
|
217091
|
+
import { exec as exec36, execFile as execFile27 } from "node:child_process";
|
|
217092
|
+
import { promisify as promisify53 } from "node:util";
|
|
216662
217093
|
function quoteAutostashArg(value) {
|
|
216663
217094
|
return `"${value.replace(/(["\\$`])/g, "\\$1")}"`;
|
|
216664
217095
|
}
|
|
@@ -216735,15 +217166,15 @@ async function snapshotDirtyFilesLocal(rootDir) {
|
|
|
216735
217166
|
const paths3 = /* @__PURE__ */ new Set();
|
|
216736
217167
|
try {
|
|
216737
217168
|
const [unstagedOut, stagedOut, porcelainOut] = await Promise.all([
|
|
216738
|
-
|
|
217169
|
+
execFileAsync21("git", ["diff", "-z", "--name-only"], { cwd: rootDir, encoding: "utf-8" }).then(
|
|
216739
217170
|
(r) => r.stdout,
|
|
216740
217171
|
() => ""
|
|
216741
217172
|
),
|
|
216742
|
-
|
|
217173
|
+
execFileAsync21("git", ["diff", "-z", "--cached", "--name-only"], { cwd: rootDir, encoding: "utf-8" }).then(
|
|
216743
217174
|
(r) => r.stdout,
|
|
216744
217175
|
() => ""
|
|
216745
217176
|
),
|
|
216746
|
-
|
|
217177
|
+
execFileAsync21("git", ["status", "-z", "--porcelain"], { cwd: rootDir, encoding: "utf-8" }).then(
|
|
216747
217178
|
(r) => r.stdout,
|
|
216748
217179
|
() => ""
|
|
216749
217180
|
)
|
|
@@ -216768,18 +217199,18 @@ async function snapshotDirtyFilesLocal(rootDir) {
|
|
|
216768
217199
|
async function gitDirtyFingerprintLocal(rootDir) {
|
|
216769
217200
|
try {
|
|
216770
217201
|
const [diffOut, statusOut] = await Promise.all([
|
|
216771
|
-
|
|
217202
|
+
execFileAsync21("git", ["diff", "HEAD"], {
|
|
216772
217203
|
cwd: rootDir,
|
|
216773
217204
|
encoding: "utf-8",
|
|
216774
217205
|
maxBuffer: 64 * 1024 * 1024
|
|
216775
217206
|
}).then((r) => r.stdout, () => ""),
|
|
216776
|
-
|
|
217207
|
+
execFileAsync21("git", ["status", "-z", "--porcelain"], { cwd: rootDir, encoding: "utf-8" }).then(
|
|
216777
217208
|
(r) => r.stdout,
|
|
216778
217209
|
() => ""
|
|
216779
217210
|
)
|
|
216780
217211
|
]);
|
|
216781
217212
|
if (!diffOut && !statusOut) return "";
|
|
216782
|
-
return
|
|
217213
|
+
return createHash33("sha256").update(diffOut).update("\0").update(statusOut).digest("hex");
|
|
216783
217214
|
} catch {
|
|
216784
217215
|
return "";
|
|
216785
217216
|
}
|
|
@@ -216796,7 +217227,7 @@ async function probeIntegrationWorktreeState(input) {
|
|
|
216796
217227
|
const dirtyFingerprint = await gitDirtyFingerprintLocal(registeredPath);
|
|
216797
217228
|
let untrackedCount = 0;
|
|
216798
217229
|
try {
|
|
216799
|
-
const { stdout } = await
|
|
217230
|
+
const { stdout } = await execFileAsync21("git", ["status", "-z", "--porcelain"], {
|
|
216800
217231
|
cwd: registeredPath,
|
|
216801
217232
|
encoding: "utf-8"
|
|
216802
217233
|
});
|
|
@@ -217157,7 +217588,7 @@ async function releaseReuseHandoff(input) {
|
|
|
217157
217588
|
}
|
|
217158
217589
|
});
|
|
217159
217590
|
}
|
|
217160
|
-
var execAsync33,
|
|
217591
|
+
var execAsync33, execFileAsync21, MERGE_HANDOFF_WORKER_ID, MergeHandoffRefusedError;
|
|
217161
217592
|
var init_merger_integration_worktree = __esm({
|
|
217162
217593
|
"../engine/src/merge/merger-integration-worktree.ts"() {
|
|
217163
217594
|
"use strict";
|
|
@@ -217168,8 +217599,8 @@ var init_merger_integration_worktree = __esm({
|
|
|
217168
217599
|
init_mesh_lease_manager();
|
|
217169
217600
|
init_worktree_pool();
|
|
217170
217601
|
init_worktree_names();
|
|
217171
|
-
execAsync33 =
|
|
217172
|
-
|
|
217602
|
+
execAsync33 = promisify53(exec36);
|
|
217603
|
+
execFileAsync21 = promisify53(execFile27);
|
|
217173
217604
|
MERGE_HANDOFF_WORKER_ID = "merger-reuse-handoff";
|
|
217174
217605
|
MergeHandoffRefusedError = class extends Error {
|
|
217175
217606
|
reason;
|
|
@@ -217198,13 +217629,13 @@ var init_push_after_merge_policy = __esm({
|
|
|
217198
217629
|
});
|
|
217199
217630
|
|
|
217200
217631
|
// ../engine/src/worktree/worktree-ref-sync.ts
|
|
217201
|
-
import { execFile as
|
|
217202
|
-
import { promisify as
|
|
217632
|
+
import { execFile as execFile28, spawn as spawn7 } from "node:child_process";
|
|
217633
|
+
import { promisify as promisify54 } from "node:util";
|
|
217203
217634
|
import { copyFileSync, existsSync as existsSync64, mkdirSync as mkdirSync8, mkdtempSync as mkdtempSync2, readFileSync as readFileSync22, rmSync as rmSync5, writeFileSync as writeFileSync8 } from "node:fs";
|
|
217204
217635
|
import { dirname as dirname39, join as join80 } from "node:path";
|
|
217205
217636
|
import { tmpdir as tmpdir7 } from "node:os";
|
|
217206
217637
|
async function runGit5(args, cwd, timeoutMs) {
|
|
217207
|
-
const result2 = await
|
|
217638
|
+
const result2 = await execFileAsync22("git", ["-c", "core.quotePath=false", ...args], {
|
|
217208
217639
|
cwd,
|
|
217209
217640
|
timeout: timeoutMs,
|
|
217210
217641
|
maxBuffer: 64 * 1024 * 1024,
|
|
@@ -217438,11 +217869,11 @@ async function syncWorktreeToHead(input) {
|
|
|
217438
217869
|
}
|
|
217439
217870
|
}
|
|
217440
217871
|
}
|
|
217441
|
-
var
|
|
217872
|
+
var execFileAsync22;
|
|
217442
217873
|
var init_worktree_ref_sync = __esm({
|
|
217443
217874
|
"../engine/src/worktree/worktree-ref-sync.ts"() {
|
|
217444
217875
|
"use strict";
|
|
217445
|
-
|
|
217876
|
+
execFileAsync22 = promisify54(execFile28);
|
|
217446
217877
|
}
|
|
217447
217878
|
});
|
|
217448
217879
|
|
|
@@ -217450,7 +217881,7 @@ var init_worktree_ref_sync = __esm({
|
|
|
217450
217881
|
import { exec as exec37 } from "node:child_process";
|
|
217451
217882
|
import { readFile as readFile44, writeFile as writeFile26 } from "node:fs/promises";
|
|
217452
217883
|
import { join as join81 } from "node:path";
|
|
217453
|
-
import { promisify as
|
|
217884
|
+
import { promisify as promisify55 } from "node:util";
|
|
217454
217885
|
function quoteArg4(value) {
|
|
217455
217886
|
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
217456
217887
|
}
|
|
@@ -217626,7 +218057,7 @@ var init_merger_scope_auto_widen = __esm({
|
|
|
217626
218057
|
"use strict";
|
|
217627
218058
|
init_src2();
|
|
217628
218059
|
init_merger();
|
|
217629
|
-
execAsync34 =
|
|
218060
|
+
execAsync34 = promisify55(exec37);
|
|
217630
218061
|
GIT_MAX_BUFFER5 = 10 * 1024 * 1024;
|
|
217631
218062
|
ScopeAutoWidenPersistError = class extends Error {
|
|
217632
218063
|
constructor(message) {
|
|
@@ -217760,9 +218191,9 @@ __export(merger_exports, {
|
|
|
217760
218191
|
});
|
|
217761
218192
|
import { execSync as execSync6, exec as exec38 } from "node:child_process";
|
|
217762
218193
|
import * as childProcess4 from "node:child_process";
|
|
217763
|
-
import { promisify as
|
|
218194
|
+
import { promisify as promisify56 } from "node:util";
|
|
217764
218195
|
import { existsSync as existsSync65, readFileSync as readFileSync23, writeFileSync as writeFileSync9, unlinkSync as unlinkSync3, renameSync as renameSync4 } from "node:fs";
|
|
217765
|
-
import { createHash as
|
|
218196
|
+
import { createHash as createHash34 } from "node:crypto";
|
|
217766
218197
|
import { join as join82, resolve as resolve48 } from "node:path";
|
|
217767
218198
|
import { hostname as hostname3 } from "node:os";
|
|
217768
218199
|
import { Type as Type4 } from "typebox";
|
|
@@ -217973,15 +218404,15 @@ async function snapshotDirtyFiles(rootDir) {
|
|
|
217973
218404
|
const paths3 = /* @__PURE__ */ new Set();
|
|
217974
218405
|
try {
|
|
217975
218406
|
const [unstagedOut, stagedOut, porcelainOut] = await Promise.all([
|
|
217976
|
-
|
|
218407
|
+
execFileAsync23("git", ["diff", "-z", "--name-only"], { cwd: rootDir, encoding: "utf-8" }).then(
|
|
217977
218408
|
(r) => r.stdout,
|
|
217978
218409
|
() => ""
|
|
217979
218410
|
),
|
|
217980
|
-
|
|
218411
|
+
execFileAsync23("git", ["diff", "-z", "--cached", "--name-only"], { cwd: rootDir, encoding: "utf-8" }).then(
|
|
217981
218412
|
(r) => r.stdout,
|
|
217982
218413
|
() => ""
|
|
217983
218414
|
),
|
|
217984
|
-
|
|
218415
|
+
execFileAsync23("git", ["status", "-z", "--porcelain"], { cwd: rootDir, encoding: "utf-8" }).then(
|
|
217985
218416
|
(r) => r.stdout,
|
|
217986
218417
|
() => ""
|
|
217987
218418
|
)
|
|
@@ -218006,18 +218437,18 @@ async function snapshotDirtyFiles(rootDir) {
|
|
|
218006
218437
|
async function gitDirtyFingerprint(rootDir) {
|
|
218007
218438
|
try {
|
|
218008
218439
|
const [diffOut, statusOut] = await Promise.all([
|
|
218009
|
-
|
|
218440
|
+
execFileAsync23("git", ["diff", "HEAD"], {
|
|
218010
218441
|
cwd: rootDir,
|
|
218011
218442
|
encoding: "utf-8",
|
|
218012
218443
|
maxBuffer: 64 * 1024 * 1024
|
|
218013
218444
|
}).then((r) => r.stdout, () => ""),
|
|
218014
|
-
|
|
218445
|
+
execFileAsync23("git", ["status", "-z", "--porcelain"], { cwd: rootDir, encoding: "utf-8" }).then(
|
|
218015
218446
|
(r) => r.stdout,
|
|
218016
218447
|
() => ""
|
|
218017
218448
|
)
|
|
218018
218449
|
]);
|
|
218019
218450
|
if (!diffOut && !statusOut) return "";
|
|
218020
|
-
return
|
|
218451
|
+
return createHash34("sha256").update(diffOut).update("\0").update(statusOut).digest("hex");
|
|
218021
218452
|
} catch {
|
|
218022
218453
|
return "";
|
|
218023
218454
|
}
|
|
@@ -219979,7 +220410,7 @@ function splitNulDelimited(output2) {
|
|
|
219979
220410
|
return text3.split(NUL).filter((entry) => entry.length > 0);
|
|
219980
220411
|
}
|
|
219981
220412
|
async function countStagedPaths(rootDir) {
|
|
219982
|
-
const { stdout } = await
|
|
220413
|
+
const { stdout } = await execFileAsync23("git", ["diff", "--cached", "--name-only", "-z"], {
|
|
219983
220414
|
cwd: rootDir,
|
|
219984
220415
|
encoding: "buffer",
|
|
219985
220416
|
maxBuffer: 10 * 1024 * 1024
|
|
@@ -219988,7 +220419,7 @@ async function countStagedPaths(rootDir) {
|
|
|
219988
220419
|
}
|
|
219989
220420
|
async function filterStagedGitignoredPaths(rootDir, taskId) {
|
|
219990
220421
|
try {
|
|
219991
|
-
const { stdout: stagedOut } = await
|
|
220422
|
+
const { stdout: stagedOut } = await execFileAsync23("git", ["diff", "--cached", "--name-only", "-z"], {
|
|
219992
220423
|
cwd: rootDir,
|
|
219993
220424
|
encoding: "buffer",
|
|
219994
220425
|
maxBuffer: 10 * 1024 * 1024
|
|
@@ -220002,7 +220433,7 @@ async function filterStagedGitignoredPaths(rootDir, taskId) {
|
|
|
220002
220433
|
for (let i = 0; i < stagedPaths.length; i += batchSize) {
|
|
220003
220434
|
const batch = stagedPaths.slice(i, i + batchSize);
|
|
220004
220435
|
try {
|
|
220005
|
-
const { stdout } = await
|
|
220436
|
+
const { stdout } = await execFileAsync23("git", ["check-ignore", "--no-index", "--", ...batch], {
|
|
220006
220437
|
cwd: rootDir,
|
|
220007
220438
|
encoding: "utf-8",
|
|
220008
220439
|
maxBuffer: 10 * 1024 * 1024
|
|
@@ -220025,7 +220456,7 @@ async function filterStagedGitignoredPaths(rootDir, taskId) {
|
|
|
220025
220456
|
`${taskId}: refusing to stage gitignored path "${path13}" \u2014 unstaging (agents must not bypass .gitignore via \`git add -f\`)`
|
|
220026
220457
|
);
|
|
220027
220458
|
try {
|
|
220028
|
-
await
|
|
220459
|
+
await execFileAsync23("git", ["reset", "HEAD", "--", path13], {
|
|
220029
220460
|
cwd: rootDir,
|
|
220030
220461
|
encoding: "utf-8",
|
|
220031
220462
|
maxBuffer: 10 * 1024 * 1024
|
|
@@ -220057,7 +220488,7 @@ async function commitOrAmendMergeWithFixes(rootDir, taskId, branch, commitLog, i
|
|
|
220057
220488
|
encoding: "utf-8"
|
|
220058
220489
|
});
|
|
220059
220490
|
const unstaged = new Set(unstagedOut.split("\n").map((l) => l.trim()).filter(Boolean));
|
|
220060
|
-
const { stdout: porcelainOut } = await
|
|
220491
|
+
const { stdout: porcelainOut } = await execFileAsync23("git", ["status", "-z", "--porcelain"], {
|
|
220061
220492
|
cwd: rootDir,
|
|
220062
220493
|
encoding: "utf-8"
|
|
220063
220494
|
});
|
|
@@ -220078,7 +220509,7 @@ async function commitOrAmendMergeWithFixes(rootDir, taskId, branch, commitLog, i
|
|
|
220078
220509
|
}
|
|
220079
220510
|
}
|
|
220080
220511
|
if (unstagedToStage.length > 0) {
|
|
220081
|
-
await
|
|
220512
|
+
await execFileAsync23("git", ["add", "--", ...unstagedToStage], { cwd: rootDir });
|
|
220082
220513
|
}
|
|
220083
220514
|
const untrackedToStage = [];
|
|
220084
220515
|
for (const p2 of untracked) {
|
|
@@ -220091,7 +220522,7 @@ async function commitOrAmendMergeWithFixes(rootDir, taskId, branch, commitLog, i
|
|
|
220091
220522
|
}
|
|
220092
220523
|
}
|
|
220093
220524
|
if (untrackedToStage.length > 0) {
|
|
220094
|
-
await
|
|
220525
|
+
await execFileAsync23("git", ["add", "--", ...untrackedToStage], { cwd: rootDir });
|
|
220095
220526
|
}
|
|
220096
220527
|
const cap = (arr, n = 20) => arr.length <= n ? arr.join(", ") : `${arr.slice(0, n).join(", ")} ... (+${arr.length - n} more)`;
|
|
220097
220528
|
mergerLog.debug(
|
|
@@ -221562,7 +221993,7 @@ function isNonFastForwardPushError(message) {
|
|
|
221562
221993
|
}
|
|
221563
221994
|
async function probeRebaseInProgress(rootDir) {
|
|
221564
221995
|
const gitPath = async (name2) => {
|
|
221565
|
-
const { stdout } = await
|
|
221996
|
+
const { stdout } = await execFileAsync23("git", ["rev-parse", "--git-path", name2], {
|
|
221566
221997
|
cwd: rootDir,
|
|
221567
221998
|
encoding: "utf-8",
|
|
221568
221999
|
timeout: PUSH_TIMEOUT_MS
|
|
@@ -225747,7 +226178,7 @@ async function completeTask(store, taskId, result2) {
|
|
|
225747
226178
|
}
|
|
225748
226179
|
store.emit("task:merged", result2);
|
|
225749
226180
|
}
|
|
225750
|
-
var execAsync35,
|
|
226181
|
+
var execAsync35, execFileAsync23, LEGACY_COMPLETE_LANES2, DEPENDENCY_SYNC_TRIGGER_PATTERNS, PULL_REBASE_TIMEOUT_MS, PUSH_TIMEOUT_MS, PUSH_NON_FF_MAX_RETRIES, PUSH_NON_FF_RETRY_BACKOFF_MS, PUSH_TRANSIENT_RETRY_BACKOFF_MS, TRANSIENT_GIT_PUSH_PATTERNS, MERGE_COMMIT_LOG_MAX_CHARS, MERGE_DIFF_STAT_MAX_CHARS, MERGE_USER_COMMENTS_MAX_CHARS, summarizeVerificationOutputLocal, VERIFICATION_EXTRA_ENV, ACTIVE_MERGER_STATUS_FILENAME, __test__, AutostashCreationFailedError, NUL, SquashAuditError;
|
|
225751
226182
|
var init_merger = __esm({
|
|
225752
226183
|
"../engine/src/merger.ts"() {
|
|
225753
226184
|
"use strict";
|
|
@@ -225819,8 +226250,8 @@ var init_merger = __esm({
|
|
|
225819
226250
|
init_merger_scope_auto_widen();
|
|
225820
226251
|
init_lifecycle_move();
|
|
225821
226252
|
init_merger_ref_update_advance();
|
|
225822
|
-
execAsync35 =
|
|
225823
|
-
|
|
226253
|
+
execAsync35 = promisify56(exec38);
|
|
226254
|
+
execFileAsync23 = (file, args, opts) => promisify56(childProcess4.execFile)(file, args, opts);
|
|
225824
226255
|
LEGACY_COMPLETE_LANES2 = ["done"];
|
|
225825
226256
|
DEPENDENCY_SYNC_TRIGGER_PATTERNS = [
|
|
225826
226257
|
"package.json",
|
|
@@ -225924,9 +226355,6 @@ function isDependencySatisfiedWithoutWorkflowMetadata(column) {
|
|
|
225924
226355
|
function isLegacyCompleteColumnForWorkspaceTeardown(column) {
|
|
225925
226356
|
return column === "done";
|
|
225926
226357
|
}
|
|
225927
|
-
function resolveRepoLocalAiMergeRoot(rootDir, settings) {
|
|
225928
|
-
return resolveAiMergeRootPath(rootDir, settings);
|
|
225929
|
-
}
|
|
225930
226358
|
async function classifyOwnedLandedEvidenceForSelfHealing(rootDir, task, mergeTargetBranch) {
|
|
225931
226359
|
const { classifyOwnedLandedEvidence: classifyOwnedLandedEvidence2 } = await Promise.resolve().then(() => (init_merger(), merger_exports));
|
|
225932
226360
|
return classifyOwnedLandedEvidence2(rootDir, task, { mergeTargetBranch });
|
|
@@ -226013,6 +226441,8 @@ var init_self_healing = __esm({
|
|
|
226013
226441
|
init_branch_conflicts();
|
|
226014
226442
|
init_run_audit();
|
|
226015
226443
|
init_auto_merge_finalization();
|
|
226444
|
+
init_merge_content_capture();
|
|
226445
|
+
init_stale_content_review_reroute();
|
|
226016
226446
|
init_post_landing_worktree_cleanup();
|
|
226017
226447
|
init_auto_recovery();
|
|
226018
226448
|
init_active_session_registry();
|
|
@@ -226181,6 +226611,7 @@ var init_self_healing = __esm({
|
|
|
226181
226611
|
symbolLockNoActionAudited = false;
|
|
226182
226612
|
maintenanceTickCounter = 0;
|
|
226183
226613
|
taskLifecycleRetentionLastPrunedAt = /* @__PURE__ */ new Map();
|
|
226614
|
+
staleContentRerouteAuditKeys = /* @__PURE__ */ new Set();
|
|
226184
226615
|
githubCheckStateRetentionLastPrunedAt = /* @__PURE__ */ new Map();
|
|
226185
226616
|
processBootStartedAt = Date.now();
|
|
226186
226617
|
lastDbCorruptionNotifiedAt = null;
|
|
@@ -226896,6 +227327,7 @@ var init_self_healing = __esm({
|
|
|
226896
227327
|
// flight" to all of them (the merge gate included), which is the two-hour
|
|
226897
227328
|
// stall-deadlock ride this sweep exists to prevent.
|
|
226898
227329
|
{ name: "reconcile-orphaned-pending-step-results", fn: () => this.reconcileOrphanedPendingStepResults().then(() => void 0) },
|
|
227330
|
+
{ name: "reconcile-unproven-review-approvals", fn: () => this.reconcileUnprovenReviewApprovals().then(() => void 0) },
|
|
226899
227331
|
/*
|
|
226900
227332
|
FNXC:WorkspaceContention 2026-08-23-08:00:
|
|
226901
227333
|
`contention-hold` is owned by an in-memory retry timer. After a process restart that
|
|
@@ -227776,6 +228208,7 @@ var init_self_healing = __esm({
|
|
|
227776
228208
|
Keep them adjacent and in this order.
|
|
227777
228209
|
*/
|
|
227778
228210
|
{ name: "reconcile-orphaned-pending-step-results", fn: () => this.reconcileOrphanedPendingStepResults() },
|
|
228211
|
+
{ name: "reconcile-unproven-review-approvals", fn: () => this.reconcileUnprovenReviewApprovals() },
|
|
227779
228212
|
{ name: "recover-failed-pre-merge-steps", fn: () => this.recoverReviewTasksWithFailedPreMergeSteps() },
|
|
227780
228213
|
{ name: "recover-missing-worktree-review-failures", fn: () => this.recoverMissingWorktreeReviewFailures() },
|
|
227781
228214
|
{ name: "recover-interrupted-merging", fn: () => this.recoverInterruptedMergingTasks() },
|
|
@@ -232222,6 +232655,95 @@ var init_self_healing = __esm({
|
|
|
232222
232655
|
return 0;
|
|
232223
232656
|
}
|
|
232224
232657
|
}
|
|
232658
|
+
/*
|
|
232659
|
+
FNXC:ReviewInputProof 2026-09-01-11:28:
|
|
232660
|
+
Prevention cannot release cards that already persisted a proofless `passed` content review. Repair
|
|
232661
|
+
only the invalid result in place, including when auto-merge is off, so automatic recovery can re-run
|
|
232662
|
+
eligible gates and a human-held card gains the failed result its audited bypass needs. The
|
|
232663
|
+
`needsOperatorBypass` label is therefore truthful rather than aspirational; no lifecycle state moves.
|
|
232664
|
+
|
|
232665
|
+
FNXC:ReviewInputProof 2026-09-01-11:57:
|
|
232666
|
+
Reconciliation must recompute from the lock-held task inside `updateTaskAtomic`; a graph writer can
|
|
232667
|
+
publish a proof-bound approval or another gate after the preliminary read, and a stale array write
|
|
232668
|
+
would discard that valid result. Re-check lane, user pause, workspace ownership, and session liveness
|
|
232669
|
+
in the callback, then log and audit only a repair whose atomic mutation actually applied.
|
|
232670
|
+
*/
|
|
232671
|
+
async reconcileUnprovenReviewApprovals() {
|
|
232672
|
+
try {
|
|
232673
|
+
const reviewColumns = await resolveProjectColumnsForRoles(this.store, REVIEW_ROLES);
|
|
232674
|
+
const candidates = /* @__PURE__ */ new Map();
|
|
232675
|
+
for (const column of reviewColumns) {
|
|
232676
|
+
for (const task of await this.store.listTasks({ column, slim: true })) candidates.set(task.id, task);
|
|
232677
|
+
}
|
|
232678
|
+
const settings = await this.store.getSettings().catch(() => void 0);
|
|
232679
|
+
let repairedTasks = 0;
|
|
232680
|
+
const isSessionLive = (taskId) => {
|
|
232681
|
+
const livePaths = activeSessionRegistry.pathsForTask(taskId);
|
|
232682
|
+
return livePaths.some((path13) => activeSessionRegistry.isPathActive(path13)) || executingTaskLock.has(taskId) || this.options.isTaskActive?.(taskId) === true;
|
|
232683
|
+
};
|
|
232684
|
+
for (const candidate of candidates.values()) {
|
|
232685
|
+
if (candidate.userPaused === true || candidate.workspaceWorktrees !== void 0 || isSessionLive(candidate.id)) continue;
|
|
232686
|
+
if (!candidate.workflowStepResults?.some((result2) => resolveUnprovenReviewApproval(result2, { workspace: false }))) continue;
|
|
232687
|
+
const fresh = await this.store.getTask(candidate.id);
|
|
232688
|
+
if (!fresh || !reviewColumns.has(fresh.column) || fresh.userPaused === true || fresh.workspaceWorktrees !== void 0 || isSessionLive(fresh.id)) continue;
|
|
232689
|
+
let repair;
|
|
232690
|
+
try {
|
|
232691
|
+
await this.store.updateTaskAtomic(fresh.id, (live) => {
|
|
232692
|
+
repair = void 0;
|
|
232693
|
+
if (!reviewColumns.has(live.column) || live.userPaused === true || live.workspaceWorktrees !== void 0 || isSessionLive(live.id)) return null;
|
|
232694
|
+
const repairedStepIds = [];
|
|
232695
|
+
let repairReason;
|
|
232696
|
+
const results = (live.workflowStepResults ?? []).map((result2) => {
|
|
232697
|
+
const resolution = resolveUnprovenReviewApproval(result2, { workspace: false });
|
|
232698
|
+
if (!resolution) return result2;
|
|
232699
|
+
repairedStepIds.push(result2.workflowStepId);
|
|
232700
|
+
repairReason ??= resolution.reason;
|
|
232701
|
+
return resolution.downgraded;
|
|
232702
|
+
});
|
|
232703
|
+
if (repairedStepIds.length === 0 || !repairReason) return null;
|
|
232704
|
+
repair = {
|
|
232705
|
+
stepIds: repairedStepIds,
|
|
232706
|
+
reason: repairReason,
|
|
232707
|
+
column: live.column,
|
|
232708
|
+
resultCount: results.length,
|
|
232709
|
+
needsOperatorBypass: settings ? !allowsAutoMergeProcessing(live, settings) : void 0
|
|
232710
|
+
};
|
|
232711
|
+
return { workflowStepResults: results };
|
|
232712
|
+
});
|
|
232713
|
+
if (!repair) continue;
|
|
232714
|
+
repairedTasks += 1;
|
|
232715
|
+
} catch (error3) {
|
|
232716
|
+
log34.warn(`reconcileUnprovenReviewApprovals: failed for ${fresh.id}: ${error3 instanceof Error ? error3.message : String(error3)}`);
|
|
232717
|
+
continue;
|
|
232718
|
+
}
|
|
232719
|
+
await this.store.logEntry(
|
|
232720
|
+
fresh.id,
|
|
232721
|
+
`[pre-merge] Invalid proofless approval repaired for ${repair.stepIds.join(", ")}: ${repair.reason}`
|
|
232722
|
+
).catch(() => void 0);
|
|
232723
|
+
await emitBoundedRunAudit2(this.store, {
|
|
232724
|
+
taskId: fresh.id,
|
|
232725
|
+
agentId: "self-healing",
|
|
232726
|
+
runId: generateSyntheticRunId("reconcile-unproven-review-approval", fresh.id),
|
|
232727
|
+
domain: "database",
|
|
232728
|
+
mutationType: "task:reconcile-unproven-review-approval",
|
|
232729
|
+
target: fresh.id,
|
|
232730
|
+
metadata: {
|
|
232731
|
+
taskId: fresh.id,
|
|
232732
|
+
column: repair.column,
|
|
232733
|
+
workflowStepId: repair.stepIds[0],
|
|
232734
|
+
repairedCount: repair.stepIds.length,
|
|
232735
|
+
resultCount: repair.resultCount,
|
|
232736
|
+
needsOperatorBypass: repair.needsOperatorBypass
|
|
232737
|
+
}
|
|
232738
|
+
}, { log: log34 });
|
|
232739
|
+
}
|
|
232740
|
+
if (repairedTasks > 0) log34.log(`Repaired unproven review approvals on ${repairedTasks} task(s)`);
|
|
232741
|
+
return repairedTasks;
|
|
232742
|
+
} catch (error3) {
|
|
232743
|
+
log34.error(`reconcileUnprovenReviewApprovals failed: ${error3 instanceof Error ? error3.message : String(error3)}`);
|
|
232744
|
+
return 0;
|
|
232745
|
+
}
|
|
232746
|
+
}
|
|
232225
232747
|
/**
|
|
232226
232748
|
* Backward lifecycle move gated on triple proof (FN-5335).
|
|
232227
232749
|
* When the unproven fallback predicate fails, emits `task:finalize-no-op-review-no-action` and skips lifecycle mutation.
|
|
@@ -232575,6 +233097,66 @@ var init_self_healing = __esm({
|
|
|
232575
233097
|
}
|
|
232576
233098
|
return allowsAutoMergeProcessing(task, settings) && resolveEffectiveAutoMerge(task, settings) !== false;
|
|
232577
233099
|
}
|
|
233100
|
+
/*
|
|
233101
|
+
FNXC:PreMergeApproval 2026-09-01-14:05:
|
|
233102
|
+
Self-healing must not treat a stale content-bound approval as mergeable just because the cheap
|
|
233103
|
+
blocker check lacks a fresh Git descriptor. Capture the same merge content the merge queue uses and
|
|
233104
|
+
seed the graph back at Code Review, so cards like FN-9234 stop looping through doomed merge retries.
|
|
233105
|
+
*/
|
|
233106
|
+
async routeStaleSingularApprovalBackToReview(task, reviewColumns, settings) {
|
|
233107
|
+
let mergeGate;
|
|
233108
|
+
try {
|
|
233109
|
+
mergeGate = await resolvePreMergeGateForTask(this.store, task.id, task.enabledWorkflowSteps, task);
|
|
233110
|
+
} catch {
|
|
233111
|
+
return false;
|
|
233112
|
+
}
|
|
233113
|
+
if (mergeGate.provenance === "default" && !mergeGate.selectionAbsent) return false;
|
|
233114
|
+
const mergeContent = await captureMergeContentDescriptor(task, {
|
|
233115
|
+
workspaceRootDir: this.options.rootDir,
|
|
233116
|
+
settings
|
|
233117
|
+
});
|
|
233118
|
+
const blocker = getTaskMergeBlocker(task, {
|
|
233119
|
+
reviewColumns,
|
|
233120
|
+
requiredPreMergeStepIds: mergeGate.requiredPreMergeStepIds,
|
|
233121
|
+
mergeContent
|
|
233122
|
+
});
|
|
233123
|
+
if (blocker !== "task has a pre-merge approval recorded against different content" || mergeContent.kind !== "singular") {
|
|
233124
|
+
return false;
|
|
233125
|
+
}
|
|
233126
|
+
const reroute = await rerouteSingularStaleContentToReview(this.store, task, {
|
|
233127
|
+
requiredPreMergeStepIds: mergeGate.requiredPreMergeStepIds,
|
|
233128
|
+
mergeContent
|
|
233129
|
+
}).catch(() => ({
|
|
233130
|
+
rerouted: false,
|
|
233131
|
+
reason: "no-progress",
|
|
233132
|
+
nodeId: void 0,
|
|
233133
|
+
workflowStepId: void 0
|
|
233134
|
+
}));
|
|
233135
|
+
if (reroute.rerouted) {
|
|
233136
|
+
await this.store.logEntry(task.id, "[pre-merge] Self-healing re-seeded Code Review after stale content evidence blocked merge.");
|
|
233137
|
+
log34.warn(`Stale content approval for ${task.id} re-seeded at ${reroute.nodeId ?? "code-review"}`);
|
|
233138
|
+
}
|
|
233139
|
+
const auditKey = `${task.id}:${reroute.reason}:${reroute.nodeId ?? ""}`;
|
|
233140
|
+
if (!this.staleContentRerouteAuditKeys.has(auditKey)) {
|
|
233141
|
+
this.staleContentRerouteAuditKeys.add(auditKey);
|
|
233142
|
+
await emitBoundedRunAudit2(this.store, {
|
|
233143
|
+
taskId: task.id,
|
|
233144
|
+
agentId: "self-healing",
|
|
233145
|
+
runId: generateSyntheticRunId("self-healing", task.id),
|
|
233146
|
+
domain: "database",
|
|
233147
|
+
mutationType: "task:merge-stale-content-review-rerouted",
|
|
233148
|
+
target: task.id,
|
|
233149
|
+
metadata: {
|
|
233150
|
+
taskId: task.id,
|
|
233151
|
+
nodeId: reroute.nodeId,
|
|
233152
|
+
workflowStepId: reroute.workflowStepId,
|
|
233153
|
+
reason: reroute.reason,
|
|
233154
|
+
source: "self-healing"
|
|
233155
|
+
}
|
|
233156
|
+
});
|
|
233157
|
+
}
|
|
233158
|
+
return true;
|
|
233159
|
+
}
|
|
232578
233160
|
/**
|
|
232579
233161
|
* Recover `in-review` tasks that are fully mergeable but never had
|
|
232580
233162
|
* `mergeTask()` invoked.
|
|
@@ -232628,6 +233210,7 @@ var init_self_healing = __esm({
|
|
|
232628
233210
|
for (const task of mergeable) {
|
|
232629
233211
|
const reviewColumns = await ownReviewLanesFor(task);
|
|
232630
233212
|
if (!reviewColumns.has(task.column)) continue;
|
|
233213
|
+
if (await this.routeStaleSingularApprovalBackToReview(task, reviewColumns, settings)) continue;
|
|
232631
233214
|
if (getTaskMergeBlocker(task, { reviewColumns }) !== void 0) continue;
|
|
232632
233215
|
laneQualifiedMergeable.push(task);
|
|
232633
233216
|
}
|
|
@@ -235194,8 +235777,7 @@ This review is not retried until its findings change. Re-run the review after ad
|
|
|
235194
235777
|
}
|
|
235195
235778
|
async listAiMergeWorktreeCandidates(taskId, settings) {
|
|
235196
235779
|
const roots = Array.from(/* @__PURE__ */ new Set([
|
|
235197
|
-
|
|
235198
|
-
resolveLegacyAiMergeRootPath(this.options.rootDir),
|
|
235780
|
+
...resolveAiMergeSearchRoots(this.options.rootDir, settings),
|
|
235199
235781
|
tmpdir8()
|
|
235200
235782
|
]));
|
|
235201
235783
|
const testWorkerRoot = process.env.FUSION_TEST_WORKER_ROOT;
|
|
@@ -237729,9 +238311,7 @@ This review is not retried until its findings change. Re-run the review after ad
|
|
|
237729
238311
|
log34.debug("[self-healing] temp-dir sweep: worktrunk enabled \u2014 AI merge clean-room worktrees use Fusion's dedicated clean-room root, proceeding with native sweep");
|
|
237730
238312
|
}
|
|
237731
238313
|
const roots = Array.from(/* @__PURE__ */ new Set([
|
|
237732
|
-
|
|
237733
|
-
resolveLegacyAiMergeRootPath(this.options.rootDir),
|
|
237734
|
-
...settings.worktreesDir ? [] : [join83(resolveLegacyWorktreesDirLayout(this.options.rootDir), ".ai-merge")],
|
|
238314
|
+
...resolveAiMergeSearchRoots(this.options.rootDir, settings),
|
|
237735
238315
|
tmpdir8()
|
|
237736
238316
|
]));
|
|
237737
238317
|
const auditor = createRunAuditor(this.store, {
|
|
@@ -238284,7 +238864,7 @@ import { exec as exec39 } from "node:child_process";
|
|
|
238284
238864
|
import { existsSync as existsSync67 } from "node:fs";
|
|
238285
238865
|
import { readFile as readFile46, writeFile as writeFile27, rm as rm11 } from "node:fs/promises";
|
|
238286
238866
|
import { join as join84 } from "node:path";
|
|
238287
|
-
import { promisify as
|
|
238867
|
+
import { promisify as promisify57 } from "node:util";
|
|
238288
238868
|
function getPlanningLifecycleLockTransportFailure(task) {
|
|
238289
238869
|
const candidate = task.customFields?.[PLANNING_LIFECYCLE_LOCK_TRANSPORT_FAILURE_KEY];
|
|
238290
238870
|
if (!candidate || typeof candidate !== "object" || Array.isArray(candidate)) return null;
|
|
@@ -241681,7 +242261,7 @@ ${lines.join("\n")}` }],
|
|
|
241681
242261
|
written,
|
|
241682
242262
|
{
|
|
241683
242263
|
cwd: this.rootDir,
|
|
241684
|
-
exec:
|
|
242264
|
+
exec: promisify57(exec39)
|
|
241685
242265
|
}
|
|
241686
242266
|
),
|
|
241687
242267
|
new Promise((resolve65) => setTimeout(() => resolve65(null), 15e3))
|
|
@@ -241935,7 +242515,7 @@ var init_workflow_gate_activity = __esm({
|
|
|
241935
242515
|
|
|
241936
242516
|
// ../engine/src/executor/browser-probe.ts
|
|
241937
242517
|
import { exec as exec40 } from "node:child_process";
|
|
241938
|
-
import { promisify as
|
|
242518
|
+
import { promisify as promisify58 } from "node:util";
|
|
241939
242519
|
function isAgentBrowserNotFoundError(error3) {
|
|
241940
242520
|
const err = error3;
|
|
241941
242521
|
const code = typeof err?.code === "string" || typeof err?.code === "number" ? String(err.code) : void 0;
|
|
@@ -241991,7 +242571,7 @@ var execAsync36, AGENT_BROWSER_NAVIGATION_SKILL_ID;
|
|
|
241991
242571
|
var init_browser_probe = __esm({
|
|
241992
242572
|
"../engine/src/executor/browser-probe.ts"() {
|
|
241993
242573
|
"use strict";
|
|
241994
|
-
execAsync36 =
|
|
242574
|
+
execAsync36 = promisify58(exec40);
|
|
241995
242575
|
AGENT_BROWSER_NAVIGATION_SKILL_ID = "agent-browser-navigation";
|
|
241996
242576
|
}
|
|
241997
242577
|
});
|
|
@@ -242510,7 +243090,7 @@ var init_workflow_failure_scope_guard = __esm({
|
|
|
242510
243090
|
// ../engine/src/executor/worktree-registry-helpers.ts
|
|
242511
243091
|
import { isAbsolute as isAbsolute21, relative as relative20, resolve as resolvePath3 } from "node:path";
|
|
242512
243092
|
import { exec as exec41 } from "node:child_process";
|
|
242513
|
-
import { promisify as
|
|
243093
|
+
import { promisify as promisify59 } from "node:util";
|
|
242514
243094
|
async function isRegisteredWorktree(rootDir, path13) {
|
|
242515
243095
|
return isRegisteredGitWorktree(rootDir, path13);
|
|
242516
243096
|
}
|
|
@@ -242554,7 +243134,7 @@ var init_worktree_registry_helpers = __esm({
|
|
|
242554
243134
|
"../engine/src/executor/worktree-registry-helpers.ts"() {
|
|
242555
243135
|
"use strict";
|
|
242556
243136
|
init_worktree_pool();
|
|
242557
|
-
execAsync37 =
|
|
243137
|
+
execAsync37 = promisify59(exec41);
|
|
242558
243138
|
NonRetryableWorktreeError = class extends Error {
|
|
242559
243139
|
};
|
|
242560
243140
|
}
|
|
@@ -242783,7 +243363,7 @@ var init_worktree_ownership = __esm({
|
|
|
242783
243363
|
|
|
242784
243364
|
// ../engine/src/executor/worktree-stale-branch.ts
|
|
242785
243365
|
import { exec as exec42 } from "node:child_process";
|
|
242786
|
-
import { promisify as
|
|
243366
|
+
import { promisify as promisify60 } from "node:util";
|
|
242787
243367
|
async function cleanupStaleBranch(rootDir, store, branch, taskId) {
|
|
242788
243368
|
const task = await store.getTask?.(taskId);
|
|
242789
243369
|
if (!task || !isFusionDeletableBranch(task, branch)) {
|
|
@@ -242839,13 +243419,13 @@ var init_worktree_stale_branch = __esm({
|
|
|
242839
243419
|
"../engine/src/executor/worktree-stale-branch.ts"() {
|
|
242840
243420
|
"use strict";
|
|
242841
243421
|
init_src2();
|
|
242842
|
-
execAsync38 =
|
|
243422
|
+
execAsync38 = promisify60(exec42);
|
|
242843
243423
|
}
|
|
242844
243424
|
});
|
|
242845
243425
|
|
|
242846
243426
|
// ../engine/src/executor/worktree-squash-import-plan.ts
|
|
242847
243427
|
import { exec as exec43 } from "node:child_process";
|
|
242848
|
-
import { promisify as
|
|
243428
|
+
import { promisify as promisify61 } from "node:util";
|
|
242849
243429
|
async function planSquashImportFromDep(rootDir, store, _taskId, depTip, originalStartPoint) {
|
|
242850
243430
|
let settings;
|
|
242851
243431
|
try {
|
|
@@ -242919,7 +243499,7 @@ var init_worktree_squash_import_plan = __esm({
|
|
|
242919
243499
|
"../engine/src/executor/worktree-squash-import-plan.ts"() {
|
|
242920
243500
|
"use strict";
|
|
242921
243501
|
init_shell_quote();
|
|
242922
|
-
execAsync39 =
|
|
243502
|
+
execAsync39 = promisify61(exec43);
|
|
242923
243503
|
}
|
|
242924
243504
|
});
|
|
242925
243505
|
|
|
@@ -243670,7 +244250,7 @@ var init_optional_step_revision = __esm({
|
|
|
243670
244250
|
|
|
243671
244251
|
// ../engine/src/executor/execute-workflow-step.ts
|
|
243672
244252
|
import { exec as exec44 } from "node:child_process";
|
|
243673
|
-
import { promisify as
|
|
244253
|
+
import { promisify as promisify62 } from "node:util";
|
|
243674
244254
|
function findReusableReviewResult(task, workflowStepId, reviewInputFingerprint, repositoryScopeRevision) {
|
|
243675
244255
|
if (!reviewInputFingerprint) return void 0;
|
|
243676
244256
|
return (task.workflowStepResults ?? []).find(
|
|
@@ -243708,6 +244288,8 @@ async function executeWorkflowStep(deps, task, workflowStep, worktreePath, setti
|
|
|
243708
244288
|
const unattended = stepOptions?.unattended === true;
|
|
243709
244289
|
const workflowStepMetadata = workflowStep;
|
|
243710
244290
|
const optionalGroupId = workflowStepMetadata.optionalGroupId;
|
|
244291
|
+
const effectiveWorkflowStepId = optionalGroupId ?? workflowStep.id.replace(/^graph:/, "");
|
|
244292
|
+
const isContentBindingStep = requiresContentReviewProof(effectiveWorkflowStepId, workflowStepMetadata);
|
|
243711
244293
|
const isPlanReviewStep = workflowStep.id === "graph:plan-review-step" || workflowStep.name === "Plan Review" || optionalGroupId === PLAN_REVIEW_GROUP_ID;
|
|
243712
244294
|
const planReviewRevisionKey = optionalStepRevisionKey2(optionalGroupId, workflowStep.name);
|
|
243713
244295
|
const isReviewTypeWorkflowStep = isPlanReviewStep || workflowStepMetadata.reviewCanFixInline === true || /(?:^|\b)(?:review|verification)(?:\b|$)/i.test(workflowStep.name) || optionalGroupId === "plan-review" || optionalGroupId === "code-review" || optionalGroupId === "browser-verification";
|
|
@@ -243718,6 +244300,8 @@ async function executeWorkflowStep(deps, task, workflowStep, worktreePath, setti
|
|
|
243718
244300
|
toolMode = "coding";
|
|
243719
244301
|
}
|
|
243720
244302
|
const requireExternalIntegrationEvidence = workflowStepMetadata.requireExternalIntegrationEvidence === true;
|
|
244303
|
+
const readonlyMcpServerAllowlist = toolMode === "readonly" ? [...new Set((workflowStepMetadata.readonlyMcpServers ?? []).map((name2) => name2.trim()).filter(Boolean))] : [];
|
|
244304
|
+
const allowReadonlyMcpTools = toolMode === "readonly" && readonlyMcpServerAllowlist.length > 0;
|
|
243721
244305
|
let workflowReviewSpecArtifact;
|
|
243722
244306
|
if (isReviewTypeWorkflowStep) {
|
|
243723
244307
|
try {
|
|
@@ -243736,7 +244320,7 @@ async function executeWorkflowStep(deps, task, workflowStep, worktreePath, setti
|
|
|
243736
244320
|
const workflowReviewSpecText = typeof workflowReviewSpecArtifact === "string" ? workflowReviewSpecArtifact : "";
|
|
243737
244321
|
const planReviewSpecText = isPlanReviewStep ? workflowReviewSpecText : "";
|
|
243738
244322
|
const latestTaskForUserComments = await deps.store.getTask(task.id).catch(() => task);
|
|
243739
|
-
const sameGateStepId =
|
|
244323
|
+
const sameGateStepId = effectiveWorkflowStepId;
|
|
243740
244324
|
const planReviewConvergenceContext = isPlanReviewStep ? buildGraphPlanReviewConvergenceContext(latestTaskForUserComments, planReviewRevisionKey) : "";
|
|
243741
244325
|
const planReviewEnvironmentCapabilities = isPlanReviewStep ? await probeEnvironmentCapabilities({
|
|
243742
244326
|
extraCommands: [
|
|
@@ -243784,21 +244368,44 @@ async function executeWorkflowStep(deps, task, workflowStep, worktreePath, setti
|
|
|
243784
244368
|
let diffShortstat;
|
|
243785
244369
|
let reviewInputFingerprint;
|
|
243786
244370
|
let reviewedCommitSha;
|
|
244371
|
+
let baseRef;
|
|
243787
244372
|
try {
|
|
243788
|
-
|
|
243789
|
-
|
|
243790
|
-
|
|
243791
|
-
|
|
243792
|
-
|
|
243793
|
-
|
|
243794
|
-
|
|
244373
|
+
baseRef = await resolveDiffBaseRef(worktreePath, diffBaseCommitSha);
|
|
244374
|
+
} catch {
|
|
244375
|
+
}
|
|
244376
|
+
if (isContentBindingStep && task.workspaceWorktrees === void 0) {
|
|
244377
|
+
const suppliedFingerprint = stepOptions?.reviewInputFingerprint?.trim();
|
|
244378
|
+
const proof = suppliedFingerprint ? { kind: "fingerprint", fingerprint: suppliedFingerprint } : await resolveContentReviewInputProof(worktreePath, diffBaseCommitSha);
|
|
244379
|
+
if (proof.kind === "unprovable") {
|
|
244380
|
+
const diagnostic = `${workflowStep.name} review input is unprovable (${proof.reason}); reviewer dispatch refused.`;
|
|
244381
|
+
await deps.store.logEntry(
|
|
244382
|
+
task.id,
|
|
244383
|
+
`[pre-merge] ${diagnostic}`,
|
|
244384
|
+
void 0,
|
|
244385
|
+
deps.getRunContextFor(task.id)
|
|
244386
|
+
);
|
|
244387
|
+
return { success: false, error: diagnostic, failureValue: "review-input-unprovable" };
|
|
244388
|
+
}
|
|
244389
|
+
reviewInputFingerprint = proof.fingerprint;
|
|
244390
|
+
} else if (baseRef) {
|
|
244391
|
+
try {
|
|
243795
244392
|
if (workflowStepMetadata.reviewKind === "code") {
|
|
243796
244393
|
reviewInputFingerprint = await computeCodeReviewInputFingerprint(worktreePath, baseRef);
|
|
243797
244394
|
} else if (isReviewTypeWorkflowStep) {
|
|
243798
244395
|
reviewInputFingerprint = await computeReviewDiffFingerprint(worktreePath, baseRef);
|
|
243799
244396
|
}
|
|
244397
|
+
} catch {
|
|
244398
|
+
}
|
|
244399
|
+
}
|
|
244400
|
+
if (baseRef) {
|
|
244401
|
+
try {
|
|
244402
|
+
const { stdout } = await execAsync40(`git diff --shortstat ${baseRef}..HEAD`, {
|
|
244403
|
+
cwd: worktreePath,
|
|
244404
|
+
encoding: "utf-8"
|
|
244405
|
+
});
|
|
244406
|
+
diffShortstat = stdout.trim() || void 0;
|
|
244407
|
+
} catch {
|
|
243800
244408
|
}
|
|
243801
|
-
} catch {
|
|
243802
244409
|
}
|
|
243803
244410
|
if (isReviewTypeWorkflowStep) {
|
|
243804
244411
|
try {
|
|
@@ -244108,6 +244715,12 @@ ${workflowStepUserCommentSection}` : ""}${priorFindingsBlock}
|
|
|
244108
244715
|
const workflowStepThinkingSource = workflowStep.thinkingLevel ?? (isReviewTypeWorkflowStep ? task.validatorThinkingLevel ?? task.thinkingLevel : task.thinkingLevel);
|
|
244109
244716
|
const workflowStepThinkingLevel = attemptLabel === "fallback" ? isReviewTypeWorkflowStep ? resolveValidatorFallbackThinkingLevel(workflowStepThinkingSource, settings) : resolveExecutorFallbackThinkingLevel(workflowStepThinkingSource, settings) : isReviewTypeWorkflowStep ? resolveValidatorThinkingLevel(workflowStepThinkingSource, settings) : resolveExecutorThinkingLevel(workflowStepThinkingSource, settings);
|
|
244110
244717
|
const workflowStepFallbackThinkingLevel = isReviewTypeWorkflowStep ? resolveValidatorFallbackThinkingLevel(workflowStepThinkingSource, settings) : resolveExecutorFallbackThinkingLevel(workflowStepThinkingSource, settings);
|
|
244718
|
+
if (allowReadonlyMcpTools) {
|
|
244719
|
+
await deps.store.logEntry(
|
|
244720
|
+
task.id,
|
|
244721
|
+
`Workflow step '${workflowStep.name}' enabled read-only MCP servers: ${readonlyMcpServerAllowlist.join(", ")}`
|
|
244722
|
+
);
|
|
244723
|
+
}
|
|
244111
244724
|
const { session } = await createResolvedAgentSession({
|
|
244112
244725
|
sessionPurpose: "executor",
|
|
244113
244726
|
taskExecutionSession: true,
|
|
@@ -244128,6 +244741,10 @@ ${workflowStepUserCommentSection}` : ""}${priorFindingsBlock}
|
|
|
244128
244741
|
settings,
|
|
244129
244742
|
taskEnv: stepEnv,
|
|
244130
244743
|
mcpServers: await deps.resolveMcpServers(void 0),
|
|
244744
|
+
...allowReadonlyMcpTools ? {
|
|
244745
|
+
allowMcpToolsInReadonly: true,
|
|
244746
|
+
readonlyMcpServerAllowlist
|
|
244747
|
+
} : {},
|
|
244131
244748
|
// FNXC:SessionRouting 2026-06-24-11:20:
|
|
244132
244749
|
// #1675: propagate task id so workflow-step requests carry the same
|
|
244133
244750
|
// X-Session-Id/X-Session-Affinity as the primary session.
|
|
@@ -244343,6 +244960,60 @@ ${detectedQuestion}
|
|
|
244343
244960
|
});
|
|
244344
244961
|
}
|
|
244345
244962
|
const revisionRequested = effectiveVerdict === "REVISE";
|
|
244963
|
+
if (isReviewTypeWorkflowStep && !isPlanReviewStep && !revisionRequested) {
|
|
244964
|
+
const priorReviewedCommitSha = reviewedCommitSha;
|
|
244965
|
+
const currentHeadSha = await readHeadSha(worktreePath);
|
|
244966
|
+
const fastForwardAdvance = await isFastForwardAdvance(worktreePath, priorReviewedCommitSha, currentHeadSha);
|
|
244967
|
+
const baseIsAncestor = await isFastForwardAdvance(worktreePath, baseRef, currentHeadSha);
|
|
244968
|
+
const decision = classifyReviewInlineFixRecapture({
|
|
244969
|
+
verdict: effectiveVerdict,
|
|
244970
|
+
reviewKind: workflowStepMetadata.reviewKind,
|
|
244971
|
+
reviewedCommitSha: priorReviewedCommitSha,
|
|
244972
|
+
currentHeadSha,
|
|
244973
|
+
baseRef,
|
|
244974
|
+
fastForwardAdvance,
|
|
244975
|
+
baseIsAncestor,
|
|
244976
|
+
fingerprintProbeAvailable: true
|
|
244977
|
+
});
|
|
244978
|
+
if (decision.recapture) {
|
|
244979
|
+
try {
|
|
244980
|
+
const recapturedFingerprint = workflowStepMetadata.reviewKind === "code" ? await computeCodeReviewInputFingerprint(worktreePath, baseRef) : await computeReviewDiffFingerprint(worktreePath, baseRef);
|
|
244981
|
+
const finalDecision = classifyReviewInlineFixRecapture({
|
|
244982
|
+
verdict: effectiveVerdict,
|
|
244983
|
+
reviewKind: workflowStepMetadata.reviewKind,
|
|
244984
|
+
reviewedCommitSha: priorReviewedCommitSha,
|
|
244985
|
+
currentHeadSha,
|
|
244986
|
+
baseRef,
|
|
244987
|
+
fastForwardAdvance,
|
|
244988
|
+
baseIsAncestor,
|
|
244989
|
+
fingerprintProbeAvailable: recapturedFingerprint !== void 0
|
|
244990
|
+
});
|
|
244991
|
+
if (finalDecision.recapture && currentHeadSha) {
|
|
244992
|
+
reviewInputFingerprint = recapturedFingerprint;
|
|
244993
|
+
reviewedCommitSha = currentHeadSha;
|
|
244994
|
+
const resolvedInReviewFindingCount = parsed.findings?.filter((finding) => finding.resolution === "resolved-in-review").length ?? 0;
|
|
244995
|
+
await deps.store.logEntry(task.id, `[pre-merge] ${workflowStep.name} re-captured its own review identity after fast-forward ${priorReviewedCommitSha?.slice(0, 7)} \u2192 ${currentHeadSha.slice(0, 7)} (${finalDecision.reason})`);
|
|
244996
|
+
const runContext = deps.getRunContextFor(task.id);
|
|
244997
|
+
if (runContext) await emitBoundedRunAudit2(deps.store, {
|
|
244998
|
+
taskId: task.id,
|
|
244999
|
+
agentId: runContext.agentId,
|
|
245000
|
+
runId: runContext.runId,
|
|
245001
|
+
domain: "git",
|
|
245002
|
+
mutationType: "task:review-input-recaptured",
|
|
245003
|
+
target: task.id,
|
|
245004
|
+
metadata: {
|
|
245005
|
+
taskId: task.id,
|
|
245006
|
+
workflowStepId: workflowStep.id,
|
|
245007
|
+
verdict: effectiveVerdict,
|
|
245008
|
+
resolvedInReviewFindingCount,
|
|
245009
|
+
reason: finalDecision.reason
|
|
245010
|
+
}
|
|
245011
|
+
});
|
|
245012
|
+
}
|
|
245013
|
+
} catch {
|
|
245014
|
+
}
|
|
245015
|
+
}
|
|
245016
|
+
}
|
|
244346
245017
|
if (workflowStep.requiresBrowser === true) {
|
|
244347
245018
|
await logBrowserVerificationActivity(`[browser-verification] finished browser verification for task ${task.id}: verdict ${effectiveVerdict}`);
|
|
244348
245019
|
}
|
|
@@ -244487,9 +245158,10 @@ var init_execute_workflow_step = __esm({
|
|
|
244487
245158
|
init_workflow_step_verdict();
|
|
244488
245159
|
init_worktree_git_refs();
|
|
244489
245160
|
init_review_diff_fingerprint();
|
|
245161
|
+
init_review_inline_fix_recapture();
|
|
244490
245162
|
init_optional_step_revision();
|
|
244491
245163
|
init_agent_usage_telemetry();
|
|
244492
|
-
execAsync40 =
|
|
245164
|
+
execAsync40 = promisify62(exec44);
|
|
244493
245165
|
WORKFLOW_STEP_NOTES_REPAIR_TIMEOUT_MS = 12e4;
|
|
244494
245166
|
}
|
|
244495
245167
|
});
|
|
@@ -245123,7 +245795,7 @@ var init_public_reexports = __esm({
|
|
|
245123
245795
|
|
|
245124
245796
|
// ../engine/src/executor/worktree-create-conflict.ts
|
|
245125
245797
|
import { exec as exec45 } from "node:child_process";
|
|
245126
|
-
import { promisify as
|
|
245798
|
+
import { promisify as promisify63 } from "node:util";
|
|
245127
245799
|
import { existsSync as existsSync69 } from "node:fs";
|
|
245128
245800
|
import { rm as rm12 } from "node:fs/promises";
|
|
245129
245801
|
async function tryCreateWorktree(deps, branch, path13, taskId, startPoint, attemptNumber = 0, recoveryDepth = 0, allowSiblingBranchRename = false, settings = {}) {
|
|
@@ -245418,13 +246090,13 @@ var init_worktree_create_conflict = __esm({
|
|
|
245418
246090
|
init_logger3();
|
|
245419
246091
|
init_worktree_conflict_info();
|
|
245420
246092
|
init_worktree_registry_helpers();
|
|
245421
|
-
execAsync41 =
|
|
246093
|
+
execAsync41 = promisify63(exec45);
|
|
245422
246094
|
}
|
|
245423
246095
|
});
|
|
245424
246096
|
|
|
245425
246097
|
// ../engine/src/executor/worktree-cleanup-conflicting.ts
|
|
245426
246098
|
import { exec as exec46 } from "node:child_process";
|
|
245427
|
-
import { promisify as
|
|
246099
|
+
import { promisify as promisify64 } from "node:util";
|
|
245428
246100
|
import { existsSync as existsSync70, lstatSync as lstatSync3, realpathSync as realpathSync11 } from "node:fs";
|
|
245429
246101
|
import { rm as rm13 } from "node:fs/promises";
|
|
245430
246102
|
async function cleanupConflictingWorktree(deps, worktreePath, branch, taskId) {
|
|
@@ -245543,13 +246215,13 @@ var init_worktree_cleanup_conflicting = __esm({
|
|
|
245543
246215
|
init_src2();
|
|
245544
246216
|
init_worktree_pool();
|
|
245545
246217
|
init_logger3();
|
|
245546
|
-
execAsync42 =
|
|
246218
|
+
execAsync42 = promisify64(exec46);
|
|
245547
246219
|
}
|
|
245548
246220
|
});
|
|
245549
246221
|
|
|
245550
246222
|
// ../engine/src/executor/worktree-create-outer.ts
|
|
245551
246223
|
import { exec as exec47 } from "node:child_process";
|
|
245552
|
-
import { promisify as
|
|
246224
|
+
import { promisify as promisify65 } from "node:util";
|
|
245553
246225
|
import { existsSync as existsSync71 } from "node:fs";
|
|
245554
246226
|
import { isAbsolute as isAbsolute22 } from "node:path";
|
|
245555
246227
|
async function resolveWorktreeStartPoint(rootDir, store, startPoint, taskId) {
|
|
@@ -245754,13 +246426,13 @@ var init_worktree_create_outer = __esm({
|
|
|
245754
246426
|
init_logger3();
|
|
245755
246427
|
init_shell_quote();
|
|
245756
246428
|
init_worktree_registry_helpers();
|
|
245757
|
-
execAsync43 =
|
|
246429
|
+
execAsync43 = promisify65(exec47);
|
|
245758
246430
|
}
|
|
245759
246431
|
});
|
|
245760
246432
|
|
|
245761
246433
|
// ../engine/src/executor/worktree-branch-conflict-handle.ts
|
|
245762
246434
|
import { exec as exec48 } from "node:child_process";
|
|
245763
|
-
import { promisify as
|
|
246435
|
+
import { promisify as promisify66 } from "node:util";
|
|
245764
246436
|
async function reclaimExistingWorktree(deps, task, livePath, branch, tipSha, count2, settings) {
|
|
245765
246437
|
const targetPath = preservedWorktreeTargetPathForTask(task.id, livePath, settings, deps.rootDir);
|
|
245766
246438
|
const normalizedPath = await deps.normalizeReclaimableWorktreePath(livePath, targetPath, task.id, settings);
|
|
@@ -245909,7 +246581,7 @@ var init_worktree_branch_conflict_handle = __esm({
|
|
|
245909
246581
|
init_worktree_git_refs();
|
|
245910
246582
|
init_worktree_registry_helpers();
|
|
245911
246583
|
init_branch_conflict_format();
|
|
245912
|
-
execAsync44 =
|
|
246584
|
+
execAsync44 = promisify66(exec48);
|
|
245913
246585
|
}
|
|
245914
246586
|
});
|
|
245915
246587
|
|
|
@@ -246064,10 +246736,10 @@ var init_session_worktree_paths = __esm({
|
|
|
246064
246736
|
});
|
|
246065
246737
|
|
|
246066
246738
|
// ../engine/src/execution/external-execution-checkout.ts
|
|
246067
|
-
import { execFile as
|
|
246739
|
+
import { execFile as execFile30 } from "node:child_process";
|
|
246068
246740
|
import { existsSync as existsSync72, realpathSync as realpathSync13, statSync as statSync14 } from "node:fs";
|
|
246069
246741
|
import { isAbsolute as isAbsolute23 } from "node:path";
|
|
246070
|
-
import { promisify as
|
|
246742
|
+
import { promisify as promisify67 } from "node:util";
|
|
246071
246743
|
function readSourceMetadata(task) {
|
|
246072
246744
|
if (!task || typeof task !== "object") return void 0;
|
|
246073
246745
|
const sourceMetadata = task.sourceMetadata;
|
|
@@ -246086,7 +246758,7 @@ async function inspectExternalGitCheckout(candidate, options = {}) {
|
|
|
246086
246758
|
return { valid: false, reason: `checkoutPath is not a directory: ${checkoutPath}` };
|
|
246087
246759
|
}
|
|
246088
246760
|
const canonicalCheckout = realpathSync13(checkoutPath);
|
|
246089
|
-
const { stdout: topLevelOutput } = await
|
|
246761
|
+
const { stdout: topLevelOutput } = await execFileAsync24("git", ["rev-parse", "--show-toplevel"], {
|
|
246090
246762
|
cwd: canonicalCheckout,
|
|
246091
246763
|
encoding: "utf-8",
|
|
246092
246764
|
timeout: 1e4
|
|
@@ -246099,7 +246771,7 @@ async function inspectExternalGitCheckout(candidate, options = {}) {
|
|
|
246099
246771
|
reason: `checkoutPath must be the Git top-level (observed ${canonicalTopLevel})`
|
|
246100
246772
|
};
|
|
246101
246773
|
}
|
|
246102
|
-
const { stdout: branchOutput } = await
|
|
246774
|
+
const { stdout: branchOutput } = await execFileAsync24("git", ["symbolic-ref", "--quiet", "--short", "HEAD"], {
|
|
246103
246775
|
cwd: canonicalCheckout,
|
|
246104
246776
|
encoding: "utf-8",
|
|
246105
246777
|
timeout: 1e4
|
|
@@ -246109,7 +246781,7 @@ async function inspectExternalGitCheckout(candidate, options = {}) {
|
|
|
246109
246781
|
return { valid: false, reason: "checkoutPath must have a checked-out branch" };
|
|
246110
246782
|
}
|
|
246111
246783
|
if (options.requireClean) {
|
|
246112
|
-
const { stdout: statusOutput } = await
|
|
246784
|
+
const { stdout: statusOutput } = await execFileAsync24("git", ["status", "--porcelain=v1"], {
|
|
246113
246785
|
cwd: canonicalCheckout,
|
|
246114
246786
|
encoding: "utf-8",
|
|
246115
246787
|
timeout: 1e4
|
|
@@ -246157,11 +246829,11 @@ async function resolveExternalExecutionCheckoutRoute(task) {
|
|
|
246157
246829
|
}
|
|
246158
246830
|
return { configured: true, ...inspection };
|
|
246159
246831
|
}
|
|
246160
|
-
var
|
|
246832
|
+
var execFileAsync24;
|
|
246161
246833
|
var init_external_execution_checkout = __esm({
|
|
246162
246834
|
"../engine/src/execution/external-execution-checkout.ts"() {
|
|
246163
246835
|
"use strict";
|
|
246164
|
-
|
|
246836
|
+
execFileAsync24 = promisify67(execFile30);
|
|
246165
246837
|
}
|
|
246166
246838
|
});
|
|
246167
246839
|
|
|
@@ -246185,7 +246857,7 @@ var init_resolve_authoritative_external_execution_route = __esm({
|
|
|
246185
246857
|
import { exec as exec49 } from "node:child_process";
|
|
246186
246858
|
import { existsSync as existsSync73, promises as fs7 } from "node:fs";
|
|
246187
246859
|
import path4 from "node:path";
|
|
246188
|
-
import { promisify as
|
|
246860
|
+
import { promisify as promisify68 } from "node:util";
|
|
246189
246861
|
function workspaceExecutionAnchor(task) {
|
|
246190
246862
|
const executionValues = [task.firstExecutionAt, task.executionStartedAt].map((value) => typeof value === "string" ? Date.parse(value) : Number.NaN).filter(Number.isFinite);
|
|
246191
246863
|
const values2 = executionValues.length ? executionValues : [typeof task.createdAt === "string" ? Date.parse(task.createdAt) : Number.NaN].filter(Number.isFinite);
|
|
@@ -246309,14 +246981,14 @@ var init_workspace_main_checkout_guard = __esm({
|
|
|
246309
246981
|
init_workspace_paths();
|
|
246310
246982
|
init_worktree_paths();
|
|
246311
246983
|
init_workflow_feedback_paths();
|
|
246312
|
-
execAsync45 =
|
|
246984
|
+
execAsync45 = promisify68(exec49);
|
|
246313
246985
|
probeOptions = { encoding: "utf-8", timeout: 1e4, maxBuffer: 1024 * 1024 };
|
|
246314
246986
|
}
|
|
246315
246987
|
});
|
|
246316
246988
|
|
|
246317
246989
|
// ../engine/src/executor/worktree-verify-invariants.ts
|
|
246318
246990
|
import { exec as exec50 } from "node:child_process";
|
|
246319
|
-
import { promisify as
|
|
246991
|
+
import { promisify as promisify69 } from "node:util";
|
|
246320
246992
|
import { existsSync as existsSync74 } from "node:fs";
|
|
246321
246993
|
async function verifyWorktreeInvariants(deps, task, worktreePathOverride, allowReanchor = true, options) {
|
|
246322
246994
|
const workspaceConfig = deps.ensureWorkspaceConfig ? await deps.ensureWorkspaceConfig() : deps.workspaceConfig;
|
|
@@ -246737,17 +247409,17 @@ var init_worktree_verify_invariants = __esm({
|
|
|
246737
247409
|
init_no_commit_eligibility();
|
|
246738
247410
|
init_resolve_authoritative_external_execution_route();
|
|
246739
247411
|
init_workspace_main_checkout_guard();
|
|
246740
|
-
execAsync46 =
|
|
247412
|
+
execAsync46 = promisify69(exec50);
|
|
246741
247413
|
}
|
|
246742
247414
|
});
|
|
246743
247415
|
|
|
246744
247416
|
// ../engine/src/executor/worktree-task-done-scope-leak.ts
|
|
246745
|
-
import { execFile as
|
|
247417
|
+
import { execFile as execFile31 } from "node:child_process";
|
|
246746
247418
|
import { access as access10 } from "node:fs/promises";
|
|
246747
|
-
import { promisify as
|
|
247419
|
+
import { promisify as promisify70 } from "node:util";
|
|
246748
247420
|
async function verifyRepositoryCaptureEvidence(worktreePath) {
|
|
246749
247421
|
await access10(worktreePath);
|
|
246750
|
-
const { stdout } = await
|
|
247422
|
+
const { stdout } = await execFileAsync25("git", ["rev-parse", "--is-inside-work-tree"], {
|
|
246751
247423
|
cwd: worktreePath,
|
|
246752
247424
|
encoding: "utf8"
|
|
246753
247425
|
});
|
|
@@ -246764,7 +247436,7 @@ async function captureRepositoryChangeEvidence(worktreePath, baseCommitSha) {
|
|
|
246764
247436
|
} else {
|
|
246765
247437
|
commands.push(["rev-parse", "--verify", "HEAD"]);
|
|
246766
247438
|
}
|
|
246767
|
-
const results = await Promise.all(commands.map((args) =>
|
|
247439
|
+
const results = await Promise.all(commands.map((args) => execFileAsync25("git", args, {
|
|
246768
247440
|
cwd: worktreePath,
|
|
246769
247441
|
encoding: "utf8"
|
|
246770
247442
|
})));
|
|
@@ -246893,7 +247565,7 @@ async function evaluateTaskDoneScopeLeak(deps, task, worktreePath, promptContent
|
|
|
246893
247565
|
}
|
|
246894
247566
|
return { blocked: false };
|
|
246895
247567
|
}
|
|
246896
|
-
var
|
|
247568
|
+
var execFileAsync25;
|
|
246897
247569
|
var init_worktree_task_done_scope_leak = __esm({
|
|
246898
247570
|
"../engine/src/executor/worktree-task-done-scope-leak.ts"() {
|
|
246899
247571
|
"use strict";
|
|
@@ -246901,7 +247573,7 @@ var init_worktree_task_done_scope_leak = __esm({
|
|
|
246901
247573
|
init_logger3();
|
|
246902
247574
|
init_prompt_derived_eligibility();
|
|
246903
247575
|
init_workflow_feedback_paths();
|
|
246904
|
-
|
|
247576
|
+
execFileAsync25 = promisify70(execFile31);
|
|
246905
247577
|
}
|
|
246906
247578
|
});
|
|
246907
247579
|
|
|
@@ -247311,7 +247983,7 @@ var init_task_done_refusal_handler = __esm({
|
|
|
247311
247983
|
|
|
247312
247984
|
// ../engine/src/executor/dep-abort-cleanup.ts
|
|
247313
247985
|
import { exec as exec51 } from "node:child_process";
|
|
247314
|
-
import { promisify as
|
|
247986
|
+
import { promisify as promisify71 } from "node:util";
|
|
247315
247987
|
async function handleDepAbortCleanup(deps, taskId, worktreePath) {
|
|
247316
247988
|
executorLog.log(`${taskId} dependency added \u2014 work discarded, moved to triage for re-planning`);
|
|
247317
247989
|
const task = await deps.store.getTask(taskId);
|
|
@@ -247362,7 +248034,7 @@ var init_dep_abort_cleanup = __esm({
|
|
|
247362
248034
|
init_logger3();
|
|
247363
248035
|
init_external_execution_checkout();
|
|
247364
248036
|
init_lifecycle_columns();
|
|
247365
|
-
execAsync47 =
|
|
248037
|
+
execAsync47 = promisify71(exec51);
|
|
247366
248038
|
}
|
|
247367
248039
|
});
|
|
247368
248040
|
|
|
@@ -247886,7 +248558,7 @@ var init_no_merge_complete_column = __esm({
|
|
|
247886
248558
|
// ../engine/src/execution/step-runner.ts
|
|
247887
248559
|
import { exec as exec52 } from "node:child_process";
|
|
247888
248560
|
import { existsSync as existsSync75, statSync as statSync15 } from "node:fs";
|
|
247889
|
-
import { promisify as
|
|
248561
|
+
import { promisify as promisify72 } from "node:util";
|
|
247890
248562
|
async function runTaskStep(deps, task, stepIndex, opts = {}) {
|
|
247891
248563
|
const { store, worktreePath } = deps;
|
|
247892
248564
|
const gitRevParse = deps.gitRevParse ?? defaultGitRevParse;
|
|
@@ -248070,7 +248742,7 @@ var init_step_runner = __esm({
|
|
|
248070
248742
|
"../engine/src/execution/step-runner.ts"() {
|
|
248071
248743
|
"use strict";
|
|
248072
248744
|
init_logger3();
|
|
248073
|
-
execAsync48 =
|
|
248745
|
+
execAsync48 = promisify72(exec52);
|
|
248074
248746
|
}
|
|
248075
248747
|
});
|
|
248076
248748
|
|
|
@@ -250029,7 +250701,7 @@ var init_recover_failed_pre_merge_step = __esm({
|
|
|
250029
250701
|
|
|
250030
250702
|
// ../engine/src/executor/reconcile-steps-from-git-history.ts
|
|
250031
250703
|
import { exec as exec53 } from "node:child_process";
|
|
250032
|
-
import { promisify as
|
|
250704
|
+
import { promisify as promisify73 } from "node:util";
|
|
250033
250705
|
async function reconcileStepsFromGitHistory(deps, taskId, detail, worktreePath) {
|
|
250034
250706
|
const baseCommitSha = detail.baseCommitSha;
|
|
250035
250707
|
if (!baseCommitSha) return;
|
|
@@ -250117,7 +250789,7 @@ var init_reconcile_steps_from_git_history = __esm({
|
|
|
250117
250789
|
"use strict";
|
|
250118
250790
|
init_src2();
|
|
250119
250791
|
init_logger3();
|
|
250120
|
-
execAsync49 =
|
|
250792
|
+
execAsync49 = promisify73(exec53);
|
|
250121
250793
|
}
|
|
250122
250794
|
});
|
|
250123
250795
|
|
|
@@ -252401,7 +253073,14 @@ async function persistWorkflowStepResultWithOutcome(deps, taskId, result2, fence
|
|
|
252401
253073
|
scopeSuperseded = true;
|
|
252402
253074
|
return null;
|
|
252403
253075
|
}
|
|
252404
|
-
const
|
|
253076
|
+
const unprovenApproval = resolveUnprovenReviewApproval(result2, {
|
|
253077
|
+
workspace: current.workspaceWorktrees !== void 0
|
|
253078
|
+
});
|
|
253079
|
+
const built = buildWorkflowStepResultPatch(
|
|
253080
|
+
current,
|
|
253081
|
+
unprovenApproval?.downgraded ?? result2,
|
|
253082
|
+
isPlanReviewResult
|
|
253083
|
+
);
|
|
252405
253084
|
activityResult = built.resultToPersist;
|
|
252406
253085
|
activityResults = built.results;
|
|
252407
253086
|
return built.patch;
|
|
@@ -252438,21 +253117,30 @@ async function persistWorkflowStepResultWithOutcome(deps, taskId, result2, fence
|
|
|
252438
253117
|
if (scopeSuperseded) return { scopeCurrent: false, persisted: false };
|
|
252439
253118
|
if (fenceRefused) return { scopeCurrent: true, persisted: false };
|
|
252440
253119
|
const persistedResult = activityResults?.find((entry) => entry.workflowStepId === result2.workflowStepId) ?? activityResult;
|
|
252441
|
-
|
|
252442
|
-
|
|
253120
|
+
const approvalDowngraded = result2.status === "passed" && persistedResult.status === "failed" && result2.reviewInputFingerprint === void 0 && persistedResult.verdict === void 0;
|
|
253121
|
+
if (approvalDowngraded) {
|
|
253122
|
+
await deps.store.logEntry(
|
|
253123
|
+
taskId,
|
|
253124
|
+
`[pre-merge] ${result2.workflowStepName} approval invalidated: ${persistedResult.notes ?? persistedResult.output ?? "review input proof missing"}`,
|
|
253125
|
+
void 0,
|
|
253126
|
+
deps.getRunContextFor(taskId)
|
|
253127
|
+
).catch(() => void 0);
|
|
253128
|
+
}
|
|
253129
|
+
if (isTerminalStepResult(persistedResult)) {
|
|
253130
|
+
const passed = persistedResult.status === "passed" || persistedResult.status === "skipped" || persistedResult.verdict === "APPROVE" || persistedResult.verdict === "APPROVE_WITH_NOTES" || persistedResult.verdict === "CLOSE_NO_OP";
|
|
252443
253131
|
try {
|
|
252444
253132
|
await deps.store.recordAgentActivity({
|
|
252445
253133
|
type: passed ? "workflow:gate-passed" : "workflow:gate-failed",
|
|
252446
253134
|
attributionClaim: resolveWorkflowGateActivityClaim(
|
|
252447
|
-
deps.workflowGateActivityPrincipals?.get(`${taskId}\0${
|
|
253135
|
+
deps.workflowGateActivityPrincipals?.get(`${taskId}\0${persistedResult.workflowStepId}`) ?? deps.activeWorkflowPrincipals?.get(taskId)?.agentId,
|
|
252448
253136
|
live?.assignedAgentId
|
|
252449
253137
|
),
|
|
252450
253138
|
taskId,
|
|
252451
|
-
occurredAt:
|
|
252452
|
-
discriminator: `${
|
|
252453
|
-
metadata: buildWorkflowGateActivityMetadata(
|
|
253139
|
+
occurredAt: persistedResult.completedAt ?? persistedResult.startedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
253140
|
+
discriminator: `${persistedResult.workflowStepId}:${persistedResult.startedAt ?? persistedResult.completedAt ?? persistedResult.status}`,
|
|
253141
|
+
metadata: buildWorkflowGateActivityMetadata(persistedResult, persistedResult)
|
|
252454
253142
|
});
|
|
252455
|
-
deps.workflowGateActivityPrincipals?.delete(`${taskId}\0${
|
|
253143
|
+
deps.workflowGateActivityPrincipals?.delete(`${taskId}\0${persistedResult.workflowStepId}`);
|
|
252456
253144
|
} catch (error3) {
|
|
252457
253145
|
executorLog.warn(`[agent-activity] ${taskId}: failed to record workflow gate activity: ${error3 instanceof Error ? error3.message : String(error3)}`);
|
|
252458
253146
|
}
|
|
@@ -254463,7 +255151,7 @@ var init_run_spawned_child = __esm({
|
|
|
254463
255151
|
|
|
254464
255152
|
// ../engine/src/auto-recovery-handlers/file-scope.ts
|
|
254465
255153
|
import { exec as exec54 } from "node:child_process";
|
|
254466
|
-
import { promisify as
|
|
255154
|
+
import { promisify as promisify74 } from "node:util";
|
|
254467
255155
|
function createFileScopeAutoRecoveryHandler(deps) {
|
|
254468
255156
|
return new FileScopeAutoRecoveryHandler({
|
|
254469
255157
|
...deps,
|
|
@@ -254474,7 +255162,7 @@ var execAsync50, FileScopeAutoRecoveryHandler;
|
|
|
254474
255162
|
var init_file_scope2 = __esm({
|
|
254475
255163
|
"../engine/src/auto-recovery-handlers/file-scope.ts"() {
|
|
254476
255164
|
"use strict";
|
|
254477
|
-
execAsync50 =
|
|
255165
|
+
execAsync50 = promisify74(exec54);
|
|
254478
255166
|
FileScopeAutoRecoveryHandler = class {
|
|
254479
255167
|
constructor(deps) {
|
|
254480
255168
|
this.deps = deps;
|
|
@@ -254490,7 +255178,7 @@ var init_file_scope2 = __esm({
|
|
|
254490
255178
|
// ../engine/src/auto-recovery-handlers/branch-worktree.ts
|
|
254491
255179
|
import { exec as exec55 } from "node:child_process";
|
|
254492
255180
|
import { existsSync as existsSync78 } from "node:fs";
|
|
254493
|
-
import { promisify as
|
|
255181
|
+
import { promisify as promisify75 } from "node:util";
|
|
254494
255182
|
var execAsync51, baseLog2, GIT_TIMEOUT_MS8, GIT_MAX_BUFFER6, BranchWorktreeAutoRecoveryHandler;
|
|
254495
255183
|
var init_branch_worktree = __esm({
|
|
254496
255184
|
"../engine/src/auto-recovery-handlers/branch-worktree.ts"() {
|
|
@@ -254500,7 +255188,7 @@ var init_branch_worktree = __esm({
|
|
|
254500
255188
|
init_active_session_registry();
|
|
254501
255189
|
init_integration_branch();
|
|
254502
255190
|
init_logger3();
|
|
254503
|
-
execAsync51 =
|
|
255191
|
+
execAsync51 = promisify75(exec55);
|
|
254504
255192
|
baseLog2 = createLogger2("auto-recovery:branch-worktree");
|
|
254505
255193
|
GIT_TIMEOUT_MS8 = 3e4;
|
|
254506
255194
|
GIT_MAX_BUFFER6 = 10 * 1024 * 1024;
|
|
@@ -255567,7 +256255,7 @@ var init_run_raw_cli_command = __esm({
|
|
|
255567
256255
|
|
|
255568
256256
|
// ../engine/src/executor/reset-steps-if-work-lost.ts
|
|
255569
256257
|
import { exec as exec56 } from "node:child_process";
|
|
255570
|
-
import { promisify as
|
|
256258
|
+
import { promisify as promisify76 } from "node:util";
|
|
255571
256259
|
async function resetStepsIfWorkLost(deps, task) {
|
|
255572
256260
|
const completedSteps = task.steps.filter(
|
|
255573
256261
|
(s3) => s3.status === "done" || s3.status === "in-progress"
|
|
@@ -255608,7 +256296,7 @@ var init_reset_steps_if_work_lost = __esm({
|
|
|
255608
256296
|
init_src2();
|
|
255609
256297
|
init_worktree_names();
|
|
255610
256298
|
init_logger3();
|
|
255611
|
-
execAsync52 =
|
|
256299
|
+
execAsync52 = promisify76(exec56);
|
|
255612
256300
|
}
|
|
255613
256301
|
});
|
|
255614
256302
|
|
|
@@ -255655,7 +256343,7 @@ var init_route_retryable_remediation = __esm({
|
|
|
255655
256343
|
|
|
255656
256344
|
// ../engine/src/executor/build-foreach-worktree-deps.ts
|
|
255657
256345
|
import { exec as exec57 } from "node:child_process";
|
|
255658
|
-
import { promisify as
|
|
256346
|
+
import { promisify as promisify77 } from "node:util";
|
|
255659
256347
|
function buildForeachWorktreeDeps(deps, task, runId) {
|
|
255660
256348
|
const taskId = task.id;
|
|
255661
256349
|
const instancePaths = /* @__PURE__ */ new Map();
|
|
@@ -255849,20 +256537,20 @@ var init_build_foreach_worktree_deps = __esm({
|
|
|
255849
256537
|
init_worktree_names();
|
|
255850
256538
|
init_worktree_paths();
|
|
255851
256539
|
init_logger3();
|
|
255852
|
-
execAsync53 =
|
|
256540
|
+
execAsync53 = promisify77(exec57);
|
|
255853
256541
|
WORKSPACE_ISOLATION_UNSUPPORTED_MESSAGE = "per-instance worktree isolation is not supported for workspace projects";
|
|
255854
256542
|
}
|
|
255855
256543
|
});
|
|
255856
256544
|
|
|
255857
256545
|
// ../engine/src/executor/derive-remediation-steps.ts
|
|
255858
|
-
import { createHash as
|
|
256546
|
+
import { createHash as createHash35 } from "node:crypto";
|
|
255859
256547
|
function normalizeVerificationEvidence(output2) {
|
|
255860
256548
|
if (!output2?.trim()) return "";
|
|
255861
256549
|
return output2.replace(ansiEscapeSequence, "").replace(/\r\n?/g, "\n").split("\n").map((line2) => line2.trim().replace(isoTimestamp, "<timestamp>").replace(bareTimestamp, "<timestamp>").replace(elapsedDuration, "<duration>").replace(/\s+/g, " ")).filter(Boolean).join("\n");
|
|
255862
256550
|
}
|
|
255863
256551
|
function verificationEvidenceDigest(output2) {
|
|
255864
256552
|
const evidence = normalizeVerificationEvidence(output2);
|
|
255865
|
-
return evidence ?
|
|
256553
|
+
return evidence ? createHash35("sha256").update(evidence).digest("hex").slice(0, 16) : void 0;
|
|
255866
256554
|
}
|
|
255867
256555
|
function verificationCandidates(input) {
|
|
255868
256556
|
const detail = input.verificationCommandLabel ?? "verification command";
|
|
@@ -260565,10 +261253,10 @@ var init_pending_review_block = __esm({
|
|
|
260565
261253
|
});
|
|
260566
261254
|
|
|
260567
261255
|
// ../engine/src/merge/merger-orphan-rehome.ts
|
|
260568
|
-
import { execFile as
|
|
260569
|
-
import { promisify as
|
|
261256
|
+
import { execFile as execFile32 } from "node:child_process";
|
|
261257
|
+
import { promisify as promisify78 } from "node:util";
|
|
260570
261258
|
async function runGit6(args, cwd) {
|
|
260571
|
-
const { stdout } = await
|
|
261259
|
+
const { stdout } = await execFileAsync26("git", args, {
|
|
260572
261260
|
cwd,
|
|
260573
261261
|
encoding: "utf-8",
|
|
260574
261262
|
timeout: 3e4
|
|
@@ -260577,7 +261265,7 @@ async function runGit6(args, cwd) {
|
|
|
260577
261265
|
}
|
|
260578
261266
|
async function isAncestor3(repoDir, ancestor, descendant) {
|
|
260579
261267
|
try {
|
|
260580
|
-
await
|
|
261268
|
+
await execFileAsync26(
|
|
260581
261269
|
"git",
|
|
260582
261270
|
["merge-base", "--is-ancestor", ancestor, descendant],
|
|
260583
261271
|
{ cwd: repoDir, encoding: "utf-8", timeout: 3e4 }
|
|
@@ -260672,13 +261360,13 @@ async function rehomeOrphanOntoIntegration(input) {
|
|
|
260672
261360
|
newTipSha: advanceResult.newSha
|
|
260673
261361
|
};
|
|
260674
261362
|
}
|
|
260675
|
-
var
|
|
261363
|
+
var execFileAsync26;
|
|
260676
261364
|
var init_merger_orphan_rehome = __esm({
|
|
260677
261365
|
"../engine/src/merge/merger-orphan-rehome.ts"() {
|
|
260678
261366
|
"use strict";
|
|
260679
261367
|
init_src2();
|
|
260680
261368
|
init_merger_ref_update_advance();
|
|
260681
|
-
|
|
261369
|
+
execFileAsync26 = promisify78(execFile32);
|
|
260682
261370
|
}
|
|
260683
261371
|
});
|
|
260684
261372
|
|
|
@@ -260705,7 +261393,7 @@ var init_merge_execution_exclusion = __esm({
|
|
|
260705
261393
|
|
|
260706
261394
|
// ../engine/src/executor/run-implementation.ts
|
|
260707
261395
|
import { exec as exec58 } from "node:child_process";
|
|
260708
|
-
import { promisify as
|
|
261396
|
+
import { promisify as promisify79 } from "node:util";
|
|
260709
261397
|
import { existsSync as existsSync81 } from "node:fs";
|
|
260710
261398
|
import { join as join93 } from "node:path";
|
|
260711
261399
|
import { SessionManager as SessionManager2 } from "@earendil-works/pi-coding-agent";
|
|
@@ -263541,7 +264229,7 @@ var init_run_implementation = __esm({
|
|
|
263541
264229
|
init_worktree_acquisition();
|
|
263542
264230
|
init_worktree_paths();
|
|
263543
264231
|
init_worktree_pool();
|
|
263544
|
-
execAsync54 =
|
|
264232
|
+
execAsync54 = promisify79(exec58);
|
|
263545
264233
|
MAX_TASK_DONE_SESSION_RETRIES = 3;
|
|
263546
264234
|
}
|
|
263547
264235
|
});
|
|
@@ -267267,8 +267955,8 @@ var init_worktree_create_binders = __esm({
|
|
|
267267
267955
|
});
|
|
267268
267956
|
|
|
267269
267957
|
// ../engine/src/executor/wire-executor-lifecycle.ts
|
|
267270
|
-
import { execFile as
|
|
267271
|
-
import { promisify as
|
|
267958
|
+
import { execFile as execFile33 } from "node:child_process";
|
|
267959
|
+
import { promisify as promisify80 } from "node:util";
|
|
267272
267960
|
async function releaseWorkspaceAcquireClaims(store, taskId) {
|
|
267273
267961
|
for (const entry of activeSessionRegistry.entriesByKind("workspace-repo-acquire")) {
|
|
267274
267962
|
if (entry.taskId === taskId) activeSessionRegistry.unregisterPath(entry.path);
|
|
@@ -267316,7 +268004,7 @@ function wireExecutorLifecycle(deps) {
|
|
|
267316
268004
|
if (await canonicalizeWorktreePath(entry.worktreePath) === await canonicalizeWorktreePath(entry.repoRootDir)) throw new Error("Refusing to remove workspace repository root");
|
|
267317
268005
|
activeSessionRegistry.unregisterPath(entry.worktreePath);
|
|
267318
268006
|
await removeWorktree({ worktreePath: entry.worktreePath, rootDir: entry.repoRootDir, settings: await deps.store.getSettings(), taskId: task.id, reason: RemovalReason.ExecutorDispose, force: true });
|
|
267319
|
-
await
|
|
268007
|
+
await execFileAsync27("git", ["branch", "-D", entry.branch], { cwd: entry.repoRootDir, timeout: 12e4, maxBuffer: 10 * 1024 * 1024 });
|
|
267320
268008
|
if (task.workspaceWorktrees) for (const repoRel of [entry.repoRel, ...entry.aliasRepoRels]) delete task.workspaceWorktrees[repoRel];
|
|
267321
268009
|
removed.push(entry.repoRel);
|
|
267322
268010
|
} catch (error3) {
|
|
@@ -267744,7 +268432,7 @@ function wireTaskExecutorLifecycle(host) {
|
|
|
267744
268432
|
h.workflowAgentCapacity = new WorkflowAgentCapacity(h.options?.agentStore ?? void 0);
|
|
267745
268433
|
applyWireExecutorLifecycleDisposers(host, wireExecutorLifecycle(buildWireExecutorLifecycleDeps(host)));
|
|
267746
268434
|
}
|
|
267747
|
-
var
|
|
268435
|
+
var execFileAsync27, WIRE_LIFECYCLE_FIELDS, WIRE_LIFECYCLE_METHODS;
|
|
267748
268436
|
var init_wire_executor_lifecycle = __esm({
|
|
267749
268437
|
"../engine/src/executor/wire-executor-lifecycle.ts"() {
|
|
267750
268438
|
"use strict";
|
|
@@ -267761,7 +268449,7 @@ var init_wire_executor_lifecycle = __esm({
|
|
|
267761
268449
|
init_task_predicates();
|
|
267762
268450
|
init_facade_methods();
|
|
267763
268451
|
init_workflow_agent_capacity();
|
|
267764
|
-
|
|
268452
|
+
execFileAsync27 = promisify80(execFile33);
|
|
267765
268453
|
WIRE_LIFECYCLE_FIELDS = [
|
|
267766
268454
|
"activeConfiguredCommandControllers",
|
|
267767
268455
|
"activeSessions",
|
|
@@ -270658,7 +271346,7 @@ import { promises as fs9 } from "node:fs";
|
|
|
270658
271346
|
import os7 from "node:os";
|
|
270659
271347
|
import path5 from "node:path";
|
|
270660
271348
|
import { exec as exec59 } from "node:child_process";
|
|
270661
|
-
import { promisify as
|
|
271349
|
+
import { promisify as promisify81 } from "node:util";
|
|
270662
271350
|
var execAsync55, verifyLog, GitCheckoutMaterializer;
|
|
270663
271351
|
var init_mission_verification = __esm({
|
|
270664
271352
|
"../engine/src/missions/mission-verification.ts"() {
|
|
@@ -270668,7 +271356,7 @@ var init_mission_verification = __esm({
|
|
|
270668
271356
|
init_sandbox_exec_detect();
|
|
270669
271357
|
init_verification_utils();
|
|
270670
271358
|
init_logger3();
|
|
270671
|
-
execAsync55 =
|
|
271359
|
+
execAsync55 = promisify81(exec59);
|
|
270672
271360
|
verifyLog = createLogger2("mission-verify");
|
|
270673
271361
|
GitCheckoutMaterializer = class {
|
|
270674
271362
|
async materialize(rootDir, revision) {
|
|
@@ -270711,14 +271399,14 @@ ${stdout.trim()}`);
|
|
|
270711
271399
|
|
|
270712
271400
|
// ../engine/src/missions/mission-execution-loop.ts
|
|
270713
271401
|
import { EventEmitter as EventEmitter25 } from "node:events";
|
|
270714
|
-
import { createHash as
|
|
271402
|
+
import { createHash as createHash36 } from "node:crypto";
|
|
270715
271403
|
import { exec as exec60 } from "node:child_process";
|
|
270716
|
-
import { promisify as
|
|
271404
|
+
import { promisify as promisify82 } from "node:util";
|
|
270717
271405
|
function quoteShellArg8(value) {
|
|
270718
271406
|
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
270719
271407
|
}
|
|
270720
271408
|
function fingerprintMissionValidationInput(landedSha, provider, modelId, systemPrompt, userPrompt) {
|
|
270721
|
-
return
|
|
271409
|
+
return createHash36("sha256").update(Buffer.from(JSON.stringify(["mission-validation-input-v1", landedSha, provider, modelId, systemPrompt, userPrompt]), "utf8")).digest("hex");
|
|
270722
271410
|
}
|
|
270723
271411
|
var execAsync56, loopLog, VALIDATION_TIMEOUT_MS, MAX_VALIDATION_RESPONSE_BYTES, MAX_VALIDATION_JSON_CANDIDATES, VALIDATION_FAILURE_BUDGET_PER_FINGERPRINT, MissionExecutionLoop;
|
|
270724
271412
|
var init_mission_execution_loop = __esm({
|
|
@@ -270734,7 +271422,7 @@ var init_mission_execution_loop = __esm({
|
|
|
270734
271422
|
init_fallback_model_observer();
|
|
270735
271423
|
init_mcp_resolution();
|
|
270736
271424
|
init_run_audit();
|
|
270737
|
-
execAsync56 =
|
|
271425
|
+
execAsync56 = promisify82(exec60);
|
|
270738
271426
|
loopLog = createLogger2("mission-loop");
|
|
270739
271427
|
VALIDATION_TIMEOUT_MS = 10 * 60 * 1e3;
|
|
270740
271428
|
MAX_VALIDATION_RESPONSE_BYTES = 256 * 1024;
|
|
@@ -272248,44 +272936,9 @@ ${taskContext}` : ""}`;
|
|
|
272248
272936
|
}
|
|
272249
272937
|
});
|
|
272250
272938
|
|
|
272251
|
-
// ../engine/src/merge/merge-content-capture.ts
|
|
272252
|
-
async function captureMergeContentDescriptor(task, deps) {
|
|
272253
|
-
if (describeMergeContentShape(task) === "workspace") {
|
|
272254
|
-
try {
|
|
272255
|
-
const evidence = await captureWorkspaceReviewEvidence({
|
|
272256
|
-
task,
|
|
272257
|
-
workspaceRootDir: deps.workspaceRootDir,
|
|
272258
|
-
settings: deps.settings
|
|
272259
|
-
});
|
|
272260
|
-
return {
|
|
272261
|
-
kind: "workspace",
|
|
272262
|
-
repositories: {
|
|
272263
|
-
state: "captured",
|
|
272264
|
-
fingerprints: Object.fromEntries(evidence.repositories.filter((repository) => repository.fingerprint).map((repository) => [repository.repository, repository.fingerprint])),
|
|
272265
|
-
inScopeModified: [...evidence.modifiedRepositories].sort()
|
|
272266
|
-
}
|
|
272267
|
-
};
|
|
272268
|
-
} catch {
|
|
272269
|
-
return { kind: "workspace", repositories: { state: "unavailable", reason: "workspace-evidence-capture-failed" } };
|
|
272270
|
-
}
|
|
272271
|
-
}
|
|
272272
|
-
const baseRef = task.worktree ? await resolveDiffBaseRef(task.worktree, task.baseCommitSha) : void 0;
|
|
272273
|
-
const probe = await probeReviewDiffFingerprint(task.worktree, baseRef);
|
|
272274
|
-
return { kind: "singular", diff: probe };
|
|
272275
|
-
}
|
|
272276
|
-
var init_merge_content_capture = __esm({
|
|
272277
|
-
"../engine/src/merge/merge-content-capture.ts"() {
|
|
272278
|
-
"use strict";
|
|
272279
|
-
init_src2();
|
|
272280
|
-
init_worktree_git_refs();
|
|
272281
|
-
init_review_diff_fingerprint();
|
|
272282
|
-
init_workspace_review_evidence();
|
|
272283
|
-
}
|
|
272284
|
-
});
|
|
272285
|
-
|
|
272286
272939
|
// ../engine/src/merge/merger-ai-squash-gates.ts
|
|
272287
|
-
import { execFile as
|
|
272288
|
-
import { promisify as
|
|
272940
|
+
import { execFile as execFile34 } from "node:child_process";
|
|
272941
|
+
import { promisify as promisify83 } from "node:util";
|
|
272289
272942
|
function resolveRepoDeclaredScopeTransform({ repoRel, repoKeys }) {
|
|
272290
272943
|
return {
|
|
272291
272944
|
transform(scope) {
|
|
@@ -272316,8 +272969,8 @@ async function enforceAiMergeSquashGates(params) {
|
|
|
272316
272969
|
});
|
|
272317
272970
|
} catch (error3) {
|
|
272318
272971
|
if (!(error3 instanceof FileScopeViolationError)) throw error3;
|
|
272319
|
-
await
|
|
272320
|
-
await
|
|
272972
|
+
await execFileAsync28("git", ["reset", "--hard", params.tipSha], { cwd: params.mergeRoot });
|
|
272973
|
+
await execFileAsync28("git", ["clean", "-fd"], { cwd: params.mergeRoot });
|
|
272321
272974
|
try {
|
|
272322
272975
|
await params.store.updateTask(params.taskId, { aiMergeReviewReconciliation: null });
|
|
272323
272976
|
} catch {
|
|
@@ -272325,13 +272978,13 @@ async function enforceAiMergeSquashGates(params) {
|
|
|
272325
272978
|
throw error3;
|
|
272326
272979
|
}
|
|
272327
272980
|
}
|
|
272328
|
-
var
|
|
272981
|
+
var execFileAsync28;
|
|
272329
272982
|
var init_merger_ai_squash_gates = __esm({
|
|
272330
272983
|
"../engine/src/merge/merger-ai-squash-gates.ts"() {
|
|
272331
272984
|
"use strict";
|
|
272332
272985
|
init_workspace_paths();
|
|
272333
272986
|
init_merger_file_scope();
|
|
272334
|
-
|
|
272987
|
+
execFileAsync28 = promisify83(execFile34);
|
|
272335
272988
|
}
|
|
272336
272989
|
});
|
|
272337
272990
|
|
|
@@ -272831,11 +273484,11 @@ var init_workspace_merge_readiness = __esm({
|
|
|
272831
273484
|
});
|
|
272832
273485
|
|
|
272833
273486
|
// ../engine/src/merge/workspace-fence-ref.ts
|
|
272834
|
-
import { execFile as
|
|
272835
|
-
import { createHash as
|
|
272836
|
-
import { promisify as
|
|
273487
|
+
import { execFile as execFile35 } from "node:child_process";
|
|
273488
|
+
import { createHash as createHash37 } from "node:crypto";
|
|
273489
|
+
import { promisify as promisify84 } from "node:util";
|
|
272837
273490
|
async function git6(args, cwd) {
|
|
272838
|
-
const { stdout } = await
|
|
273491
|
+
const { stdout } = await execFileAsync29("git", args, {
|
|
272839
273492
|
cwd,
|
|
272840
273493
|
encoding: "utf8",
|
|
272841
273494
|
maxBuffer: 1024 * 1024
|
|
@@ -272848,7 +273501,7 @@ async function remoteRefSha(remote, ref, cwd) {
|
|
|
272848
273501
|
return /^[0-9a-f]{40,64}$/i.test(sha ?? "") ? sha : void 0;
|
|
272849
273502
|
}
|
|
272850
273503
|
function workspaceLandFenceRef(repoRelPath) {
|
|
272851
|
-
const slug2 =
|
|
273504
|
+
const slug2 = createHash37("sha256").update(repoRelPath).digest("hex").slice(0, 24);
|
|
272852
273505
|
return `refs/fusion/workspace-lease/${slug2}`;
|
|
272853
273506
|
}
|
|
272854
273507
|
function mergeDispatchFenceRef(taskId) {
|
|
@@ -272857,7 +273510,7 @@ function mergeDispatchFenceRef(taskId) {
|
|
|
272857
273510
|
async function createFenceObject(cwd, handle2) {
|
|
272858
273511
|
const tree = await git6(["hash-object", "-w", "-t", "tree", "/dev/null"], cwd);
|
|
272859
273512
|
const message = `workspace lease ${handle2.leaseKey} ${handle2.owner.taskId} ${handle2.owner.nodeId} ${handle2.owner.incarnationId} ${handle2.fenceToken}`;
|
|
272860
|
-
const { stdout } = await
|
|
273513
|
+
const { stdout } = await execFileAsync29("git", [
|
|
272861
273514
|
"-c",
|
|
272862
273515
|
"user.name=Fusion",
|
|
272863
273516
|
"-c",
|
|
@@ -272987,11 +273640,11 @@ async function publishWorkspaceIntegrationRef(input) {
|
|
|
272987
273640
|
await pushWithWorkspaceFence({ ...input, expectedTargetSha: observedTargetSha });
|
|
272988
273641
|
return { republishedFromObservedTip: true, observedTargetSha };
|
|
272989
273642
|
}
|
|
272990
|
-
var
|
|
273643
|
+
var execFileAsync29, WorkspaceFenceRefError;
|
|
272991
273644
|
var init_workspace_fence_ref = __esm({
|
|
272992
273645
|
"../engine/src/merge/workspace-fence-ref.ts"() {
|
|
272993
273646
|
"use strict";
|
|
272994
|
-
|
|
273647
|
+
execFileAsync29 = promisify84(execFile35);
|
|
272995
273648
|
WorkspaceFenceRefError = class extends Error {
|
|
272996
273649
|
constructor(message, kind) {
|
|
272997
273650
|
super(message);
|
|
@@ -273003,10 +273656,10 @@ var init_workspace_fence_ref = __esm({
|
|
|
273003
273656
|
});
|
|
273004
273657
|
|
|
273005
273658
|
// ../engine/src/merge/workspace-integration-target.ts
|
|
273006
|
-
import { execFile as
|
|
273007
|
-
import { promisify as
|
|
273659
|
+
import { execFile as execFile36 } from "node:child_process";
|
|
273660
|
+
import { promisify as promisify85 } from "node:util";
|
|
273008
273661
|
async function git7(args, cwd) {
|
|
273009
|
-
const { stdout } = await
|
|
273662
|
+
const { stdout } = await execFileAsync30("git", args, { cwd, encoding: "utf8" });
|
|
273010
273663
|
return stdout.trim();
|
|
273011
273664
|
}
|
|
273012
273665
|
async function resolveWorkspaceIntegrationTarget(input) {
|
|
@@ -273046,11 +273699,11 @@ async function resolveWorkspaceIntegrationTarget(input) {
|
|
|
273046
273699
|
`Workspace repository ${input.repository} has ambiguous integration remotes: ${remotes.join(", ")}`
|
|
273047
273700
|
);
|
|
273048
273701
|
}
|
|
273049
|
-
var
|
|
273702
|
+
var execFileAsync30, WorkspaceEnvironmentError, WorkspaceIntegrationTargetError;
|
|
273050
273703
|
var init_workspace_integration_target = __esm({
|
|
273051
273704
|
"../engine/src/merge/workspace-integration-target.ts"() {
|
|
273052
273705
|
"use strict";
|
|
273053
|
-
|
|
273706
|
+
execFileAsync30 = promisify85(execFile36);
|
|
273054
273707
|
WorkspaceEnvironmentError = class extends Error {
|
|
273055
273708
|
constructor(repository, resource, action, message) {
|
|
273056
273709
|
super(message);
|
|
@@ -273073,14 +273726,14 @@ var init_workspace_integration_target = __esm({
|
|
|
273073
273726
|
});
|
|
273074
273727
|
|
|
273075
273728
|
// ../engine/src/merge/merger-ai-worktree.ts
|
|
273076
|
-
import { execFile as
|
|
273729
|
+
import { execFile as execFile37 } from "node:child_process";
|
|
273077
273730
|
import { appendFileSync as appendFileSync2, existsSync as existsSync84, mkdirSync as mkdirSync10, readdirSync as readdirSync12, readFileSync as readFileSync26, realpathSync as realpathSync14, rmSync as rmSync7, statSync as statSync16 } from "node:fs";
|
|
273078
273731
|
import { rm as rm17 } from "node:fs/promises";
|
|
273079
273732
|
import { tmpdir as tmpdir11 } from "node:os";
|
|
273080
273733
|
import { isAbsolute as isAbsolute25, join as join95, relative as relative22 } from "node:path";
|
|
273081
|
-
import { promisify as
|
|
273734
|
+
import { promisify as promisify86 } from "node:util";
|
|
273082
273735
|
async function git8(args, cwd, opts = {}) {
|
|
273083
|
-
const { stdout } = await
|
|
273736
|
+
const { stdout } = await execFileAsync31("git", args, {
|
|
273084
273737
|
cwd,
|
|
273085
273738
|
encoding: "utf-8",
|
|
273086
273739
|
timeout: opts.timeout ?? 12e4,
|
|
@@ -273109,14 +273762,7 @@ function ensureAiMergeRootIgnored(projectRootDir, settings) {
|
|
|
273109
273762
|
if (!existsSync84(excludePath)) return;
|
|
273110
273763
|
try {
|
|
273111
273764
|
const current = readFileSync26(excludePath, "utf-8");
|
|
273112
|
-
const
|
|
273113
|
-
const legacyRelativeAiMergeRoot = relative22(projectRootDir, legacyAiMergeRoot);
|
|
273114
|
-
const entries = [`${legacyRelativeAiMergeRoot.replaceAll("\\", "/")}/`];
|
|
273115
|
-
const aiMergeRoot = resolveAiMergeRootPath(projectRootDir, settings);
|
|
273116
|
-
const relativeAiMergeRoot = relative22(projectRootDir, aiMergeRoot);
|
|
273117
|
-
if (relativeAiMergeRoot && !relativeAiMergeRoot.startsWith("..") && !isAbsolute25(relativeAiMergeRoot)) {
|
|
273118
|
-
entries.push(`${relativeAiMergeRoot.replaceAll("\\", "/")}/`);
|
|
273119
|
-
}
|
|
273765
|
+
const entries = resolveAiMergeSearchRoots(projectRootDir, settings).map((root) => relative22(projectRootDir, root)).filter((root) => root && !root.startsWith("..") && !isAbsolute25(root)).map((root) => `${root.replaceAll("\\", "/")}/`);
|
|
273120
273766
|
const missing = entries.filter((entry) => !current.split(/\r?\n/).includes(entry));
|
|
273121
273767
|
if (missing.length > 0) {
|
|
273122
273768
|
appendFileSync2(excludePath, `${current.endsWith("\n") ? "" : "\n"}${missing.join("\n")}
|
|
@@ -273132,7 +273778,7 @@ function resolveAiMergeRoot(projectRootDir, settings) {
|
|
|
273132
273778
|
return root;
|
|
273133
273779
|
}
|
|
273134
273780
|
function getAiMergeTempSearchRoots(projectRootDir, settings) {
|
|
273135
|
-
const roots = [resolveAiMergeRoot(projectRootDir, settings),
|
|
273781
|
+
const roots = [resolveAiMergeRoot(projectRootDir, settings), ...resolveAiMergeSearchRoots(projectRootDir, settings), tmpdir11()];
|
|
273136
273782
|
const testWorkerRoot = process.env.FUSION_TEST_WORKER_ROOT;
|
|
273137
273783
|
if (testWorkerRoot) {
|
|
273138
273784
|
try {
|
|
@@ -273185,7 +273831,7 @@ async function pruneExistingAiMergeWorktrees(taskId, projectRootDir, audit, log4
|
|
|
273185
273831
|
let alreadyAbsent = false;
|
|
273186
273832
|
try {
|
|
273187
273833
|
cleanupAttempted = true;
|
|
273188
|
-
await
|
|
273834
|
+
await execFileAsync31("git", ["worktree", "remove", "--force", canonicalPath], {
|
|
273189
273835
|
cwd: projectRootDir,
|
|
273190
273836
|
timeout: 3e4
|
|
273191
273837
|
});
|
|
@@ -273216,7 +273862,7 @@ async function pruneExistingAiMergeWorktrees(taskId, projectRootDir, audit, log4
|
|
|
273216
273862
|
}
|
|
273217
273863
|
if (cleanupAttempted) {
|
|
273218
273864
|
try {
|
|
273219
|
-
await
|
|
273865
|
+
await execFileAsync31("git", ["worktree", "prune"], { cwd: projectRootDir, timeout: 3e4 });
|
|
273220
273866
|
} catch (err) {
|
|
273221
273867
|
await log42(`AI merge pre-merge prune: git worktree prune failed: ${describeCleanupError(err)}`);
|
|
273222
273868
|
}
|
|
@@ -273282,7 +273928,7 @@ async function cleanupAiMergeWorktree(input) {
|
|
|
273282
273928
|
await audit.git({ type: "merge:ai-worktree-cleanup", target: canonicalRoot, metadata: { ...cleanupMetadata, phase: "git-prune", success: false, error: error3, ...code ? { code } : {} } });
|
|
273283
273929
|
}
|
|
273284
273930
|
}
|
|
273285
|
-
var
|
|
273931
|
+
var execFileAsync31;
|
|
273286
273932
|
var init_merger_ai_worktree = __esm({
|
|
273287
273933
|
"../engine/src/merge/merger-ai-worktree.ts"() {
|
|
273288
273934
|
"use strict";
|
|
@@ -273290,7 +273936,7 @@ var init_merger_ai_worktree = __esm({
|
|
|
273290
273936
|
init_self_healing();
|
|
273291
273937
|
init_worktree_paths();
|
|
273292
273938
|
init_worktree_removal_retry();
|
|
273293
|
-
|
|
273939
|
+
execFileAsync31 = promisify86(execFile37);
|
|
273294
273940
|
}
|
|
273295
273941
|
});
|
|
273296
273942
|
|
|
@@ -273642,8 +274288,8 @@ var init_merger_ai_prompts = __esm({
|
|
|
273642
274288
|
});
|
|
273643
274289
|
|
|
273644
274290
|
// ../engine/src/merge/merger-ai.ts
|
|
273645
|
-
import { execFile as
|
|
273646
|
-
import { promisify as
|
|
274291
|
+
import { execFile as execFile38 } from "node:child_process";
|
|
274292
|
+
import { promisify as promisify87 } from "node:util";
|
|
273647
274293
|
import { realpathSync as realpathSync15, readdirSync as readdirSync13 } from "node:fs";
|
|
273648
274294
|
import { mkdtemp as mkdtemp5 } from "node:fs/promises";
|
|
273649
274295
|
import { tmpdir as tmpdir12 } from "node:os";
|
|
@@ -273671,7 +274317,7 @@ function writeTransientMergeStatus(store, taskId, signal, status) {
|
|
|
273671
274317
|
return fence.write("lifecycle", () => store.updateTask(taskId, { status }).catch(() => void 0));
|
|
273672
274318
|
}
|
|
273673
274319
|
async function git9(args, cwd, opts = {}) {
|
|
273674
|
-
const { stdout } = await
|
|
274320
|
+
const { stdout } = await execFileAsync32("git", args, {
|
|
273675
274321
|
cwd,
|
|
273676
274322
|
encoding: "utf-8",
|
|
273677
274323
|
timeout: opts.timeout ?? 12e4,
|
|
@@ -273711,7 +274357,7 @@ function boundBlockingReviewReasons(reasons) {
|
|
|
273711
274357
|
}
|
|
273712
274358
|
function listAiMergeWorktreeCandidates(taskId, projectRootDir, settings) {
|
|
273713
274359
|
const prefix = `fusion-ai-merge-${taskId.toLowerCase()}-`;
|
|
273714
|
-
const roots = Array.from(/* @__PURE__ */ new Set([resolveAiMergeRoot(projectRootDir, settings),
|
|
274360
|
+
const roots = Array.from(/* @__PURE__ */ new Set([resolveAiMergeRoot(projectRootDir, settings), ...resolveAiMergeSearchRoots(projectRootDir, settings), tmpdir12()]));
|
|
273715
274361
|
const testWorkerRoot = process.env.FUSION_TEST_WORKER_ROOT;
|
|
273716
274362
|
if (testWorkerRoot) {
|
|
273717
274363
|
try {
|
|
@@ -276060,7 +276706,7 @@ async function finalizeTask(store, taskId, result2, audit, log42, rootDir, fence
|
|
|
276060
276706
|
function throwIfAborted3(signal, taskId) {
|
|
276061
276707
|
assertMergeGenerationOwned(signal, taskId);
|
|
276062
276708
|
}
|
|
276063
|
-
var
|
|
276709
|
+
var execFileAsync32, aiMergeLog, MAX_CONCURRENT_ADVANCE_RETRIES, MAX_BLOCKING_REVIEW_REASONS, AiMergeBlockedError, AiMergeReviewReconciliationInvalidatedError, LEGACY_COMPLETE_COLUMN, LEGACY_ARCHIVED_COLUMN, LEGACY_TERMINAL_COLUMNS3, LEGACY_REBOUND_COLUMN2, STRONG_LANDED_STRATEGIES, RecordedMergeBranchTipChangedError, WORKSPACE_REPO_LAND_OWNER_KEY, WorkspaceRepoLandBusyError, WorkspaceMergeTechnicalError, WorkspacePartialLandError, WorkspaceFinalizeBlockedError, WorkspaceReviewRequiredError, WorkspaceMergeDispatchSupersededError;
|
|
276064
276710
|
var init_merger_ai = __esm({
|
|
276065
276711
|
"../engine/src/merge/merger-ai.ts"() {
|
|
276066
276712
|
"use strict";
|
|
@@ -276110,7 +276756,7 @@ var init_merger_ai = __esm({
|
|
|
276110
276756
|
init_merger_ai_prompts();
|
|
276111
276757
|
init_merger_ai_worktree();
|
|
276112
276758
|
init_merger_ai_prompts();
|
|
276113
|
-
|
|
276759
|
+
execFileAsync32 = promisify87(execFile38);
|
|
276114
276760
|
aiMergeLog = createLogger2("merger-ai");
|
|
276115
276761
|
MAX_CONCURRENT_ADVANCE_RETRIES = 3;
|
|
276116
276762
|
MAX_BLOCKING_REVIEW_REASONS = 8;
|
|
@@ -276262,7 +276908,7 @@ var init_workspace_merge_dispatch_lease = __esm({
|
|
|
276262
276908
|
// ../engine/src/execution/task-revert.ts
|
|
276263
276909
|
import { exec as exec61 } from "node:child_process";
|
|
276264
276910
|
import { join as join97 } from "node:path";
|
|
276265
|
-
import { promisify as
|
|
276911
|
+
import { promisify as promisify88 } from "node:util";
|
|
276266
276912
|
function quoteShellArg9(value) {
|
|
276267
276913
|
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
276268
276914
|
}
|
|
@@ -277131,7 +277777,7 @@ var init_task_revert = __esm({
|
|
|
277131
277777
|
init_branch_attribution();
|
|
277132
277778
|
init_workspace_base_branch();
|
|
277133
277779
|
init_run_audit();
|
|
277134
|
-
defaultExecAsync2 =
|
|
277780
|
+
defaultExecAsync2 = promisify88(exec61);
|
|
277135
277781
|
GIT_TIMEOUT_MS9 = 3e4;
|
|
277136
277782
|
GIT_MAX_BUFFER7 = 10 * 1024 * 1024;
|
|
277137
277783
|
TaskRevertError = class extends Error {
|
|
@@ -277150,10 +277796,10 @@ var init_task_revert = __esm({
|
|
|
277150
277796
|
});
|
|
277151
277797
|
|
|
277152
277798
|
// ../engine/src/merge/smart-pull.ts
|
|
277153
|
-
import { execFile as
|
|
277154
|
-
import { promisify as
|
|
277799
|
+
import { execFile as execFile39 } from "node:child_process";
|
|
277800
|
+
import { promisify as promisify89 } from "node:util";
|
|
277155
277801
|
async function runGit8(args, cwd, timeoutMs) {
|
|
277156
|
-
const result2 = await
|
|
277802
|
+
const result2 = await execFileAsync33("git", args, {
|
|
277157
277803
|
cwd,
|
|
277158
277804
|
timeout: timeoutMs,
|
|
277159
277805
|
maxBuffer: 10 * 1024 * 1024,
|
|
@@ -277304,11 +277950,11 @@ async function smartPull(input) {
|
|
|
277304
277950
|
return { kind: "stash-pop-conflict", fromSha, toSha, stashSha, stashLabel, conflictedFiles };
|
|
277305
277951
|
}
|
|
277306
277952
|
}
|
|
277307
|
-
var
|
|
277953
|
+
var execFileAsync33;
|
|
277308
277954
|
var init_smart_pull = __esm({
|
|
277309
277955
|
"../engine/src/merge/smart-pull.ts"() {
|
|
277310
277956
|
"use strict";
|
|
277311
|
-
|
|
277957
|
+
execFileAsync33 = promisify89(execFile39);
|
|
277312
277958
|
}
|
|
277313
277959
|
});
|
|
277314
277960
|
|
|
@@ -278954,7 +279600,7 @@ var init_finalize_types = __esm({
|
|
|
278954
279600
|
|
|
278955
279601
|
// ../engine/src/experiment/git-ops.ts
|
|
278956
279602
|
import { exec as exec62 } from "node:child_process";
|
|
278957
|
-
import { promisify as
|
|
279603
|
+
import { promisify as promisify90 } from "node:util";
|
|
278958
279604
|
async function runGit9(cwd, args) {
|
|
278959
279605
|
const command = `git ${args.join(" ")}`;
|
|
278960
279606
|
try {
|
|
@@ -279061,7 +279707,7 @@ var init_git_ops = __esm({
|
|
|
279061
279707
|
"use strict";
|
|
279062
279708
|
init_git_identity();
|
|
279063
279709
|
init_finalize_types();
|
|
279064
|
-
execAsync57 =
|
|
279710
|
+
execAsync57 = promisify90(exec62);
|
|
279065
279711
|
GIT_TIMEOUT_MS10 = 3e4;
|
|
279066
279712
|
GIT_MAX_BUFFER8 = 10 * 1024 * 1024;
|
|
279067
279713
|
}
|
|
@@ -283685,9 +284331,9 @@ var init_routine_scheduler = __esm({
|
|
|
283685
284331
|
});
|
|
283686
284332
|
|
|
283687
284333
|
// ../engine/src/healing/stuck-task-detector.ts
|
|
283688
|
-
import { createHash as
|
|
284334
|
+
import { createHash as createHash38 } from "node:crypto";
|
|
283689
284335
|
function hashToolDetail(detail) {
|
|
283690
|
-
return
|
|
284336
|
+
return createHash38("sha256").update(detail).digest("hex").slice(0, TOOL_DETAIL_HASH_HEX_LEN);
|
|
283691
284337
|
}
|
|
283692
284338
|
function buildToolFingerprint(toolName, toolDetail) {
|
|
283693
284339
|
const name2 = toolName.trim().toLowerCase() || "tool";
|
|
@@ -286963,11 +287609,11 @@ var init_adapters = __esm({
|
|
|
286963
287609
|
|
|
286964
287610
|
// ../engine/src/cli-agent/resume-coordinator.ts
|
|
286965
287611
|
import { existsSync as existsSync87 } from "node:fs";
|
|
286966
|
-
import { execFile as
|
|
286967
|
-
import { promisify as
|
|
287612
|
+
import { execFile as execFile40 } from "node:child_process";
|
|
287613
|
+
import { promisify as promisify91 } from "node:util";
|
|
286968
287614
|
async function defaultIsWorktreeDirty(worktreePath) {
|
|
286969
287615
|
try {
|
|
286970
|
-
const { stdout } = await
|
|
287616
|
+
const { stdout } = await execFileAsync34("git", ["status", "--porcelain"], {
|
|
286971
287617
|
cwd: worktreePath
|
|
286972
287618
|
});
|
|
286973
287619
|
return stdout.trim().length > 0;
|
|
@@ -286975,13 +287621,13 @@ async function defaultIsWorktreeDirty(worktreePath) {
|
|
|
286975
287621
|
return false;
|
|
286976
287622
|
}
|
|
286977
287623
|
}
|
|
286978
|
-
var
|
|
287624
|
+
var execFileAsync34, ORPHANED_LIVE_STATES, DEFAULT_MAX_RESUME_ATTEMPTS, DEFAULT_RESUME_BACKOFF_BASE_MS, CliResumeCoordinator;
|
|
286979
287625
|
var init_resume_coordinator = __esm({
|
|
286980
287626
|
"../engine/src/cli-agent/resume-coordinator.ts"() {
|
|
286981
287627
|
"use strict";
|
|
286982
287628
|
init_session_manager();
|
|
286983
287629
|
init_state_machine();
|
|
286984
|
-
|
|
287630
|
+
execFileAsync34 = promisify91(execFile40);
|
|
286985
287631
|
ORPHANED_LIVE_STATES = /* @__PURE__ */ new Set([
|
|
286986
287632
|
"starting",
|
|
286987
287633
|
"ready",
|
|
@@ -287268,7 +287914,7 @@ var init_node_dispatch_validation = __esm({
|
|
|
287268
287914
|
});
|
|
287269
287915
|
|
|
287270
287916
|
// ../engine/src/runtimes/in-process-runtime.ts
|
|
287271
|
-
import { createHash as
|
|
287917
|
+
import { createHash as createHash39 } from "node:crypto";
|
|
287272
287918
|
import { EventEmitter as EventEmitter26 } from "node:events";
|
|
287273
287919
|
import { setImmediate as setImmediateCb4 } from "node:timers";
|
|
287274
287920
|
function createDiscoveryPluginLoaderOptions(scopedStore) {
|
|
@@ -287533,7 +288179,7 @@ function stableNotificationJson(value) {
|
|
|
287533
288179
|
return `{${fields.join(",")}}`;
|
|
287534
288180
|
}
|
|
287535
288181
|
function buildCliAgentNotificationDedupeKey(input) {
|
|
287536
|
-
const notificationFingerprint =
|
|
288182
|
+
const notificationFingerprint = createHash39("sha256").update(stableNotificationJson(input.info.notification ?? null)).digest("hex").slice(0, 16);
|
|
287537
288183
|
const waitingEpoch = input.session?.updatedAt ?? "unknown-waiting-epoch";
|
|
287538
288184
|
return [
|
|
287539
288185
|
"cli-agent",
|
|
@@ -291614,8 +292260,8 @@ var init_provider_adapters = __esm({
|
|
|
291614
292260
|
|
|
291615
292261
|
// ../engine/src/remote-access/tunnel-process-manager.ts
|
|
291616
292262
|
import { EventEmitter as EventEmitter31 } from "node:events";
|
|
291617
|
-
import { exec as exec64, execFile as
|
|
291618
|
-
import { promisify as
|
|
292263
|
+
import { exec as exec64, execFile as execFile41, spawn as spawn9 } from "node:child_process";
|
|
292264
|
+
import { promisify as promisify92 } from "node:util";
|
|
291619
292265
|
function serveConfigScopes(config3) {
|
|
291620
292266
|
const foreground = Object.values(config3.Foreground ?? {}).filter(
|
|
291621
292267
|
(scope) => Boolean(scope)
|
|
@@ -291661,7 +292307,7 @@ function toStateError(code, err) {
|
|
|
291661
292307
|
at: nowIso2()
|
|
291662
292308
|
};
|
|
291663
292309
|
}
|
|
291664
|
-
var DEFAULT_MAX_LOG_ENTRIES, DEFAULT_STOP_TIMEOUT_MS2, DEFAULT_RESTART_BASE_DELAY_MS, DEFAULT_RESTART_MAX_DELAY_MS,
|
|
292310
|
+
var DEFAULT_MAX_LOG_ENTRIES, DEFAULT_STOP_TIMEOUT_MS2, DEFAULT_RESTART_BASE_DELAY_MS, DEFAULT_RESTART_MAX_DELAY_MS, execFileAsync35, execAsync58, LineBuffer, TunnelProcessManager;
|
|
291665
292311
|
var init_tunnel_process_manager = __esm({
|
|
291666
292312
|
"../engine/src/remote-access/tunnel-process-manager.ts"() {
|
|
291667
292313
|
"use strict";
|
|
@@ -291672,8 +292318,8 @@ var init_tunnel_process_manager = __esm({
|
|
|
291672
292318
|
DEFAULT_STOP_TIMEOUT_MS2 = 5e3;
|
|
291673
292319
|
DEFAULT_RESTART_BASE_DELAY_MS = 1e3;
|
|
291674
292320
|
DEFAULT_RESTART_MAX_DELAY_MS = 3e4;
|
|
291675
|
-
|
|
291676
|
-
execAsync58 =
|
|
292321
|
+
execFileAsync35 = promisify92(execFile41);
|
|
292322
|
+
execAsync58 = promisify92(exec64);
|
|
291677
292323
|
LineBuffer = class {
|
|
291678
292324
|
pending = "";
|
|
291679
292325
|
push(chunk) {
|
|
@@ -291778,7 +292424,7 @@ var init_tunnel_process_manager = __esm({
|
|
|
291778
292424
|
return null;
|
|
291779
292425
|
}
|
|
291780
292426
|
try {
|
|
291781
|
-
const { stdout } = await
|
|
292427
|
+
const { stdout } = await execFileAsync35("tailscale", ["status", "--json"], { timeout: 3e3 });
|
|
291782
292428
|
const data = JSON.parse(String(stdout));
|
|
291783
292429
|
const dnsName = data.Self?.DNSName?.replace(/\.$/, "");
|
|
291784
292430
|
if (!dnsName) {
|
|
@@ -291801,7 +292447,7 @@ var init_tunnel_process_manager = __esm({
|
|
|
291801
292447
|
];
|
|
291802
292448
|
for (const resetCommand of resetCommands) {
|
|
291803
292449
|
try {
|
|
291804
|
-
await
|
|
292450
|
+
await execFileAsync35(resetCommand.command, resetCommand.args, { timeout: 5e3 });
|
|
291805
292451
|
return;
|
|
291806
292452
|
} catch {
|
|
291807
292453
|
}
|
|
@@ -291907,7 +292553,7 @@ var init_tunnel_process_manager = __esm({
|
|
|
291907
292553
|
async detectActiveFunnel() {
|
|
291908
292554
|
let stdout = "";
|
|
291909
292555
|
try {
|
|
291910
|
-
const result2 = await
|
|
292556
|
+
const result2 = await execFileAsync35("tailscale", ["serve", "status", "--json"], { timeout: 5e3 });
|
|
291911
292557
|
stdout = String(result2.stdout ?? "");
|
|
291912
292558
|
} catch (error3) {
|
|
291913
292559
|
const failure = error3;
|
|
@@ -292325,8 +292971,8 @@ var init_tunnel_process_manager = __esm({
|
|
|
292325
292971
|
});
|
|
292326
292972
|
|
|
292327
292973
|
// ../engine/src/remote-access/remote-tunnel-service.ts
|
|
292328
|
-
import { execFile as
|
|
292329
|
-
import { promisify as
|
|
292974
|
+
import { execFile as execFile42 } from "node:child_process";
|
|
292975
|
+
import { promisify as promisify93 } from "node:util";
|
|
292330
292976
|
function remoteTunnelScopeKey(input) {
|
|
292331
292977
|
const projectId2 = input.projectId?.trim();
|
|
292332
292978
|
if (projectId2) return `project:${projectId2}`;
|
|
@@ -292369,14 +293015,14 @@ async function shutdownAllRemoteTunnels() {
|
|
|
292369
293015
|
function __resetRemoteTunnelServicesForTests() {
|
|
292370
293016
|
remoteTunnelServices.clear();
|
|
292371
293017
|
}
|
|
292372
|
-
var
|
|
293018
|
+
var execFileAsync36, isRemoteActive, RemoteTunnelService, remoteTunnelServices;
|
|
292373
293019
|
var init_remote_tunnel_service = __esm({
|
|
292374
293020
|
"../engine/src/remote-access/remote-tunnel-service.ts"() {
|
|
292375
293021
|
"use strict";
|
|
292376
293022
|
init_logger3();
|
|
292377
293023
|
init_local_dashboard_port();
|
|
292378
293024
|
init_tunnel_process_manager();
|
|
292379
|
-
|
|
293025
|
+
execFileAsync36 = promisify93(execFile42);
|
|
292380
293026
|
isRemoteActive = (ra) => ra?.activeProvider != null && (ra.providers[ra.activeProvider]?.enabled ?? false);
|
|
292381
293027
|
RemoteTunnelService = class {
|
|
292382
293028
|
manager = new TunnelProcessManager();
|
|
@@ -292725,7 +293371,7 @@ var init_remote_tunnel_service = __esm({
|
|
|
292725
293371
|
async checkTailscaleDaemonReady() {
|
|
292726
293372
|
let stdout = "";
|
|
292727
293373
|
try {
|
|
292728
|
-
const result2 = await
|
|
293374
|
+
const result2 = await execFileAsync36("tailscale", ["status", "--json"], {
|
|
292729
293375
|
timeout: 5e3,
|
|
292730
293376
|
maxBuffer: 8 * 1024 * 1024
|
|
292731
293377
|
});
|
|
@@ -292773,7 +293419,7 @@ var init_remote_tunnel_service = __esm({
|
|
|
292773
293419
|
async checkExecutableAvailable(command) {
|
|
292774
293420
|
const checker = process.platform === "win32" ? "where" : "which";
|
|
292775
293421
|
try {
|
|
292776
|
-
await
|
|
293422
|
+
await execFileAsync36(checker, [command]);
|
|
292777
293423
|
return { available: true };
|
|
292778
293424
|
} catch {
|
|
292779
293425
|
return {
|
|
@@ -292788,8 +293434,8 @@ var init_remote_tunnel_service = __esm({
|
|
|
292788
293434
|
});
|
|
292789
293435
|
|
|
292790
293436
|
// ../engine/src/project-engine.ts
|
|
292791
|
-
import { execFile as
|
|
292792
|
-
import { promisify as
|
|
293437
|
+
import { execFile as execFile43 } from "node:child_process";
|
|
293438
|
+
import { promisify as promisify94 } from "node:util";
|
|
292793
293439
|
function emitMergeRequestShadowDequeueParityAudit(store, legacyTaskId, shadowTaskId) {
|
|
292794
293440
|
const agree = shadowTaskId === legacyTaskId;
|
|
292795
293441
|
void emitBoundedRunAudit2(store, {
|
|
@@ -292844,7 +293490,7 @@ async function verifyMergeConfirmedReachability(args) {
|
|
|
292844
293490
|
return { reachable: true, skipped: "no-integration-branch" };
|
|
292845
293491
|
}
|
|
292846
293492
|
try {
|
|
292847
|
-
await
|
|
293493
|
+
await execFileAsync37("git", ["cat-file", "-e", `${commitSha}^{commit}`], {
|
|
292848
293494
|
cwd,
|
|
292849
293495
|
timeout: 1e4
|
|
292850
293496
|
});
|
|
@@ -292853,7 +293499,7 @@ async function verifyMergeConfirmedReachability(args) {
|
|
|
292853
293499
|
return { reachable: false, reason: "commit-missing", diagnostic };
|
|
292854
293500
|
}
|
|
292855
293501
|
try {
|
|
292856
|
-
await
|
|
293502
|
+
await execFileAsync37(
|
|
292857
293503
|
"git",
|
|
292858
293504
|
["merge-base", "--is-ancestor", commitSha, `refs/heads/${integrationBranch}`],
|
|
292859
293505
|
{ cwd, timeout: 1e4 }
|
|
@@ -292869,7 +293515,7 @@ async function verifyMergeConfirmedReachability(args) {
|
|
|
292869
293515
|
return { reachable: false, reason: "git-error", diagnostic };
|
|
292870
293516
|
}
|
|
292871
293517
|
}
|
|
292872
|
-
var WorkspaceMergeDispatchBusyError2,
|
|
293518
|
+
var WorkspaceMergeDispatchBusyError2, execFileAsync37, MERGE_HANDOFF_GRACE_MS, PR_MERGE_RETRY_BACKOFF_BASE_MS, deterministicMergerModeDeprecationWarnedProjects, ProjectEngine;
|
|
292873
293519
|
var init_project_engine = __esm({
|
|
292874
293520
|
"../engine/src/project-engine.ts"() {
|
|
292875
293521
|
"use strict";
|
|
@@ -292902,6 +293548,7 @@ var init_project_engine = __esm({
|
|
|
292902
293548
|
init_merger_ai();
|
|
292903
293549
|
init_group_merge_coordinator();
|
|
292904
293550
|
init_workspace_review_reroute();
|
|
293551
|
+
init_stale_content_review_reroute();
|
|
292905
293552
|
init_workspace_integration_target();
|
|
292906
293553
|
init_concurrency();
|
|
292907
293554
|
init_merge_reclaim_policy();
|
|
@@ -292928,7 +293575,7 @@ var init_project_engine = __esm({
|
|
|
292928
293575
|
}
|
|
292929
293576
|
retryable = true;
|
|
292930
293577
|
};
|
|
292931
|
-
|
|
293578
|
+
execFileAsync37 = promisify94(execFile43);
|
|
292932
293579
|
MERGE_HANDOFF_GRACE_MS = 300;
|
|
292933
293580
|
PR_MERGE_RETRY_BACKOFF_BASE_MS = 5e3;
|
|
292934
293581
|
deterministicMergerModeDeprecationWarnedProjects = /* @__PURE__ */ new Set();
|
|
@@ -292992,6 +293639,7 @@ var init_project_engine = __esm({
|
|
|
292992
293639
|
}
|
|
292993
293640
|
});
|
|
292994
293641
|
}
|
|
293642
|
+
staleContentRerouteAuditKeys = /* @__PURE__ */ new Set();
|
|
292995
293643
|
runtime;
|
|
292996
293644
|
started = false;
|
|
292997
293645
|
specDriftReconciler;
|
|
@@ -294788,11 +295436,44 @@ ${detail}`);
|
|
|
294788
295436
|
workspaceRootDir: this.config.workingDirectory,
|
|
294789
295437
|
settings
|
|
294790
295438
|
});
|
|
294791
|
-
|
|
295439
|
+
const blocker = getTaskMergeBlocker(task, {
|
|
294792
295440
|
reviewColumns: mergeGate.reviewColumns.size > 0 ? mergeGate.reviewColumns : /* @__PURE__ */ new Set(["in-review"]),
|
|
294793
295441
|
requiredPreMergeStepIds: mergeGate.requiredPreMergeStepIds,
|
|
294794
295442
|
mergeContent
|
|
294795
295443
|
});
|
|
295444
|
+
if (blocker === "task has a pre-merge approval recorded against different content" && mergeContent.kind === "singular") {
|
|
295445
|
+
const reroute = await rerouteSingularStaleContentToReview(store, task, {
|
|
295446
|
+
requiredPreMergeStepIds: mergeGate.requiredPreMergeStepIds,
|
|
295447
|
+
mergeContent
|
|
295448
|
+
}).catch(() => ({
|
|
295449
|
+
rerouted: false,
|
|
295450
|
+
reason: "no-progress",
|
|
295451
|
+
nodeId: void 0,
|
|
295452
|
+
workflowStepId: void 0
|
|
295453
|
+
}));
|
|
295454
|
+
if (reroute.rerouted) {
|
|
295455
|
+
await store.logEntry(task.id, `[pre-merge] Code Review re-entry is owned by the workflow graph after stale content evidence was refused.`);
|
|
295456
|
+
}
|
|
295457
|
+
const auditKey = `${task.id}:${reroute.reason}`;
|
|
295458
|
+
if (!this.staleContentRerouteAuditKeys.has(auditKey)) {
|
|
295459
|
+
this.staleContentRerouteAuditKeys.add(auditKey);
|
|
295460
|
+
await emitBoundedRunAudit2(store, {
|
|
295461
|
+
taskId: task.id,
|
|
295462
|
+
agentId: "merge-gate",
|
|
295463
|
+
runId: `${task.id}:merge-gate`,
|
|
295464
|
+
domain: "database",
|
|
295465
|
+
mutationType: "task:merge-stale-content-review-rerouted",
|
|
295466
|
+
target: task.id,
|
|
295467
|
+
metadata: {
|
|
295468
|
+
taskId: task.id,
|
|
295469
|
+
nodeId: reroute.nodeId,
|
|
295470
|
+
workflowStepId: reroute.workflowStepId,
|
|
295471
|
+
reason: reroute.reason
|
|
295472
|
+
}
|
|
295473
|
+
});
|
|
295474
|
+
}
|
|
295475
|
+
}
|
|
295476
|
+
return blocker;
|
|
294796
295477
|
}
|
|
294797
295478
|
/**
|
|
294798
295479
|
* Remove and return the highest-priority taskId from the merge queue.
|
|
@@ -295638,7 +296319,7 @@ ${detail}`);
|
|
|
295638
296319
|
}
|
|
295639
296320
|
const checklist = planConfirmedMergeChecklistReconciliation(task);
|
|
295640
296321
|
if (checklist.skippedStepIndexes.length > 0 || checklist.reconciledWorkflowStepIds.length > 0) {
|
|
295641
|
-
const steps = task.steps.map((step, index2) => checklist.skippedStepIndexes.includes(index2) ? { ...step, status: "skipped" } : step);
|
|
296322
|
+
const steps = (task.steps ?? []).map((step, index2) => checklist.skippedStepIndexes.includes(index2) ? { ...step, status: "skipped" } : step);
|
|
295642
296323
|
const workflowStepResults = (task.workflowStepResults ?? []).map((result2) => checklist.reconciledWorkflowStepIds.includes(result2.workflowStepId) ? { ...result2, status: "skipped" } : result2);
|
|
295643
296324
|
await store.updateTask(taskId, { steps, workflowStepResults });
|
|
295644
296325
|
task.steps = steps;
|
|
@@ -297384,9 +298065,9 @@ import { access as access12, unlink as unlink12, writeFile as writeFile31 } from
|
|
|
297384
298065
|
import net2 from "node:net";
|
|
297385
298066
|
import { platform as platform3, tmpdir as tmpdir13 } from "node:os";
|
|
297386
298067
|
import { join as join100 } from "node:path";
|
|
297387
|
-
import { createHash as
|
|
298068
|
+
import { createHash as createHash40 } from "node:crypto";
|
|
297388
298069
|
function projectHash(projectId2) {
|
|
297389
|
-
return
|
|
298070
|
+
return createHash40("sha1").update(projectId2).digest("hex").slice(0, 16);
|
|
297390
298071
|
}
|
|
297391
298072
|
function computeEngineSocketPath(projectId2) {
|
|
297392
298073
|
const hash3 = projectHash(projectId2);
|
|
@@ -299004,8 +299685,8 @@ var init_remote_access = __esm({
|
|
|
299004
299685
|
});
|
|
299005
299686
|
|
|
299006
299687
|
// ../engine/src/healing/archive-worktree-disposer-install.ts
|
|
299007
|
-
import { execFile as
|
|
299008
|
-
import { promisify as
|
|
299688
|
+
import { execFile as execFile44 } from "node:child_process";
|
|
299689
|
+
import { promisify as promisify95 } from "node:util";
|
|
299009
299690
|
function installBaselineArchiveWorktreeDisposer(store, input) {
|
|
299010
299691
|
const allowLiveRemoval = input.allowLiveRemoval ?? (() => false);
|
|
299011
299692
|
const unregisterSingle = getArchiveWorktreeDisposer(store) ? () => {
|
|
@@ -299027,7 +299708,7 @@ function installBaselineArchiveWorktreeDisposer(store, input) {
|
|
|
299027
299708
|
try {
|
|
299028
299709
|
if (await canonicalizeWorktreePath(entry.worktreePath) === await canonicalizeWorktreePath(entry.repoRootDir)) throw new Error("Refusing to remove workspace repository root");
|
|
299029
299710
|
await removeWorktree({ worktreePath: entry.worktreePath, rootDir: entry.repoRootDir, settings: await input.getSettings(), taskId: task.id, reason: RemovalReason.ExecutorDispose, force: true });
|
|
299030
|
-
await
|
|
299711
|
+
await execFileAsync38("git", ["branch", "-D", entry.branch], { cwd: entry.repoRootDir, timeout: 12e4, maxBuffer: 10 * 1024 * 1024 });
|
|
299031
299712
|
if (task.workspaceWorktrees) for (const repoRel of [entry.repoRel, ...entry.aliasRepoRels]) delete task.workspaceWorktrees[repoRel];
|
|
299032
299713
|
removed.push(entry.repoRel);
|
|
299033
299714
|
} catch (error3) {
|
|
@@ -299041,13 +299722,13 @@ function installBaselineArchiveWorktreeDisposer(store, input) {
|
|
|
299041
299722
|
unregisterSingle();
|
|
299042
299723
|
};
|
|
299043
299724
|
}
|
|
299044
|
-
var
|
|
299725
|
+
var execFileAsync38;
|
|
299045
299726
|
var init_archive_worktree_disposer_install = __esm({
|
|
299046
299727
|
"../engine/src/healing/archive-worktree-disposer-install.ts"() {
|
|
299047
299728
|
"use strict";
|
|
299048
299729
|
init_src2();
|
|
299049
299730
|
init_worktree_backend();
|
|
299050
|
-
|
|
299731
|
+
execFileAsync38 = promisify95(execFile44);
|
|
299051
299732
|
}
|
|
299052
299733
|
});
|
|
299053
299734
|
|
|
@@ -300900,7 +301581,7 @@ import { exec as exec65 } from "node:child_process";
|
|
|
300900
301581
|
import { mkdtemp as mkdtemp7, rm as rm18 } from "node:fs/promises";
|
|
300901
301582
|
import { tmpdir as tmpdir14 } from "node:os";
|
|
300902
301583
|
import { join as join101 } from "node:path";
|
|
300903
|
-
import { promisify as
|
|
301584
|
+
import { promisify as promisify96 } from "node:util";
|
|
300904
301585
|
function resolveCommentAuthor(input) {
|
|
300905
301586
|
const login = input.login || "unknown";
|
|
300906
301587
|
const authorIsBot = Boolean(
|
|
@@ -301369,7 +302050,7 @@ var init_github = __esm({
|
|
|
301369
302050
|
"use strict";
|
|
301370
302051
|
init_src2();
|
|
301371
302052
|
init_issue_image_attachments();
|
|
301372
|
-
execAsync59 =
|
|
302053
|
+
execAsync59 = promisify96(exec65);
|
|
301373
302054
|
DiscussionsDisabledError = class extends Error {
|
|
301374
302055
|
name = "DiscussionsDisabledError";
|
|
301375
302056
|
constructor(owner, repo, cause) {
|
|
@@ -308726,7 +309407,7 @@ var init_knowledge_index_refresh = __esm({
|
|
|
308726
309407
|
});
|
|
308727
309408
|
|
|
308728
309409
|
// ../dashboard/src/pr-metadata-generator.ts
|
|
308729
|
-
import { promisify as
|
|
309410
|
+
import { promisify as promisify97 } from "node:util";
|
|
308730
309411
|
import { exec as execCb } from "node:child_process";
|
|
308731
309412
|
import { access as access13, readFile as readFile52 } from "node:fs/promises";
|
|
308732
309413
|
import { join as join102 } from "node:path";
|
|
@@ -309018,7 +309699,7 @@ var init_pr_metadata_generator = __esm({
|
|
|
309018
309699
|
"use strict";
|
|
309019
309700
|
init_src2();
|
|
309020
309701
|
init_src5();
|
|
309021
|
-
execAsync60 =
|
|
309702
|
+
execAsync60 = promisify97(execCb);
|
|
309022
309703
|
PR_METADATA_TIMEOUT_MS = 6e4;
|
|
309023
309704
|
PR_METADATA_SYSTEM_PROMPT = [
|
|
309024
309705
|
"You generate GitHub pull request metadata for Fusion tasks.",
|
|
@@ -309035,13 +309716,13 @@ var init_pr_metadata_generator = __esm({
|
|
|
309035
309716
|
});
|
|
309036
309717
|
|
|
309037
309718
|
// ../dashboard/src/routes/resolve-diff-base.ts
|
|
309038
|
-
import { execFile as
|
|
309039
|
-
import { promisify as
|
|
309040
|
-
var
|
|
309719
|
+
import { execFile as execFile45 } from "node:child_process";
|
|
309720
|
+
import { promisify as promisify98 } from "node:util";
|
|
309721
|
+
var execFileAsync39;
|
|
309041
309722
|
var init_resolve_diff_base = __esm({
|
|
309042
309723
|
"../dashboard/src/routes/resolve-diff-base.ts"() {
|
|
309043
309724
|
"use strict";
|
|
309044
|
-
|
|
309725
|
+
execFileAsync39 = promisify98(execFile45);
|
|
309045
309726
|
}
|
|
309046
309727
|
});
|
|
309047
309728
|
|
|
@@ -309082,7 +309763,7 @@ var init_git_worktree_safety = __esm({
|
|
|
309082
309763
|
|
|
309083
309764
|
// ../dashboard/src/routes/register-git-github.ts
|
|
309084
309765
|
import { exec as execCb2, spawn as spawn10 } from "node:child_process";
|
|
309085
|
-
import { promisify as
|
|
309766
|
+
import { promisify as promisify99 } from "node:util";
|
|
309086
309767
|
var severityAuditLog30, execAsync61, PR_ROUTE_MAX_BUFFER_BYTES, GITHUB_TRACKING_RECONCILE_INTERVAL_MS;
|
|
309087
309768
|
var init_register_git_github = __esm({
|
|
309088
309769
|
"../dashboard/src/routes/register-git-github.ts"() {
|
|
@@ -309114,7 +309795,7 @@ var init_register_git_github = __esm({
|
|
|
309114
309795
|
init_resolve_diff_base();
|
|
309115
309796
|
init_git_worktree_safety();
|
|
309116
309797
|
severityAuditLog30 = createLogger("dashboard-register-git-github");
|
|
309117
|
-
execAsync61 =
|
|
309798
|
+
execAsync61 = promisify99(execCb2);
|
|
309118
309799
|
PR_ROUTE_MAX_BUFFER_BYTES = 10 * 1024 * 1024;
|
|
309119
309800
|
GITHUB_TRACKING_RECONCILE_INTERVAL_MS = 15 * 60 * 1e3;
|
|
309120
309801
|
}
|
|
@@ -316051,13 +316732,13 @@ var init_register_agents_projects_nodes = __esm({
|
|
|
316051
316732
|
});
|
|
316052
316733
|
|
|
316053
316734
|
// ../dashboard/src/exec-file.ts
|
|
316054
|
-
import { execFile as
|
|
316055
|
-
import { promisify as
|
|
316056
|
-
var
|
|
316735
|
+
import { execFile as execFile46 } from "node:child_process";
|
|
316736
|
+
import { promisify as promisify100 } from "node:util";
|
|
316737
|
+
var execFileAsync40;
|
|
316057
316738
|
var init_exec_file = __esm({
|
|
316058
316739
|
"../dashboard/src/exec-file.ts"() {
|
|
316059
316740
|
"use strict";
|
|
316060
|
-
|
|
316741
|
+
execFileAsync40 = promisify100(execFile46);
|
|
316061
316742
|
}
|
|
316062
316743
|
});
|
|
316063
316744
|
|
|
@@ -327335,7 +328016,7 @@ var init_register_fn_binary_routes = __esm({
|
|
|
327335
328016
|
|
|
327336
328017
|
// ../dashboard/src/update-check.ts
|
|
327337
328018
|
import { exec as exec66 } from "node:child_process";
|
|
327338
|
-
import { promisify as
|
|
328019
|
+
import { promisify as promisify101 } from "node:util";
|
|
327339
328020
|
var INSTALL_MAX_BUFFER, DAY_MS, execAsync62;
|
|
327340
328021
|
var init_update_check = __esm({
|
|
327341
328022
|
"../dashboard/src/update-check.ts"() {
|
|
@@ -327343,7 +328024,7 @@ var init_update_check = __esm({
|
|
|
327343
328024
|
init_src2();
|
|
327344
328025
|
INSTALL_MAX_BUFFER = 10 * 1024 * 1024;
|
|
327345
328026
|
DAY_MS = 24 * 60 * 60 * 1e3;
|
|
327346
|
-
execAsync62 =
|
|
328027
|
+
execAsync62 = promisify101(exec66);
|
|
327347
328028
|
}
|
|
327348
328029
|
});
|
|
327349
328030
|
|
|
@@ -327434,7 +328115,7 @@ var init_types5 = __esm({
|
|
|
327434
328115
|
});
|
|
327435
328116
|
|
|
327436
328117
|
// ../dashboard/src/stt/model-manager.ts
|
|
327437
|
-
import { createHash as
|
|
328118
|
+
import { createHash as createHash41, randomUUID as randomUUID63 } from "node:crypto";
|
|
327438
328119
|
import { mkdir as mkdir34, open as open5, readFile as readFile56, readdir as readdir14, rename as rename13, rm as rm21, stat as stat15, writeFile as writeFile33 } from "node:fs/promises";
|
|
327439
328120
|
import { join as join121, relative as relative25, resolve as resolve62, sep as sep20 } from "node:path";
|
|
327440
328121
|
function parseSafeTarListing(listing) {
|
|
@@ -327523,7 +328204,7 @@ function createVoiceModelManager(options = {}) {
|
|
|
327523
328204
|
if (!response.ok || !response.body) throw Object.assign(new Error("download failed"), { voiceReason: "network" });
|
|
327524
328205
|
if (!current(g2, signal)) return state;
|
|
327525
328206
|
const total = Number(response.headers.get("content-length")) || void 0;
|
|
327526
|
-
const hash3 =
|
|
328207
|
+
const hash3 = createHash41("sha256");
|
|
327527
328208
|
let bytes = 0;
|
|
327528
328209
|
for await (const chunk of response.body) {
|
|
327529
328210
|
if (!current(g2, signal)) return state;
|