@runfusion/fusion 0.74.0-beta.0 → 0.74.0-beta.1
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 +9456 -8529
- package/dist/child-process-worker.js +223 -25
- package/dist/client/.vite/manifest.json +256 -256
- package/dist/client/assets/{AgentDetailView-CUXS0Odh.js → AgentDetailView-Bopzxiqb.js} +1 -1
- package/dist/client/assets/{AgentPermissionPolicyEditor-CzjHjB5r.js → AgentPermissionPolicyEditor-i5N7rUlL.js} +1 -1
- package/dist/client/assets/{AgentsView-B5stgI5m.js → AgentsView-M3GoJDHH.js} +3 -3
- package/dist/client/assets/ChatView-CqiyA9Kt.js +13 -0
- package/dist/client/assets/{CommandCenter-BdEQ_ZOX.js → CommandCenter-CAvMGKhl.js} +1 -1
- package/dist/client/assets/{DevServerView-BHgAmF3y.js → DevServerView-wqM6h3nV.js} +1 -1
- package/dist/client/assets/{DirectoryPicker-BQXVc5YW.js → DirectoryPicker-C8OyXCE-.js} +1 -1
- package/dist/client/assets/{DocumentsView-CxN0Ptrj.js → DocumentsView-CjNMZQi8.js} +1 -1
- package/dist/client/assets/{EvalsView-DAgJtpO5.js → EvalsView-BVlbuB5t.js} +1 -1
- package/dist/client/assets/{ExperimentalAgentOnboardingModal-NZcXkGrN.js → ExperimentalAgentOnboardingModal-CIwCg8sq.js} +1 -1
- package/dist/client/assets/{GoalsView-Dwq7NW4j.js → GoalsView-Cnw2igil.js} +1 -1
- package/dist/client/assets/{InsightsView-CUlL5NSC.js → InsightsView-D7GmD-Kx.js} +1 -1
- package/dist/client/assets/{MemoryView-WfHzJflp.js → MemoryView-BlqkfIE5.js} +1 -1
- package/dist/client/assets/{PiExtensionsManager-BS1dkauB.js → PiExtensionsManager-EC94zLMq.js} +1 -1
- package/dist/client/assets/{PluginManager-B1oLb0pn.js → PluginManager-pYyCD3uh.js} +1 -1
- package/dist/client/assets/{PullRequestView-Cdp662lx.js → PullRequestView-BAb0vVhu.js} +1 -1
- package/dist/client/assets/{ReportModal-C92wQO-k.js → ReportModal-COmReivA.js} +1 -1
- package/dist/client/assets/{ResearchView-4-SoxmQv.js → ResearchView-DLMo4rFw.js} +1 -1
- package/dist/client/assets/{SecretsView-C5UQ1Mms.js → SecretsView-w_O8NLfw.js} +1 -1
- package/dist/client/assets/{SessionTerminal-BTjX9p3a.js → SessionTerminal-CSPi-qWE.js} +1 -1
- package/dist/client/assets/{SettingsModal-B37HBcKT.css → SettingsModal-BF1KzZ0q.css} +1 -1
- package/dist/client/assets/SettingsModal-C9bVvYQq.js +21 -0
- package/dist/client/assets/{SettingsModal-BfHAE14s.js → SettingsModal-wilrGXvE.js} +1 -1
- package/dist/client/assets/{SettingsTextareaRow-C2JqzQdD.js → SettingsTextareaRow-Bd7_SxVv.js} +1 -1
- package/dist/client/assets/{SetupWizardModal-C1KmMVfU.js → SetupWizardModal-sPs6Lw3a.js} +2 -2
- package/dist/client/assets/{SkillsView-DyLNdfDy.js → SkillsView-B9PvYS8t.js} +1 -1
- package/dist/client/assets/{TodoView-DyrniX19.js → TodoView-Df0SD_JT.js} +1 -1
- package/dist/client/assets/{WorkflowNodeEditor-Bh-Hn1Kx.js → WorkflowNodeEditor-B3kFD-S0.js} +1 -1
- package/dist/client/assets/{agent-import-generation-C5pyefIj.js → agent-import-generation-OXfU1-D1.js} +1 -1
- package/dist/client/assets/{app-YM47G7Ks.js → app-DJIiVHdA.js} +1 -1
- package/dist/client/assets/{app-DNrauoYS.js → app-DMZ_RusZ.js} +3 -3
- package/dist/client/assets/{app-Bl764LdY.js → app-DaikOPcV.js} +3 -3
- package/dist/client/assets/{app-QmIotwFZ.js → app-Dn1u7zJ9.js} +3 -3
- package/dist/client/assets/{app-DdCnRHSe.js → app-DxTbBEMH.js} +3 -3
- package/dist/client/assets/{app-oUEtzFOj.js → app-hQw_x2KJ.js} +3 -3
- package/dist/client/assets/{architectureDiagram-3BPJPVTR-B6axGlaS.js → architectureDiagram-3BPJPVTR-B_8zk4ag.js} +1 -1
- package/dist/client/assets/{blockDiagram-GPEHLZMM-BENjJaZD.js → blockDiagram-GPEHLZMM-CpDKBJkO.js} +1 -1
- package/dist/client/assets/{c4Diagram-AAUBKEIU-Cl2qKhuO.js → c4Diagram-AAUBKEIU-D3wtfGzI.js} +1 -1
- package/dist/client/assets/channel-BLzjKIVz.js +1 -0
- package/dist/client/assets/{chunk-2J33WTMH-BWo7R8T7.js → chunk-2J33WTMH-DS9sHIMv.js} +1 -1
- package/dist/client/assets/{chunk-4BX2VUAB-DiRoI7pq.js → chunk-4BX2VUAB-B-xW6cfi.js} +1 -1
- package/dist/client/assets/{chunk-55IACEB6-DPtv1GVO.js → chunk-55IACEB6-Ddxf-sPU.js} +1 -1
- package/dist/client/assets/{chunk-727SXJPM-BVcm5ITs.js → chunk-727SXJPM-Bv_Z1w57.js} +1 -1
- package/dist/client/assets/{chunk-AQP2D5EJ-CFT4bmXK.js → chunk-AQP2D5EJ-DYHYN43E.js} +1 -1
- package/dist/client/assets/{chunk-FMBD7UC4-BDcEHQ0o.js → chunk-FMBD7UC4-wuuFvvBk.js} +1 -1
- package/dist/client/assets/{chunk-ND2GUHAM-CYlDBFdI.js → chunk-ND2GUHAM-DfVRkVZo.js} +1 -1
- package/dist/client/assets/{chunk-QZHKN3VN-3Wv3WxYt.js → chunk-QZHKN3VN-D0t6ryuh.js} +1 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-DkwPy8u9.js +1 -0
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-DkwPy8u9.js +1 -0
- package/dist/client/assets/{cose-bilkent-S5V4N54A-BuMkKBMC.js → cose-bilkent-S5V4N54A-DVlKqNFJ.js} +1 -1
- package/dist/client/assets/{dagre-BM42HDAG-D1P4z_OM.js → dagre-BM42HDAG-DTtiGxz-.js} +1 -1
- package/dist/client/assets/{dashboard-view-CcK2sH0v.js → dashboard-view-CLjYqvE9.js} +1 -1
- package/dist/client/assets/{dashboard-view-DaRKU5oU.js → dashboard-view-D-nDgSmP.js} +1 -1
- package/dist/client/assets/{dashboard-view-BgQBLynI.js → dashboard-view-DH99T6VJ.js} +1 -1
- package/dist/client/assets/{diagram-2AECGRRQ-hmY-reWF.js → diagram-2AECGRRQ-Tv-YxCWk.js} +1 -1
- package/dist/client/assets/{diagram-5GNKFQAL-CGfRqm_0.js → diagram-5GNKFQAL-DlAAPkGu.js} +1 -1
- package/dist/client/assets/{diagram-KO2AKTUF-BfKo4Jd4.js → diagram-KO2AKTUF-DisatTBB.js} +1 -1
- package/dist/client/assets/{diagram-LMA3HP47-BZqpNemd.js → diagram-LMA3HP47-CDrUxjzW.js} +1 -1
- package/dist/client/assets/{diagram-OG6HWLK6-CxLTV4DH.js → diagram-OG6HWLK6-BQ34a4Ej.js} +1 -1
- package/dist/client/assets/{erDiagram-TEJ5UH35-vw3tx2tK.js → erDiagram-TEJ5UH35-s-YHwAEU.js} +1 -1
- package/dist/client/assets/{flowDiagram-I6XJVG4X-OEm-Us2U.js → flowDiagram-I6XJVG4X-EpXzmG2d.js} +1 -1
- package/dist/client/assets/{folder-open-D_zgZHWi.js → folder-open-DN86xUly.js} +1 -1
- package/dist/client/assets/{ganttDiagram-6RSMTGT7-C5bc1DG1.js → ganttDiagram-6RSMTGT7-Dk2WaoX8.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-PVQCEYII-DEvcWRBq.js → gitGraphDiagram-PVQCEYII-CjchnKW0.js} +1 -1
- package/dist/client/assets/index-Dv-95s50.css +1 -0
- package/dist/client/assets/index-aGZ3DHQw.js +2671 -0
- package/dist/client/assets/{infoDiagram-5YYISTIA-kFOE9wxd.js → infoDiagram-5YYISTIA-CiU-twoj.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-DvLbzHmR.js → ishikawaDiagram-YF4QCWOH-BvylyUKK.js} +1 -1
- package/dist/client/assets/{journeyDiagram-JHISSGLW-ov6Tbcuz.js → journeyDiagram-JHISSGLW-Ca6z84KB.js} +1 -1
- package/dist/client/assets/{kanban-definition-UN3LZRKU-Dr0foW2M.js → kanban-definition-UN3LZRKU-DXbw2-s-.js} +1 -1
- package/dist/client/assets/{mermaid.core-CM55309V.js → mermaid.core-DkS33D12.js} +4 -4
- package/dist/client/assets/{mindmap-definition-RKZ34NQL-xNyB6Z6o.js → mindmap-definition-RKZ34NQL-BgXuWPDD.js} +1 -1
- package/dist/client/assets/{pieDiagram-4H26LBE5-DlS5Kpga.js → pieDiagram-4H26LBE5-CnOzTN6U.js} +1 -1
- package/dist/client/assets/{puzzle-BrEvi5DH.js → puzzle-Dxl1kcLF.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-W4KKPZXB-D4z2CHAA.js → quadrantDiagram-W4KKPZXB-DI3s1u95.js} +1 -1
- package/dist/client/assets/{requirementDiagram-4Y6WPE33-Bcwt6-p9.js → requirementDiagram-4Y6WPE33-Ck97mo-W.js} +1 -1
- package/dist/client/assets/{sankeyDiagram-5OEKKPKP-C54N76yk.js → sankeyDiagram-5OEKKPKP-Z3w8NJac.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-3UESZ5HK-DtqryztE.js → sequenceDiagram-3UESZ5HK-DLGtWgfy.js} +1 -1
- package/dist/client/assets/{shield-alert-DhxKVKek.js → shield-alert-BCGxgBpM.js} +1 -1
- package/dist/client/assets/{standing-instructions-template-CdHJwmLI.js → standing-instructions-template-CUE6ItG6.js} +1 -1
- package/dist/client/assets/{stateDiagram-AJRCARHV-DQAvSrHw.js → stateDiagram-AJRCARHV-C6Zl2EJW.js} +1 -1
- package/dist/client/assets/{stateDiagram-v2-BHNVJYJU-BzIGKq7y.js → stateDiagram-v2-BHNVJYJU-BA77mDAW.js} +1 -1
- package/dist/client/assets/{timeline-definition-PNZ67QCA-GDj_48Um.js → timeline-definition-PNZ67QCA-D9Cp15Hm.js} +1 -1
- package/dist/client/assets/{upload-B7GKZiF1.js → upload-2jCicylS.js} +1 -1
- package/dist/client/assets/{users-CBtvFVLM.js → users-C1TTGAfX.js} +1 -1
- package/dist/client/assets/{vennDiagram-CIIHVFJN-PQDmLFbj.js → vennDiagram-CIIHVFJN-BwFSh6Tr.js} +1 -1
- package/dist/client/assets/{wardley-L42UT6IY-GmGtXctI.js → wardley-L42UT6IY-CQknAo24.js} +1 -1
- package/dist/client/assets/{wardleyDiagram-YWT4CUSO-Bv6slmsW.js → wardleyDiagram-YWT4CUSO-Dwc8f8bd.js} +1 -1
- package/dist/client/assets/{xychartDiagram-2RQKCTM6-CK1RJHwB.js → xychartDiagram-2RQKCTM6-CPkeHv8g.js} +1 -1
- package/dist/client/index.html +2 -2
- package/dist/client/version.json +1 -1
- package/dist/extension.js +6436 -5628
- package/package.json +1 -1
- package/dist/client/assets/ChatView-CpoOgZ4X.js +0 -13
- package/dist/client/assets/SettingsModal-BcnOOo9g.js +0 -21
- package/dist/client/assets/channel-CktWdAhK.js +0 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-CrUS4gHO.js +0 -1
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-CrUS4gHO.js +0 -1
- package/dist/client/assets/index-BinRUCFV.js +0 -2661
- package/dist/client/assets/index-DGmuyTtv.css +0 -1
|
@@ -1663,6 +1663,7 @@ var init_settings_schema = __esm({
|
|
|
1663
1663
|
defaultProvider: void 0,
|
|
1664
1664
|
defaultModelId: void 0,
|
|
1665
1665
|
testMode: void 0,
|
|
1666
|
+
voiceInput: void 0,
|
|
1666
1667
|
modelPricingOverrides: void 0,
|
|
1667
1668
|
modelPricingFetchedAt: void 0,
|
|
1668
1669
|
modelPricingSource: void 0,
|
|
@@ -1954,6 +1955,7 @@ var init_settings_schema = __esm({
|
|
|
1954
1955
|
// with this on but auto-merge off, review threads are resolved but the PR is not merged.
|
|
1955
1956
|
autoResolveReviewComments: true,
|
|
1956
1957
|
testMode: void 0,
|
|
1958
|
+
voiceInput: void 0,
|
|
1957
1959
|
mergeRequestContractShadowEnabled: false,
|
|
1958
1960
|
mergeStrategy: "direct",
|
|
1959
1961
|
directMergeCommitStrategy: "always-squash",
|
|
@@ -18387,9 +18389,13 @@ function buildRefinementSeedPrompt(title, description) {
|
|
|
18387
18389
|
${description}
|
|
18388
18390
|
`;
|
|
18389
18391
|
}
|
|
18392
|
+
function normalizeSeedText(content) {
|
|
18393
|
+
return content.replace(/\r\n/g, "\n").replace(/[ \t]+$/gm, "").trimEnd();
|
|
18394
|
+
}
|
|
18390
18395
|
function isUnplannedSeedPrompt(content, taskId, title, description) {
|
|
18391
|
-
|
|
18392
|
-
|
|
18396
|
+
const normalized = normalizeSeedText(content);
|
|
18397
|
+
if (normalized === normalizeSeedText(buildBootstrapPrompt(taskId, title, description))) return true;
|
|
18398
|
+
return title !== void 0 && normalized === normalizeSeedText(buildRefinementSeedPrompt(title, description));
|
|
18393
18399
|
}
|
|
18394
18400
|
var init_mesh_task_replication = __esm({
|
|
18395
18401
|
"../core/src/mesh-task-replication.ts"() {
|
|
@@ -29650,9 +29656,11 @@ var init_agent_store = __esm({
|
|
|
29650
29656
|
`Invalid state transition: ${currentState} -> ${newState}. Valid transitions: ${validTransitions.join(", ")}`
|
|
29651
29657
|
);
|
|
29652
29658
|
}
|
|
29659
|
+
const clearsPauseReasonOnResume = (currentState === "paused" || currentState === "error") && (newState === "active" || newState === "idle" || newState === "running");
|
|
29653
29660
|
const updated = {
|
|
29654
29661
|
...agent,
|
|
29655
29662
|
state: newState,
|
|
29663
|
+
...clearsPauseReasonOnResume && { pauseReason: void 0 },
|
|
29656
29664
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
29657
29665
|
};
|
|
29658
29666
|
await this.writeAgent(updated);
|
|
@@ -64738,11 +64746,18 @@ async function moveTaskInternalImpl(store, id, toColumn, options, internal, curr
|
|
|
64738
64746
|
const isLegacyRecoveryRehome = options?.recoveryRehome === true && sourceIsLegacy && COLUMNS.includes(toColumn);
|
|
64739
64747
|
const isWorkflowDeclaredRecoveryRehome = options?.recoveryRehome === true && !COLUMNS.includes(toColumn) && workflowHasColumn(await resolveTaskWorkflowIrForMove(store, id), toColumn);
|
|
64740
64748
|
if (!isEvacuation && !isLegacyRecoveryRehome && !isWorkflowDeclaredRecoveryRehome) {
|
|
64741
|
-
const
|
|
64742
|
-
if (!
|
|
64743
|
-
|
|
64744
|
-
|
|
64749
|
+
const legacyTargets = sourceIsLegacy ? VALID_TRANSITIONS[task.column] ?? [] : [];
|
|
64750
|
+
if (!legacyTargets.includes(toColumn)) {
|
|
64751
|
+
const workflowTargets = resolveAllowedColumns(
|
|
64752
|
+
await resolveTaskWorkflowIrForMove(store, id),
|
|
64753
|
+
task.column
|
|
64745
64754
|
);
|
|
64755
|
+
const validTargets = [.../* @__PURE__ */ new Set([...legacyTargets, ...workflowTargets])];
|
|
64756
|
+
if (!validTargets.includes(toColumn)) {
|
|
64757
|
+
throw new Error(
|
|
64758
|
+
`Invalid transition: '${task.column}' \u2192 '${toColumn}'. Valid targets: ${validTargets.join(", ") || "none"}`
|
|
64759
|
+
);
|
|
64760
|
+
}
|
|
64746
64761
|
}
|
|
64747
64762
|
}
|
|
64748
64763
|
if (fromColumn === "in-review" && toColumn === "done" && !options?.skipMergeBlocker) {
|
|
@@ -87812,7 +87827,8 @@ async function _createTaskInternalBackendImpl(store, input, title, resolvedWorkf
|
|
|
87812
87827
|
ownsStagingDirectory = true;
|
|
87813
87828
|
if (store.isWatching) store.taskCache.set(id, { ...task });
|
|
87814
87829
|
await store.writeTaskJsonFile(stagingDir, task);
|
|
87815
|
-
const
|
|
87830
|
+
const isUnplannedStartCreate = options?.resolvedEntryColumn !== void 0 && options.resolvedEntryColumn !== "triage" && task.column === "todo";
|
|
87831
|
+
const isIntakeColumn = task.column === "triage" || options?.resolvedEntryColumn !== void 0 && task.column === options.resolvedEntryColumn || isUnplannedStartCreate;
|
|
87816
87832
|
const usedBootstrapPrompt = !options?.promptOverride && isIntakeColumn;
|
|
87817
87833
|
const prompt = options?.promptOverride ?? (isIntakeColumn ? buildBootstrapPrompt(id, task.title, task.description) : store.generateSpecifiedPrompt(task));
|
|
87818
87834
|
if (!usedBootstrapPrompt) {
|
|
@@ -88264,7 +88280,8 @@ async function _createTaskInternalImpl(store, input, title, resolvedWorkflowStep
|
|
|
88264
88280
|
const dir = store.taskDir(id);
|
|
88265
88281
|
await store.atomicCreateTaskJson(dir, task, "createTask");
|
|
88266
88282
|
if (store.isWatching) store.taskCache.set(id, { ...task });
|
|
88267
|
-
const
|
|
88283
|
+
const isUnplannedStartCreate = options?.resolvedEntryColumn !== void 0 && options.resolvedEntryColumn !== "triage" && task.column === "todo";
|
|
88284
|
+
const isIntakeColumn = task.column === "triage" || options?.resolvedEntryColumn !== void 0 && task.column === options.resolvedEntryColumn || isUnplannedStartCreate;
|
|
88268
88285
|
const usedBootstrapPrompt = !options?.promptOverride && isIntakeColumn;
|
|
88269
88286
|
const prompt = options?.promptOverride ?? (isIntakeColumn ? buildBootstrapPrompt(id, task.title, task.description) : store.generateSpecifiedPrompt(task));
|
|
88270
88287
|
if (!usedBootstrapPrompt) {
|
|
@@ -136153,15 +136170,26 @@ function countCapacitySlot(allTasks, effectiveWorkflowIdByTask, budgetColumns, w
|
|
|
136153
136170
|
}
|
|
136154
136171
|
return count2;
|
|
136155
136172
|
}
|
|
136173
|
+
function trackHeld(taskId, reason, nowMs) {
|
|
136174
|
+
const existing = heldSince.get(taskId);
|
|
136175
|
+
if (!existing || existing.reason !== reason) {
|
|
136176
|
+
heldSince.set(taskId, { reason, sinceMs: nowMs });
|
|
136177
|
+
return 0;
|
|
136178
|
+
}
|
|
136179
|
+
return nowMs - existing.sinceMs;
|
|
136180
|
+
}
|
|
136156
136181
|
async function runHoldReleaseSweep(store, deps) {
|
|
136157
136182
|
const result = { released: [], held: [] };
|
|
136183
|
+
const sweepStartedMs = deps.now();
|
|
136158
136184
|
const settings = await store.getSettings();
|
|
136159
136185
|
const allTasks = await store.listTasks({ includeArchived: false });
|
|
136160
136186
|
const irCache = /* @__PURE__ */ new Map();
|
|
136161
136187
|
const effectiveWorkflowIdByTask = /* @__PURE__ */ new Map();
|
|
136188
|
+
const prefetchStartedMs = deps.now();
|
|
136162
136189
|
for (const t of allTasks) {
|
|
136163
136190
|
effectiveWorkflowIdByTask.set(t.id, await effectiveWorkflowId(store, t.id));
|
|
136164
136191
|
}
|
|
136192
|
+
const prefetchMs = deps.now() - prefetchStartedMs;
|
|
136165
136193
|
for (const task of allTasks) {
|
|
136166
136194
|
if (task.paused || task.userPaused) {
|
|
136167
136195
|
continue;
|
|
@@ -136176,6 +136204,7 @@ async function runHoldReleaseSweep(store, deps) {
|
|
|
136176
136204
|
if (!column || !holdConfig) continue;
|
|
136177
136205
|
const release2 = typeof holdConfig.release === "string" ? holdConfig.release : "manual";
|
|
136178
136206
|
if (release2 === "manual" || release2 === "external-event") {
|
|
136207
|
+
trackHeld(task.id, `${release2}-only`, deps.now());
|
|
136179
136208
|
result.held.push({ taskId: task.id, reason: `${release2}-only` });
|
|
136180
136209
|
continue;
|
|
136181
136210
|
}
|
|
@@ -136184,18 +136213,21 @@ async function runHoldReleaseSweep(store, deps) {
|
|
|
136184
136213
|
const deadline = resolveTimerDeadline(holdConfig, task);
|
|
136185
136214
|
shouldRelease = deadline !== void 0 && deps.now() >= deadline;
|
|
136186
136215
|
if (!shouldRelease) {
|
|
136216
|
+
trackHeld(task.id, "timer-not-elapsed", deps.now());
|
|
136187
136217
|
result.held.push({ taskId: task.id, reason: "timer-not-elapsed" });
|
|
136188
136218
|
continue;
|
|
136189
136219
|
}
|
|
136190
136220
|
} else if (release2 === "dependency") {
|
|
136191
136221
|
shouldRelease = await allDependenciesSatisfied(store, task, allTasks);
|
|
136192
136222
|
if (!shouldRelease) {
|
|
136223
|
+
trackHeld(task.id, "deps-unsatisfied", deps.now());
|
|
136193
136224
|
result.held.push({ taskId: task.id, reason: "deps-unsatisfied" });
|
|
136194
136225
|
continue;
|
|
136195
136226
|
}
|
|
136196
136227
|
} else if (release2 === "capacity") {
|
|
136197
136228
|
const target2 = resolveReleaseTarget(ir2, task.column, true);
|
|
136198
136229
|
if (!target2) {
|
|
136230
|
+
trackHeld(task.id, "no-downstream-capacity-column", deps.now());
|
|
136199
136231
|
result.held.push({ taskId: task.id, reason: "no-downstream-capacity-column" });
|
|
136200
136232
|
continue;
|
|
136201
136233
|
}
|
|
@@ -136205,6 +136237,7 @@ async function runHoldReleaseSweep(store, deps) {
|
|
|
136205
136237
|
const budgetColumns = new Set(resolveWipBudgetColumns(ir2, target2));
|
|
136206
136238
|
const occupants = countCapacitySlot(allTasks, effectiveWorkflowIdByTask, budgetColumns, workflowId, capacity.countPending);
|
|
136207
136239
|
if (occupants >= capacity.limit) {
|
|
136240
|
+
trackHeld(task.id, "downstream-full", deps.now());
|
|
136208
136241
|
result.held.push({ taskId: task.id, reason: "downstream-full" });
|
|
136209
136242
|
continue;
|
|
136210
136243
|
}
|
|
@@ -136214,16 +136247,40 @@ async function runHoldReleaseSweep(store, deps) {
|
|
|
136214
136247
|
if (!shouldRelease) continue;
|
|
136215
136248
|
const target = resolveReleaseTarget(ir2, task.column, release2 === "capacity");
|
|
136216
136249
|
if (!target) {
|
|
136250
|
+
trackHeld(task.id, "no-release-target", deps.now());
|
|
136217
136251
|
result.held.push({ taskId: task.id, reason: "no-release-target" });
|
|
136218
136252
|
continue;
|
|
136219
136253
|
}
|
|
136220
136254
|
const released = await issueRelease(store, deps, task, target, ir2);
|
|
136221
136255
|
if (released) {
|
|
136256
|
+
const waitedMs = deps.now() - (heldSince.get(task.id)?.sinceMs ?? deps.now());
|
|
136257
|
+
heldSince.delete(task.id);
|
|
136258
|
+
schedulerLog.log(
|
|
136259
|
+
`Hold release for ${task.id} \u2192 ${target} after ${waitedMs}ms held (release=${release2})`
|
|
136260
|
+
);
|
|
136222
136261
|
result.released.push(task.id);
|
|
136223
136262
|
} else {
|
|
136263
|
+
trackHeld(task.id, "move-rejected-or-no-slot", deps.now());
|
|
136224
136264
|
result.held.push({ taskId: task.id, reason: "move-rejected-or-no-slot" });
|
|
136225
136265
|
}
|
|
136226
136266
|
}
|
|
136267
|
+
const sweepMs = deps.now() - sweepStartedMs;
|
|
136268
|
+
const longestHeldMs = result.held.reduce((max2, h) => {
|
|
136269
|
+
const entry = heldSince.get(h.taskId);
|
|
136270
|
+
return entry ? Math.max(max2, deps.now() - entry.sinceMs) : max2;
|
|
136271
|
+
}, 0);
|
|
136272
|
+
const summary = `Hold-release sweep: ${sweepMs}ms (prefetch ${prefetchMs}ms over ${allTasks.length} tasks), released=${result.released.length}, held=${result.held.length}` + (longestHeldMs > 0 ? `, longest held ${longestHeldMs}ms` : "");
|
|
136273
|
+
if (sweepMs >= SLOW_SWEEP_WARN_MS) {
|
|
136274
|
+
schedulerLog.warn(`${summary} \u2014 sweep exceeded ${SLOW_SWEEP_WARN_MS}ms and is itself the delay`);
|
|
136275
|
+
} else if (result.released.length > 0) {
|
|
136276
|
+
schedulerLog.log(summary);
|
|
136277
|
+
} else {
|
|
136278
|
+
schedulerLog.debug(summary);
|
|
136279
|
+
}
|
|
136280
|
+
const stillHeld = new Set(result.held.map((h) => h.taskId));
|
|
136281
|
+
for (const taskId of [...heldSince.keys()]) {
|
|
136282
|
+
if (!stillHeld.has(taskId)) heldSince.delete(taskId);
|
|
136283
|
+
}
|
|
136227
136284
|
return result;
|
|
136228
136285
|
}
|
|
136229
136286
|
async function issueRelease(store, deps, task, target, ir2) {
|
|
@@ -136326,12 +136383,15 @@ async function releaseHeldTaskByEvent(store, taskId, eventTag, deps = {}) {
|
|
|
136326
136383
|
);
|
|
136327
136384
|
return released ? { released: true, toColumn: target } : { released: false, rejection: "capacity-exhausted-or-no-slot" };
|
|
136328
136385
|
}
|
|
136386
|
+
var heldSince, SLOW_SWEEP_WARN_MS;
|
|
136329
136387
|
var init_hold_release = __esm({
|
|
136330
136388
|
"../engine/src/hold-release.ts"() {
|
|
136331
136389
|
"use strict";
|
|
136332
136390
|
init_src2();
|
|
136333
136391
|
init_logger();
|
|
136334
136392
|
init_spec_staleness();
|
|
136393
|
+
heldSince = /* @__PURE__ */ new Map();
|
|
136394
|
+
SLOW_SWEEP_WARN_MS = 2e3;
|
|
136335
136395
|
}
|
|
136336
136396
|
});
|
|
136337
136397
|
|
|
@@ -191897,6 +191957,15 @@ var Scheduler = class {
|
|
|
191897
191957
|
this.schedule();
|
|
191898
191958
|
}
|
|
191899
191959
|
}
|
|
191960
|
+
if (task.status === "planning") {
|
|
191961
|
+
this.planningTaskIds.add(task.id);
|
|
191962
|
+
} else if (this.planningTaskIds.has(task.id)) {
|
|
191963
|
+
this.planningTaskIds.delete(task.id);
|
|
191964
|
+
if (this.running && !task.status && !task.paused && !task.userPaused && (task.column === "todo" || task.column === "triage")) {
|
|
191965
|
+
schedulerLog.log(`Task ${task.id} finished planning \u2014 triggering scheduling`);
|
|
191966
|
+
this.schedule();
|
|
191967
|
+
}
|
|
191968
|
+
}
|
|
191900
191969
|
if (!this.options.prMonitor) return;
|
|
191901
191970
|
if (task.column !== "in-review") return;
|
|
191902
191971
|
if (!task.prInfo) return;
|
|
@@ -191914,6 +191983,7 @@ var Scheduler = class {
|
|
|
191914
191983
|
this.lastAutoClaimFingerprint.delete(task.id);
|
|
191915
191984
|
this.options.snapshotManager?.invalidate("task:deleted");
|
|
191916
191985
|
this.pausedTaskIds.delete(task.id);
|
|
191986
|
+
this.planningTaskIds.delete(task.id);
|
|
191917
191987
|
this.failedTaskIds.delete(task.id);
|
|
191918
191988
|
this.recentEngineTodoRequeues.delete(task.id);
|
|
191919
191989
|
this.wasNodeDispatchValidationBlocked.delete(task.id);
|
|
@@ -191986,6 +192056,13 @@ var Scheduler = class {
|
|
|
191986
192056
|
activePollMs = null;
|
|
191987
192057
|
/** Tracks which task IDs are currently paused, to detect unpause transitions. */
|
|
191988
192058
|
pausedTaskIds = /* @__PURE__ */ new Set();
|
|
192059
|
+
/**
|
|
192060
|
+
* FNXC:CodingIdeasWorkflow 2026-07-25-13:10:
|
|
192061
|
+
* Tracks task IDs last seen with status "planning", so the planning -> dispatchable transition
|
|
192062
|
+
* can trigger an immediate scheduling pass. Plan-in-place workflows clear status without a
|
|
192063
|
+
* task:moved, so this is the only signal that the card just became executable.
|
|
192064
|
+
*/
|
|
192065
|
+
planningTaskIds = /* @__PURE__ */ new Set();
|
|
191989
192066
|
/** Tracks mission-linked tasks observed with status=failed before moveTask clears status/error. */
|
|
191990
192067
|
failedTaskIds = /* @__PURE__ */ new Set();
|
|
191991
192068
|
/** Tracks tasks blocked by unavailable-node policy to deduplicate block log entries. */
|
|
@@ -192405,7 +192482,7 @@ var Scheduler = class {
|
|
|
192405
192482
|
todo.map(async (t) => {
|
|
192406
192483
|
try {
|
|
192407
192484
|
const content = await readFile30(getPromptPath(this.store.getTasksDir(), t.id), "utf-8");
|
|
192408
|
-
if (content
|
|
192485
|
+
if (isUnplannedSeedPrompt(content, t.id, t.title, t.description)) return null;
|
|
192409
192486
|
} catch {
|
|
192410
192487
|
}
|
|
192411
192488
|
return t;
|
|
@@ -202218,6 +202295,44 @@ function renderRoomCoordinationPromptBlock(decision, pendingMessage) {
|
|
|
202218
202295
|
];
|
|
202219
202296
|
}
|
|
202220
202297
|
|
|
202298
|
+
// ../engine/src/reports-health.ts
|
|
202299
|
+
var OPERATOR_ACTIONABLE_PAUSE_REASONS = /* @__PURE__ */ new Set([
|
|
202300
|
+
"error-unrecoverable",
|
|
202301
|
+
"error-retry-exhausted",
|
|
202302
|
+
"heartbeat-model-unavailable"
|
|
202303
|
+
]);
|
|
202304
|
+
function classifyReportHealth(input) {
|
|
202305
|
+
const pauseReason = input.pauseReason?.trim();
|
|
202306
|
+
if (pauseReason) {
|
|
202307
|
+
if (OPERATOR_ACTIONABLE_PAUSE_REASONS.has(pauseReason)) {
|
|
202308
|
+
return {
|
|
202309
|
+
bucket: "operator-actionable",
|
|
202310
|
+
cellText: `**needs operator repair** (${pauseReason})`
|
|
202311
|
+
};
|
|
202312
|
+
}
|
|
202313
|
+
return {
|
|
202314
|
+
bucket: "paused",
|
|
202315
|
+
cellText: `paused (${pauseReason})`
|
|
202316
|
+
};
|
|
202317
|
+
}
|
|
202318
|
+
if (input.state === "error") {
|
|
202319
|
+
return { bucket: "operator-actionable", cellText: "**needs operator repair**" };
|
|
202320
|
+
}
|
|
202321
|
+
if (input.staleParkedAssignment) {
|
|
202322
|
+
return { bucket: "stale-assignment", cellText: "**stale** assignment" };
|
|
202323
|
+
}
|
|
202324
|
+
if (input.state === "running" && input.heartbeatAgeMs > input.heartbeatTimeoutMs * 2) {
|
|
202325
|
+
return { bucket: "stuck", cellText: "**stuck**" };
|
|
202326
|
+
}
|
|
202327
|
+
if ((input.state === "active" || input.state === "idle") && input.heartbeatAgeMs > input.staleThresholdMs) {
|
|
202328
|
+
return { bucket: "stale", cellText: "**stale**" };
|
|
202329
|
+
}
|
|
202330
|
+
if (input.state === "paused") {
|
|
202331
|
+
return { bucket: "paused", cellText: "paused" };
|
|
202332
|
+
}
|
|
202333
|
+
return { bucket: "healthy", cellText: "healthy" };
|
|
202334
|
+
}
|
|
202335
|
+
|
|
202221
202336
|
// ../engine/src/agent-heartbeat.ts
|
|
202222
202337
|
init_session_token_usage();
|
|
202223
202338
|
|
|
@@ -205323,26 +205438,28 @@ ${trimPromptMd(taskDetail.prompt, promptTemplate)}` : "No PROMPT.md available.",
|
|
|
205323
205438
|
heartbeatLog.warn(`[reports-health] failed to validate task link for ${report.id}/${report.taskId}: ${error2 instanceof Error ? error2.message : String(error2)}`);
|
|
205324
205439
|
}
|
|
205325
205440
|
}
|
|
205326
|
-
|
|
205327
|
-
|
|
205328
|
-
|
|
205329
|
-
|
|
205330
|
-
|
|
205331
|
-
|
|
205332
|
-
|
|
205333
|
-
}
|
|
205334
|
-
|
|
205335
|
-
} else if ((report.state === "active" || report.state === "idle") && heartbeatAgeMs > staleThresholdMs) {
|
|
205336
|
-
health = "**stale**";
|
|
205441
|
+
const classification = classifyReportHealth({
|
|
205442
|
+
state: report.state,
|
|
205443
|
+
pauseReason: report.pauseReason,
|
|
205444
|
+
heartbeatAgeMs,
|
|
205445
|
+
heartbeatTimeoutMs,
|
|
205446
|
+
staleThresholdMs,
|
|
205447
|
+
staleParkedAssignment
|
|
205448
|
+
});
|
|
205449
|
+
if (classification.bucket === "stale") {
|
|
205337
205450
|
heartbeatLog.log(`[reports-health] stale report ${report.id} intervalSource=${intervalSource} staleThresholdMs=${staleThresholdMs} heartbeatAgeMs=${heartbeatAgeMs}`);
|
|
205338
205451
|
}
|
|
205339
205452
|
const task = renderedTask;
|
|
205340
205453
|
const state = renderedState;
|
|
205341
205454
|
const heartbeat = formatRelativeTime(report.lastHeartbeatAt);
|
|
205342
|
-
return
|
|
205455
|
+
return {
|
|
205456
|
+
classification,
|
|
205457
|
+
row: `| ${report.name} | ${state} | ${task} | ${heartbeat} | ${classification.cellText} |`
|
|
205458
|
+
};
|
|
205343
205459
|
}));
|
|
205344
|
-
const hasStuck = rows.some((
|
|
205345
|
-
const hasStale = rows.some((
|
|
205460
|
+
const hasStuck = rows.some(({ classification }) => classification.bucket === "stuck");
|
|
205461
|
+
const hasStale = rows.some(({ classification }) => classification.bucket === "stale" || classification.bucket === "stale-assignment");
|
|
205462
|
+
const hasOperatorActionable = rows.some(({ classification }) => classification.bucket === "operator-actionable");
|
|
205346
205463
|
const actionLines = ["### Actions for Unresponsive Reports"];
|
|
205347
205464
|
if (hasStuck) {
|
|
205348
205465
|
actionLines.push("- For **stuck** reports: first check task-log/step progress, the active heartbeat run, and worktree/session liveness. If work is live, do not stop or reassign it; request status if needed. Reassign only after no live session and no forward progress are confirmed.");
|
|
@@ -205350,6 +205467,9 @@ ${trimPromptMd(taskDetail.prompt, promptTemplate)}` : "No PROMPT.md available.",
|
|
|
205350
205467
|
if (hasStale) {
|
|
205351
205468
|
actionLines.push("- For **stale** reports: the agent may have lost its heartbeat trigger \u2014 create a follow-up task to investigate.");
|
|
205352
205469
|
}
|
|
205470
|
+
if (hasOperatorActionable) {
|
|
205471
|
+
actionLines.push("- For reports that **need operator repair**: notify the operator and create a follow-up task; do not reassign work until the parked agent's configuration or access issue is repaired.");
|
|
205472
|
+
}
|
|
205353
205473
|
return [
|
|
205354
205474
|
"## Reports Health Check",
|
|
205355
205475
|
"",
|
|
@@ -205357,7 +205477,7 @@ ${trimPromptMd(taskDetail.prompt, promptTemplate)}` : "No PROMPT.md available.",
|
|
|
205357
205477
|
"",
|
|
205358
205478
|
"| Name | State | Task | Last Heartbeat | Health |",
|
|
205359
205479
|
"|------|-------|------|----------------|--------|",
|
|
205360
|
-
...rows,
|
|
205480
|
+
...rows.map(({ row }) => row),
|
|
205361
205481
|
"",
|
|
205362
205482
|
...actionLines
|
|
205363
205483
|
].join("\n");
|
|
@@ -241396,12 +241516,30 @@ var TriageProcessor = class _TriageProcessor {
|
|
|
241396
241516
|
this.activeSessions.delete(task.id);
|
|
241397
241517
|
}
|
|
241398
241518
|
};
|
|
241519
|
+
this.taskColumnWakeHandler = (task) => {
|
|
241520
|
+
if (!task?.id) return;
|
|
241521
|
+
if (task.column !== "todo" && task.column !== "triage") return;
|
|
241522
|
+
if (task.paused === true || task.userPaused === true) return;
|
|
241523
|
+
if (this.processing.has(task.id) || this.hasLivePlanningWork(task.id)) return;
|
|
241524
|
+
this.requestImmediatePoll();
|
|
241525
|
+
};
|
|
241399
241526
|
}
|
|
241400
241527
|
running = false;
|
|
241401
241528
|
polling = false;
|
|
241402
241529
|
pollInterval = null;
|
|
241403
241530
|
/** The interval (ms) of the currently active `setInterval` timer. */
|
|
241404
241531
|
activePollMs = null;
|
|
241532
|
+
/*
|
|
241533
|
+
FNXC:CodingIdeasWorkflow 2026-07-25-11:20:
|
|
241534
|
+
Event-wake state for requestImmediatePoll(). Planning discovery is timer-driven, so pressing
|
|
241535
|
+
Start on an Ideas card (which only writes a column change) used to wait out the remainder of the
|
|
241536
|
+
poll interval — up to pollIntervalMs, 15s by default — before anything even looked at the card.
|
|
241537
|
+
`nudgeTimer` debounces a burst of moves into one poll; `nudgeDuringPoll` remembers a nudge that
|
|
241538
|
+
arrived while a poll was already in flight, since that poll may have snapshotted the task list
|
|
241539
|
+
before the move landed and would otherwise drop the wake entirely.
|
|
241540
|
+
*/
|
|
241541
|
+
nudgeTimer = null;
|
|
241542
|
+
nudgeDuringPoll = false;
|
|
241405
241543
|
processing = /* @__PURE__ */ new Set();
|
|
241406
241544
|
/** Synchronous ownership fence shared with advanced-triage self-healing. */
|
|
241407
241545
|
advancedRecoveryReservations = /* @__PURE__ */ new Set();
|
|
@@ -241441,6 +241579,8 @@ var TriageProcessor = class _TriageProcessor {
|
|
|
241441
241579
|
stuckAborted = /* @__PURE__ */ new Set();
|
|
241442
241580
|
taskDeletedHandler;
|
|
241443
241581
|
taskPausedHandler;
|
|
241582
|
+
/** FNXC:CodingIdeasWorkflow 2026-07-25-11:20: store-event wake for planning-eligible columns. */
|
|
241583
|
+
taskColumnWakeHandler;
|
|
241444
241584
|
_approvalRequestStore;
|
|
241445
241585
|
/**
|
|
241446
241586
|
* @param store — Task store instance (also used to listen for `settings:updated` events)
|
|
@@ -241545,6 +241685,10 @@ var TriageProcessor = class _TriageProcessor {
|
|
|
241545
241685
|
if (this.taskPausedHandler && typeof this.store.on === "function") {
|
|
241546
241686
|
this.store.on("task:updated", this.taskPausedHandler);
|
|
241547
241687
|
}
|
|
241688
|
+
if (this.taskColumnWakeHandler && typeof this.store.on === "function") {
|
|
241689
|
+
this.store.on("task:updated", this.taskColumnWakeHandler);
|
|
241690
|
+
this.store.on("task:created", this.taskColumnWakeHandler);
|
|
241691
|
+
}
|
|
241548
241692
|
this.clearStaleSpecifyingStatuses().catch((err) => {
|
|
241549
241693
|
planLog.error("Failed to clear stale planning statuses:", err);
|
|
241550
241694
|
});
|
|
@@ -241577,12 +241721,21 @@ var TriageProcessor = class _TriageProcessor {
|
|
|
241577
241721
|
this.pollInterval = null;
|
|
241578
241722
|
this.activePollMs = null;
|
|
241579
241723
|
}
|
|
241724
|
+
if (this.nudgeTimer) {
|
|
241725
|
+
clearTimeout(this.nudgeTimer);
|
|
241726
|
+
this.nudgeTimer = null;
|
|
241727
|
+
}
|
|
241728
|
+
this.nudgeDuringPoll = false;
|
|
241580
241729
|
if (this.taskDeletedHandler && typeof this.store.off === "function") {
|
|
241581
241730
|
this.store.off("task:deleted", this.taskDeletedHandler);
|
|
241582
241731
|
}
|
|
241583
241732
|
if (this.taskPausedHandler && typeof this.store.off === "function") {
|
|
241584
241733
|
this.store.off("task:updated", this.taskPausedHandler);
|
|
241585
241734
|
}
|
|
241735
|
+
if (this.taskColumnWakeHandler && typeof this.store.off === "function") {
|
|
241736
|
+
this.store.off("task:updated", this.taskColumnWakeHandler);
|
|
241737
|
+
this.store.off("task:created", this.taskColumnWakeHandler);
|
|
241738
|
+
}
|
|
241586
241739
|
this.abortAndDisposeActiveSessions("engine stop");
|
|
241587
241740
|
planLog.log("Processor stopped");
|
|
241588
241741
|
}
|
|
@@ -241990,7 +242143,17 @@ var TriageProcessor = class _TriageProcessor {
|
|
|
241990
242143
|
if (isUnplannedSeedPrompt(content, todoTask.id, todoTask.title, todoTask.description)) {
|
|
241991
242144
|
eligibleTodoTasks.push(todoTask);
|
|
241992
242145
|
}
|
|
241993
|
-
} catch {
|
|
242146
|
+
} catch (err) {
|
|
242147
|
+
if (err?.code === "ENOENT") {
|
|
242148
|
+
planLog.warn(
|
|
242149
|
+
`${todoTask.id}: PROMPT.md is missing \u2014 treating as unplanned and admitting it for planning`
|
|
242150
|
+
);
|
|
242151
|
+
eligibleTodoTasks.push(todoTask);
|
|
242152
|
+
} else {
|
|
242153
|
+
planLog.warn(
|
|
242154
|
+
`${todoTask.id}: PROMPT.md unreadable (${err?.code ?? "unknown"}) \u2014 skipping planning discovery for this poll`
|
|
242155
|
+
);
|
|
242156
|
+
}
|
|
241994
242157
|
}
|
|
241995
242158
|
}
|
|
241996
242159
|
return [...eligibleTriageTasks, ...eligibleTodoTasks].sort((a, b3) => {
|
|
@@ -242004,10 +242167,41 @@ var TriageProcessor = class _TriageProcessor {
|
|
|
242004
242167
|
return numeric2 !== 0 ? numeric2 : a.id.localeCompare(b3.id);
|
|
242005
242168
|
});
|
|
242006
242169
|
}
|
|
242170
|
+
/**
|
|
242171
|
+
* Run a planning-discovery poll now instead of waiting for the next timer tick.
|
|
242172
|
+
*
|
|
242173
|
+
* FNXC:CodingIdeasWorkflow 2026-07-25-11:20:
|
|
242174
|
+
* Requirement: starting a task must begin planning immediately, not "within 15 seconds".
|
|
242175
|
+
* The Start affordance on an intake (Ideas) card performs a bare column move — there is no
|
|
242176
|
+
* dispatch call in that path — so planning only began when the next `setInterval` tick happened
|
|
242177
|
+
* to fire. The store-event wake (taskColumnWakeHandler) is the primary caller.
|
|
242178
|
+
*
|
|
242179
|
+
* Contract: advisory and idempotent. It never plans a task by itself, it only advances WHEN the
|
|
242180
|
+
* existing poll runs — every pause, seed-prompt, dependency, and concurrency gate still applies,
|
|
242181
|
+
* so a nudge on a capacity-blocked card is a no-op rather than an admission bypass. Returns false
|
|
242182
|
+
* when the processor is not running.
|
|
242183
|
+
*/
|
|
242184
|
+
requestImmediatePoll() {
|
|
242185
|
+
if (!this.running) return false;
|
|
242186
|
+
if (this.polling) {
|
|
242187
|
+
this.nudgeDuringPoll = true;
|
|
242188
|
+
return true;
|
|
242189
|
+
}
|
|
242190
|
+
if (this.nudgeTimer) return true;
|
|
242191
|
+
this.nudgeTimer = setTimeout(() => {
|
|
242192
|
+
this.nudgeTimer = null;
|
|
242193
|
+
void this.poll();
|
|
242194
|
+
}, _TriageProcessor.NUDGE_DEBOUNCE_MS);
|
|
242195
|
+
this.nudgeTimer.unref?.();
|
|
242196
|
+
return true;
|
|
242197
|
+
}
|
|
242198
|
+
/** Coalescing window for requestImmediatePoll, so a multi-card drag causes one poll, not N. */
|
|
242199
|
+
static NUDGE_DEBOUNCE_MS = 150;
|
|
242007
242200
|
async poll() {
|
|
242008
242201
|
if (!this.running) return;
|
|
242009
242202
|
if (this.polling) return;
|
|
242010
242203
|
this.polling = true;
|
|
242204
|
+
this.nudgeDuringPoll = false;
|
|
242011
242205
|
try {
|
|
242012
242206
|
const settings = await this.store.getSettings();
|
|
242013
242207
|
this.refreshPollInterval(settings.pollIntervalMs);
|
|
@@ -242113,6 +242307,10 @@ var TriageProcessor = class _TriageProcessor {
|
|
|
242113
242307
|
planLog.error("Poll error:", err);
|
|
242114
242308
|
} finally {
|
|
242115
242309
|
this.polling = false;
|
|
242310
|
+
if (this.nudgeDuringPoll && this.running) {
|
|
242311
|
+
this.nudgeDuringPoll = false;
|
|
242312
|
+
this.requestImmediatePoll();
|
|
242313
|
+
}
|
|
242116
242314
|
}
|
|
242117
242315
|
}
|
|
242118
242316
|
async backfillBlankTitleAfterTerminalTriageFailure(task) {
|