@runfusion/fusion 0.76.0-beta.2 → 0.76.0-beta.3
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 +323 -59
- package/dist/child-process-worker.js +274 -42
- package/dist/client/.vite/manifest.json +273 -273
- package/dist/client/assets/{AgentDetailView-gak4EWTI.js → AgentDetailView-T767kKTg.js} +1 -1
- package/dist/client/assets/{AgentPermissionPolicyEditor-DP1QbZL-.js → AgentPermissionPolicyEditor--u9jyUf2.js} +1 -1
- package/dist/client/assets/{AgentsView-DAMRTKzI.js → AgentsView-6Ifu7qDr.js} +5 -5
- package/dist/client/assets/{ChatView-iE-2gf5P.js → ChatView-BV3lixQi.js} +1 -1
- package/dist/client/assets/{CommandCenter-B6RnkLYm.js → CommandCenter-CSRYoveB.js} +1 -1
- package/dist/client/assets/{DevServerView-DcFL_LzK.js → DevServerView-B9So_oYx.js} +1 -1
- package/dist/client/assets/{DirectoryPicker-CtjqrYoO.js → DirectoryPicker-BhyDL_2m.js} +1 -1
- package/dist/client/assets/{DocumentsView-BkAe2S4H.js → DocumentsView-pbERA7O-.js} +1 -1
- package/dist/client/assets/{EvalsView-CbGA9dMn.js → EvalsView-DJQ4ltCg.js} +1 -1
- package/dist/client/assets/{ExperimentalAgentOnboardingModal-CMgO_S8T.js → ExperimentalAgentOnboardingModal-BwJuzkzB.js} +1 -1
- package/dist/client/assets/{GoalsView-_3P9J5sf.js → GoalsView-B6X5_0Ve.js} +1 -1
- package/dist/client/assets/InsightsView-CJgI0J7S.js +11 -0
- package/dist/client/assets/{InsightsView-Gn5lOBA0.css → InsightsView-DAAXuX4v.css} +1 -1
- package/dist/client/assets/{MemoryView-DwJas8vi.js → MemoryView-BHq1AHPu.js} +1 -1
- package/dist/client/assets/{PiExtensionsManager-B_LiW_e9.js → PiExtensionsManager-B8At6fO8.js} +1 -1
- package/dist/client/assets/{PluginManager-BkB6WLQc.js → PluginManager-k7hV7_9e.js} +1 -1
- package/dist/client/assets/{PullRequestView-DcH5tmYc.js → PullRequestView-B1hZFrWo.js} +1 -1
- package/dist/client/assets/{ReportModal-BOEbqtqG.js → ReportModal-C46V_zEa.js} +1 -1
- package/dist/client/assets/{ResearchView-Dp6V42pI.js → ResearchView-D8G85BYN.js} +2 -2
- package/dist/client/assets/{SecretsView-BCqXHB2L.js → SecretsView-CTri9LRK.js} +1 -1
- package/dist/client/assets/{SessionTerminal-CkdoQv4y.js → SessionTerminal-BRf6r4Vp.js} +1 -1
- package/dist/client/assets/SettingsModal-D0RBeZik.js +21 -0
- package/dist/client/assets/{SettingsModal-Dc7YG6KB.js → SettingsModal-rUQcSTJp.js} +1 -1
- package/dist/client/assets/{SettingsTextareaRow-WSkBoAOO.js → SettingsTextareaRow-BirlBcem.js} +1 -1
- package/dist/client/assets/{SetupWizardModal-VTrJAsKd.js → SetupWizardModal-xnCBM9EL.js} +2 -2
- package/dist/client/assets/{SkillsView-CXeXOxfF.js → SkillsView-O5U0ep50.js} +1 -1
- package/dist/client/assets/{WorkflowNodeEditor-DoxLGPRF.js → WorkflowNodeEditor-BX4d2qqF.js} +3 -3
- package/dist/client/assets/{agent-import-generation-upc0yw-M.js → agent-import-generation-DnqVkPkz.js} +1 -1
- package/dist/client/assets/{agentsOrgChartLayout-C3iumMrW.js → agentsOrgChartLayout-CKuzbhFf.js} +1 -1
- package/dist/client/assets/app-B2FwULu2.js +5 -0
- package/dist/client/assets/{app-BA9gw9hx.js → app-B6nJaqAl.js} +2 -2
- package/dist/client/assets/{app-B_lScKc1.js → app-CGXZeIRc.js} +2 -2
- package/dist/client/assets/{app-DG_vjDw5.js → app-CGtkeBF5.js} +3 -3
- package/dist/client/assets/{app-GBgoY-oh.js → app-CNzN1Plu.js} +2 -2
- package/dist/client/assets/{app-B0KFGP8D.js → app-DLs-f5yM.js} +3 -3
- package/dist/client/assets/{app-DeHIOCEP.js → app-DsvtcRUG.js} +2 -2
- package/dist/client/assets/{architectureDiagram-3BPJPVTR-D6jqc3fJ.js → architectureDiagram-3BPJPVTR-gi467xY0.js} +1 -1
- package/dist/client/assets/{blockDiagram-GPEHLZMM-DY3AKuPD.js → blockDiagram-GPEHLZMM-B_gpcYiR.js} +1 -1
- package/dist/client/assets/{c4Diagram-AAUBKEIU-CpD52V4g.js → c4Diagram-AAUBKEIU-DeylEYsQ.js} +1 -1
- package/dist/client/assets/channel-BoE8DeM4.js +1 -0
- package/dist/client/assets/{chunk-2J33WTMH-CPeIHyAX.js → chunk-2J33WTMH-BL2WY0HN.js} +1 -1
- package/dist/client/assets/{chunk-4BX2VUAB-ivAwI4xM.js → chunk-4BX2VUAB-BkLExGMe.js} +1 -1
- package/dist/client/assets/{chunk-55IACEB6-BtVQ5XaZ.js → chunk-55IACEB6-CSTvCF5T.js} +1 -1
- package/dist/client/assets/{chunk-727SXJPM-1eap1vDU.js → chunk-727SXJPM-9J8pKk4x.js} +1 -1
- package/dist/client/assets/{chunk-AQP2D5EJ-B2NB3BW9.js → chunk-AQP2D5EJ-DXC1vPWr.js} +1 -1
- package/dist/client/assets/{chunk-FMBD7UC4-Hk_smNYv.js → chunk-FMBD7UC4-CFRUb-zD.js} +1 -1
- package/dist/client/assets/{chunk-ND2GUHAM-BmGCAojk.js → chunk-ND2GUHAM-B87HFYS8.js} +1 -1
- package/dist/client/assets/{chunk-QZHKN3VN-D0aXZ8CV.js → chunk-QZHKN3VN-CTjHiGbd.js} +1 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-qnbLX_9_.js +1 -0
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-qnbLX_9_.js +1 -0
- package/dist/client/assets/{cose-bilkent-S5V4N54A-DAbu_gnF.js → cose-bilkent-S5V4N54A-D3Edq3L9.js} +1 -1
- package/dist/client/assets/{dagre-BM42HDAG-BdmLlrDJ.js → dagre-BM42HDAG-CwwbeQfN.js} +1 -1
- package/dist/client/assets/{dashboard-view-CULL1yhL.js → dashboard-view-BLAoW3D4.js} +1 -1
- package/dist/client/assets/{dashboard-view-PRCWCSLm.js → dashboard-view-DAlJxqiJ.js} +1 -1
- package/dist/client/assets/{dashboard-view-BoFBSXUn.js → dashboard-view-QxQwJFLz.js} +1 -1
- package/dist/client/assets/{dashboard-view-CxXMDfNY.js → dashboard-view-aPzfv99T.js} +1 -1
- package/dist/client/assets/{diagram-2AECGRRQ-PpqLbVUA.js → diagram-2AECGRRQ-koJWWXE4.js} +1 -1
- package/dist/client/assets/{diagram-5GNKFQAL-9rkGmTwh.js → diagram-5GNKFQAL-Yob5cOKT.js} +1 -1
- package/dist/client/assets/{diagram-KO2AKTUF-BT-efOMo.js → diagram-KO2AKTUF-DelvFSkK.js} +1 -1
- package/dist/client/assets/{diagram-LMA3HP47-w79OWFxg.js → diagram-LMA3HP47-CMput2h2.js} +1 -1
- package/dist/client/assets/{diagram-OG6HWLK6-Bye9I5IO.js → diagram-OG6HWLK6-04VXDl79.js} +1 -1
- package/dist/client/assets/{erDiagram-TEJ5UH35-aodREgDf.js → erDiagram-TEJ5UH35-C9iP8Uyp.js} +1 -1
- package/dist/client/assets/{flowDiagram-I6XJVG4X-D0DKItY3.js → flowDiagram-I6XJVG4X-DENQvu_t.js} +1 -1
- package/dist/client/assets/{folder-open-CqvaMJvx.js → folder-open-D-554oji.js} +1 -1
- package/dist/client/assets/{ganttDiagram-6RSMTGT7-CZVApkvw.js → ganttDiagram-6RSMTGT7-BqOttZAT.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-PVQCEYII-D_ynwJ4p.js → gitGraphDiagram-PVQCEYII-CDcydi-5.js} +1 -1
- package/dist/client/assets/{index-BzAldNrK.css → index-CXTd3LAB.css} +1 -1
- package/dist/client/assets/{index-DWRJyaa3.js → index-CtYRoouR.js} +264 -264
- package/dist/client/assets/{infoDiagram-5YYISTIA-pJG6zxjk.js → infoDiagram-5YYISTIA-B5LQQnxt.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-nFZ5laUo.js → ishikawaDiagram-YF4QCWOH-DpFEt7D2.js} +1 -1
- package/dist/client/assets/{journeyDiagram-JHISSGLW-CWpCaAIe.js → journeyDiagram-JHISSGLW-MELtgu22.js} +1 -1
- package/dist/client/assets/{kanban-definition-UN3LZRKU-ATkPspKa.js → kanban-definition-UN3LZRKU-h33PLATd.js} +1 -1
- package/dist/client/assets/{mermaid.core-CDXPNs7a.js → mermaid.core-Dk2mUPOq.js} +4 -4
- package/dist/client/assets/{mindmap-definition-RKZ34NQL-BkqS9tpe.js → mindmap-definition-RKZ34NQL-B_T4O2-B.js} +1 -1
- package/dist/client/assets/{pieDiagram-4H26LBE5-DEUyVLs-.js → pieDiagram-4H26LBE5-B1YIFkRl.js} +1 -1
- package/dist/client/assets/{puzzle-DQ0y1-XK.js → puzzle-hvecxlpJ.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-W4KKPZXB-ESBJNK5c.js → quadrantDiagram-W4KKPZXB-BoGQR_hO.js} +1 -1
- package/dist/client/assets/{requirementDiagram-4Y6WPE33-CqPs7zcv.js → requirementDiagram-4Y6WPE33-BSDmUBIx.js} +1 -1
- package/dist/client/assets/{sankeyDiagram-5OEKKPKP-CkFN0m14.js → sankeyDiagram-5OEKKPKP-Dz_GqOa5.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-3UESZ5HK-Dx2nDuMO.js → sequenceDiagram-3UESZ5HK-B6twjYUH.js} +1 -1
- package/dist/client/assets/{shield-alert-BS05s4RM.js → shield-alert-BX4WRJOv.js} +1 -1
- package/dist/client/assets/{standing-instructions-template-xprxYNHm.js → standing-instructions-template-BJY317CC.js} +1 -1
- package/dist/client/assets/{stateDiagram-AJRCARHV-EUPmRFGd.js → stateDiagram-AJRCARHV-DuwqWLx-.js} +1 -1
- package/dist/client/assets/{stateDiagram-v2-BHNVJYJU-DcQ2mhi5.js → stateDiagram-v2-BHNVJYJU-Bu8Sk187.js} +1 -1
- package/dist/client/assets/{timeline-definition-PNZ67QCA-D4YO_3V-.js → timeline-definition-PNZ67QCA-BS6VnqSI.js} +1 -1
- package/dist/client/assets/{upload-BjyBtxo7.js → upload-CaDoyaMW.js} +1 -1
- package/dist/client/assets/{users-D5ogZ7WQ.js → users-C5uCLwVM.js} +1 -1
- package/dist/client/assets/{vennDiagram-CIIHVFJN-BT5_XuQL.js → vennDiagram-CIIHVFJN-CUbzqT5Y.js} +1 -1
- package/dist/client/assets/{wardley-L42UT6IY-X_ZMW457.js → wardley-L42UT6IY-Mv-NotFS.js} +1 -1
- package/dist/client/assets/{wardleyDiagram-YWT4CUSO-GK9nONHU.js → wardleyDiagram-YWT4CUSO-DuYpvLZX.js} +1 -1
- package/dist/client/assets/{xychartDiagram-2RQKCTM6-Dw3zXHAq.js → xychartDiagram-2RQKCTM6-24_7QXdw.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 +285 -47
- package/dist/pi-claude-cli/package.json +1 -1
- package/dist/plugin-sdk/index.d.ts +23 -0
- package/dist/plugin-sdk/index.js +2 -0
- package/dist/plugins/fusion-plugin-acp-runtime/bundled.js +2 -0
- package/dist/plugins/fusion-plugin-acp-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-claude-runtime/bundled.js +2 -0
- package/dist/plugins/fusion-plugin-claude-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-cli-printing-press/bundled.js +2 -0
- package/dist/plugins/fusion-plugin-cli-printing-press/package.json +1 -1
- package/dist/plugins/fusion-plugin-compound-engineering/bundled.js +2 -0
- package/dist/plugins/fusion-plugin-compound-engineering/package.json +1 -1
- package/dist/plugins/fusion-plugin-cursor-runtime/bundled.js +2 -0
- package/dist/plugins/fusion-plugin-cursor-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-dependency-graph/bundled.js +2 -0
- package/dist/plugins/fusion-plugin-dependency-graph/package.json +1 -1
- package/dist/plugins/fusion-plugin-droid-runtime/bundled.js +2 -0
- package/dist/plugins/fusion-plugin-droid-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-grok-runtime/bundled.js +2 -0
- package/dist/plugins/fusion-plugin-grok-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-hermes-runtime/bundled.js +2 -0
- package/dist/plugins/fusion-plugin-hermes-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-linear-import/bundled.js +2 -0
- package/dist/plugins/fusion-plugin-linear-import/package.json +1 -1
- package/dist/plugins/fusion-plugin-omp-runtime/bundled.js +2 -0
- package/dist/plugins/fusion-plugin-omp-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-openclaw-runtime/bundled.js +2 -0
- package/dist/plugins/fusion-plugin-openclaw-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-paperclip-runtime/bundled.js +2 -0
- package/dist/plugins/fusion-plugin-paperclip-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-quality/bundled.js +2 -0
- package/dist/plugins/fusion-plugin-quality/package.json +1 -1
- package/dist/plugins/fusion-plugin-reports/bundled.js +2 -0
- package/dist/plugins/fusion-plugin-reports/package.json +1 -1
- package/dist/plugins/fusion-plugin-roadmap/bundled.js +2 -0
- package/dist/plugins/fusion-plugin-roadmap/package.json +1 -1
- package/dist/plugins/fusion-plugin-todos/bundled.js +2 -0
- package/dist/plugins/fusion-plugin-todos/package.json +1 -1
- package/dist/plugins/fusion-plugin-whatsapp-chat/bundled.js +2 -0
- package/dist/plugins/fusion-plugin-whatsapp-chat/package.json +1 -1
- package/package.json +1 -1
- package/dist/client/assets/InsightsView-DOhO7xH5.js +0 -11
- package/dist/client/assets/SettingsModal-D4Fn4GlS.js +0 -21
- package/dist/client/assets/app-DBCGrz-f.js +0 -5
- package/dist/client/assets/channel-CaxOu15c.js +0 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-DXIkGbsl.js +0 -1
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-DXIkGbsl.js +0 -1
package/dist/bin.js
CHANGED
|
@@ -2184,6 +2184,8 @@ var init_settings_schema = __esm({
|
|
|
2184
2184
|
DEFAULT_PROJECT_SETTINGS = {
|
|
2185
2185
|
// FNXC:TaskRecommendations 2026-08-08-05:02: completion follows-ups stay bounded by default; 0 disables writing them.
|
|
2186
2186
|
maxRecommendationsPerTask: 3,
|
|
2187
|
+
// FNXC:TaskRecommendations 2026-08-13-03:56: surface completed-task proposals by default; operators can suppress the notice without suppressing capture.
|
|
2188
|
+
recommendationMailboxNoticeEnabled: true,
|
|
2187
2189
|
globalPause: false,
|
|
2188
2190
|
globalPauseReason: void 0,
|
|
2189
2191
|
defaultWorkflowId: void 0,
|
|
@@ -68757,20 +68759,32 @@ async function replaceActiveTaskWorkflowContinuation(layer, input) {
|
|
|
68757
68759
|
return upsertWorkflowWorkItem(layer, input, tx);
|
|
68758
68760
|
}));
|
|
68759
68761
|
}
|
|
68760
|
-
async function seedStrandedPlanReviewContinuation(layer, input) {
|
|
68762
|
+
async function seedStrandedPlanReviewContinuation(layer, input, options = {}) {
|
|
68761
68763
|
return layer.transactionImmediate(async (tx) => withTaskWorkflowSerialization(tx, layer.projectId, input.taskId, async () => {
|
|
68762
68764
|
const active2 = await tx.select({ id: project_exports.workflowWorkItems.id }).from(project_exports.workflowWorkItems).where(and(
|
|
68763
68765
|
projectScopeFor(project_exports.workflowWorkItems.projectId, layer.projectId),
|
|
68764
68766
|
eq(project_exports.workflowWorkItems.taskId, input.taskId),
|
|
68765
68767
|
inArray(project_exports.workflowWorkItems.state, [...ACTIVE_WORKFLOW_WORK_ITEM_STATES])
|
|
68766
68768
|
));
|
|
68767
|
-
|
|
68769
|
+
const blocking = options.retirePredecessorId ? active2.filter((row) => row.id !== options.retirePredecessorId) : active2;
|
|
68770
|
+
if (blocking.length > 0) return { seeded: false, reason: "active-continuation" };
|
|
68768
68771
|
const taskRows = await tx.select({ workflowStepResults: project_exports.tasks.workflowStepResults }).from(project_exports.tasks).where(and(
|
|
68769
68772
|
projectScopeFor(project_exports.tasks.projectId, layer.projectId),
|
|
68770
68773
|
eq(project_exports.tasks.id, input.taskId)
|
|
68771
68774
|
)).limit(1);
|
|
68772
68775
|
const results = taskRows[0]?.workflowStepResults;
|
|
68773
68776
|
if (results?.some(isPlanReviewSatisfied)) return { seeded: false, reason: "plan-review-passed" };
|
|
68777
|
+
if (options.retirePredecessorId) {
|
|
68778
|
+
const predRows = await tx.select().from(project_exports.workflowWorkItems).where(and(
|
|
68779
|
+
projectScopeFor(project_exports.workflowWorkItems.projectId, layer.projectId),
|
|
68780
|
+
eq(project_exports.workflowWorkItems.id, options.retirePredecessorId),
|
|
68781
|
+
eq(project_exports.workflowWorkItems.taskId, input.taskId)
|
|
68782
|
+
)).limit(1);
|
|
68783
|
+
const pred = predRows[0];
|
|
68784
|
+
if (pred && !isTerminalWorkflowWorkItemState(normalizeWorkflowWorkItemState(pred.state))) {
|
|
68785
|
+
await transitionWorkflowWorkItem(layer, pred.id, "succeeded", { leaseOwner: null, leaseExpiresAt: null, lastError: null }, tx);
|
|
68786
|
+
}
|
|
68787
|
+
}
|
|
68774
68788
|
const item = await upsertWorkflowWorkItem(layer, input, tx);
|
|
68775
68789
|
return { seeded: true, workItemId: item.id };
|
|
68776
68790
|
}));
|
|
@@ -97148,8 +97162,8 @@ async function upsertWorkflowWorkItemImpl(store, input, tx) {
|
|
|
97148
97162
|
async function replaceActiveTaskWorkflowContinuationImpl(store, input) {
|
|
97149
97163
|
return replaceActiveTaskWorkflowContinuation(store.asyncLayer, input);
|
|
97150
97164
|
}
|
|
97151
|
-
async function seedStrandedPlanReviewContinuationImpl(store, input) {
|
|
97152
|
-
return seedStrandedPlanReviewContinuation(store.asyncLayer, input);
|
|
97165
|
+
async function seedStrandedPlanReviewContinuationImpl(store, input, options = {}) {
|
|
97166
|
+
return seedStrandedPlanReviewContinuation(store.asyncLayer, input, options);
|
|
97153
97167
|
}
|
|
97154
97168
|
async function transitionWorkflowWorkItemImpl(store, id, state, patch = {}, tx) {
|
|
97155
97169
|
return transitionWorkflowWorkItem(store.asyncLayer, id, state, patch, tx);
|
|
@@ -101292,6 +101306,37 @@ async function getTaskVerificationRequestAsyncImpl(store, taskId) {
|
|
|
101292
101306
|
const row = rows[0];
|
|
101293
101307
|
return row ? { taskId: row.taskId, requestId: row.requestId, status: row.status, profile: row.profile, command: row.command, scope: row.scope, requestedBy: row.requestedBy, requestedAt: row.requestedAt, ...row.startedAt ? { startedAt: row.startedAt } : {}, ...row.completedAt ? { completedAt: row.completedAt } : {}, ...row.result ? { result: row.result } : {}, ...row.rejectionReason ? { rejectionReason: row.rejectionReason } : {} } : null;
|
|
101294
101308
|
}
|
|
101309
|
+
async function listTaskRecommendationsImpl(store, options) {
|
|
101310
|
+
const layer = store.asyncLayer;
|
|
101311
|
+
const completeColumns = options?.completeColumns ?? await resolveProjectColumnsForRoles(store, ["complete"]);
|
|
101312
|
+
const rawLimit = options?.limit;
|
|
101313
|
+
const rawOffset = options?.offset;
|
|
101314
|
+
const limit2 = typeof rawLimit === "number" && Number.isFinite(rawLimit) ? Math.min(200, Math.max(1, Math.trunc(rawLimit))) : 50;
|
|
101315
|
+
const offset = typeof rawOffset === "number" && Number.isFinite(rawOffset) ? Math.max(0, Math.trunc(rawOffset)) : 0;
|
|
101316
|
+
const columns = [...completeColumns];
|
|
101317
|
+
if (columns.length === 0) return { items: [], rowOffset: offset, rowLimit: limit2, returnedRowCount: 0, totalRowCount: 0, hasMore: false };
|
|
101318
|
+
const filter2 = and(
|
|
101319
|
+
taskProjectScope(layer),
|
|
101320
|
+
isNull(project_exports.tasks.deletedAt),
|
|
101321
|
+
inArray(project_exports.tasks.column, columns),
|
|
101322
|
+
isNotNull(project_exports.tasks.recommendations),
|
|
101323
|
+
sql`jsonb_array_length(${project_exports.tasks.recommendations}) > 0`
|
|
101324
|
+
);
|
|
101325
|
+
const [countRows, rows] = await Promise.all([
|
|
101326
|
+
layer.db.select({ count: sql`count(*)` }).from(project_exports.tasks).where(filter2),
|
|
101327
|
+
layer.db.select({ id: project_exports.tasks.id, title: project_exports.tasks.title, column: project_exports.tasks.column, updatedAt: project_exports.tasks.updatedAt, recommendations: project_exports.tasks.recommendations }).from(project_exports.tasks).where(filter2).orderBy(desc(project_exports.tasks.updatedAt), desc(project_exports.tasks.id)).limit(limit2).offset(offset)
|
|
101328
|
+
]);
|
|
101329
|
+
const items = [];
|
|
101330
|
+
for (const row of rows) {
|
|
101331
|
+
if (!Array.isArray(row.recommendations) || row.recommendations.length === 0) continue;
|
|
101332
|
+
for (const recommendation of row.recommendations) {
|
|
101333
|
+
items.push({ taskId: row.id, taskTitle: row.title ?? void 0, taskColumn: row.column, updatedAt: row.updatedAt, recommendation });
|
|
101334
|
+
}
|
|
101335
|
+
}
|
|
101336
|
+
const totalRowCount = Number(countRows[0]?.count ?? 0);
|
|
101337
|
+
const returnedRowCount = rows.length;
|
|
101338
|
+
return { items, rowOffset: offset, rowLimit: limit2, returnedRowCount, totalRowCount, hasMore: offset + returnedRowCount < totalRowCount };
|
|
101339
|
+
}
|
|
101295
101340
|
var LEGACY_REVIEW_LANES5, LEGACY_ARCHIVE_LANES2;
|
|
101296
101341
|
var init_reads = __esm({
|
|
101297
101342
|
"../core/src/task-store/reads.ts"() {
|
|
@@ -101314,6 +101359,7 @@ var init_reads = __esm({
|
|
|
101314
101359
|
init_retry_summary();
|
|
101315
101360
|
init_errors3();
|
|
101316
101361
|
init_project_lane_vocabulary();
|
|
101362
|
+
init_data_layer();
|
|
101317
101363
|
init_async_persistence();
|
|
101318
101364
|
init_async_search();
|
|
101319
101365
|
init_async_archive_db();
|
|
@@ -103420,6 +103466,9 @@ var init_store = __esm({
|
|
|
103420
103466
|
async clearWorkflowRunStepInstancesAsync(taskId, keepRunId) {
|
|
103421
103467
|
return clearWorkflowRunStepInstancesAsyncImpl(this, taskId, keepRunId);
|
|
103422
103468
|
}
|
|
103469
|
+
async listTaskRecommendations(options) {
|
|
103470
|
+
return listTaskRecommendationsImpl(this, options);
|
|
103471
|
+
}
|
|
103423
103472
|
async listTasksForGithubTrackingReconcile(options) {
|
|
103424
103473
|
return listTasksForGithubTrackingReconcileImpl(this, options);
|
|
103425
103474
|
}
|
|
@@ -104146,8 +104195,8 @@ var init_store = __esm({
|
|
|
104146
104195
|
async replaceActiveTaskWorkflowContinuation(input) {
|
|
104147
104196
|
return replaceActiveTaskWorkflowContinuationImpl(this, input);
|
|
104148
104197
|
}
|
|
104149
|
-
async seedStrandedPlanReviewContinuation(input) {
|
|
104150
|
-
return seedStrandedPlanReviewContinuationImpl(this, input);
|
|
104198
|
+
async seedStrandedPlanReviewContinuation(input, options = {}) {
|
|
104199
|
+
return seedStrandedPlanReviewContinuationImpl(this, input, options);
|
|
104151
104200
|
}
|
|
104152
104201
|
async transitionWorkflowWorkItem(id, state, patch = {}, tx) {
|
|
104153
104202
|
return transitionWorkflowWorkItemImpl(this, id, state, patch, tx);
|
|
@@ -133285,6 +133334,77 @@ var init_task_timing = __esm({
|
|
|
133285
133334
|
}
|
|
133286
133335
|
});
|
|
133287
133336
|
|
|
133337
|
+
// ../core/src/task-recommendation-notice.ts
|
|
133338
|
+
import { createHash as createHash20 } from "node:crypto";
|
|
133339
|
+
function registerTaskRecommendationNoticeMailbox(store, mailbox) {
|
|
133340
|
+
mailboxes2.set(store, mailbox);
|
|
133341
|
+
return () => {
|
|
133342
|
+
if (mailboxes2.get(store) === mailbox) mailboxes2.delete(store);
|
|
133343
|
+
};
|
|
133344
|
+
}
|
|
133345
|
+
function getTaskRecommendationNoticeMailbox(store) {
|
|
133346
|
+
return mailboxes2.get(store);
|
|
133347
|
+
}
|
|
133348
|
+
function buildTaskRecommendationNoticeContent(task, recommendations) {
|
|
133349
|
+
const title2 = task.title?.trim();
|
|
133350
|
+
const heading = title2 ? `## Recommendations from ${task.id} \u2014 ${title2}` : `## Recommendations from ${task.id}`;
|
|
133351
|
+
return [
|
|
133352
|
+
heading,
|
|
133353
|
+
"",
|
|
133354
|
+
"These are optional, non-blocking out-of-scope proposals that were **not** executed.",
|
|
133355
|
+
"",
|
|
133356
|
+
...recommendations.map((recommendation) => `- **${recommendation.title}** \u2014 \`${recommendation.category}\`: ${recommendation.description}`),
|
|
133357
|
+
"",
|
|
133358
|
+
`Open ${task.id}'s **Recommendations** tab to review them. **Create task** files one through normal guarded intake.`
|
|
133359
|
+
].join("\n");
|
|
133360
|
+
}
|
|
133361
|
+
function buildTaskRecommendationNoticeIdempotencyKey(taskId, recommendations) {
|
|
133362
|
+
const ids = recommendations.map(({ id }) => id).sort().join("\n");
|
|
133363
|
+
const digest = createHash20("sha256").update(ids, "utf8").digest("hex").slice(0, 16);
|
|
133364
|
+
return `task-recommendation-notice:${taskId}:${digest}`;
|
|
133365
|
+
}
|
|
133366
|
+
async function notifyOperatorOfTaskRecommendations(store, task, recommendations, settings) {
|
|
133367
|
+
try {
|
|
133368
|
+
if (settings.recommendationMailboxNoticeEnabled === false || !recommendations?.length) return false;
|
|
133369
|
+
const mailbox = mailboxes2.get(store);
|
|
133370
|
+
if (!mailbox) return false;
|
|
133371
|
+
await mailbox.sendMessageOnce(
|
|
133372
|
+
{
|
|
133373
|
+
fromId: "system",
|
|
133374
|
+
fromType: "system",
|
|
133375
|
+
toId: DASHBOARD_USER_ID,
|
|
133376
|
+
toType: "user",
|
|
133377
|
+
type: "system",
|
|
133378
|
+
content: buildTaskRecommendationNoticeContent(task, recommendations),
|
|
133379
|
+
metadata: {
|
|
133380
|
+
kind: "task-recommendation-notice",
|
|
133381
|
+
taskId: task.id,
|
|
133382
|
+
recommendationCount: recommendations.length,
|
|
133383
|
+
recommendationIds: recommendations.map(({ id }) => id),
|
|
133384
|
+
categories: recommendations.map(({ category }) => category)
|
|
133385
|
+
}
|
|
133386
|
+
},
|
|
133387
|
+
buildTaskRecommendationNoticeIdempotencyKey(task.id, recommendations)
|
|
133388
|
+
);
|
|
133389
|
+
return true;
|
|
133390
|
+
} catch (error3) {
|
|
133391
|
+
noticeLog2.warn(
|
|
133392
|
+
`Operator recommendation notice failed for ${task.id}: ${error3 instanceof Error ? error3.message : String(error3)}`
|
|
133393
|
+
);
|
|
133394
|
+
return false;
|
|
133395
|
+
}
|
|
133396
|
+
}
|
|
133397
|
+
var noticeLog2, mailboxes2;
|
|
133398
|
+
var init_task_recommendation_notice = __esm({
|
|
133399
|
+
"../core/src/task-recommendation-notice.ts"() {
|
|
133400
|
+
"use strict";
|
|
133401
|
+
init_logger();
|
|
133402
|
+
init_types();
|
|
133403
|
+
noticeLog2 = createLogger("task-recommendation-notice");
|
|
133404
|
+
mailboxes2 = /* @__PURE__ */ new WeakMap();
|
|
133405
|
+
}
|
|
133406
|
+
});
|
|
133407
|
+
|
|
133288
133408
|
// ../core/src/session-identity-registry.ts
|
|
133289
133409
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
133290
133410
|
import { resolve as resolve24 } from "node:path";
|
|
@@ -134134,6 +134254,8 @@ __export(src_exports, {
|
|
|
134134
134254
|
buildTaskDeleteNoticeContent: () => buildTaskDeleteNoticeContent,
|
|
134135
134255
|
buildTaskDeleteNoticeIdempotencyKey: () => buildTaskDeleteNoticeIdempotencyKey,
|
|
134136
134256
|
buildTaskLineageTrailer: () => buildTaskLineageTrailer,
|
|
134257
|
+
buildTaskRecommendationNoticeContent: () => buildTaskRecommendationNoticeContent,
|
|
134258
|
+
buildTaskRecommendationNoticeIdempotencyKey: () => buildTaskRecommendationNoticeIdempotencyKey,
|
|
134137
134259
|
buildToolOutputTruncationMarker: () => buildToolOutputTruncationMarker,
|
|
134138
134260
|
buildTriageHeartbeatGuidance: () => buildTriageHeartbeatGuidance,
|
|
134139
134261
|
buildTriageMemoryInstructions: () => buildTriageMemoryInstructions,
|
|
@@ -134464,6 +134586,7 @@ __export(src_exports, {
|
|
|
134464
134586
|
getTaskMergeBlocker: () => getTaskMergeBlocker,
|
|
134465
134587
|
getTaskMoveDisposer: () => getTaskMoveDisposer,
|
|
134466
134588
|
getTaskPriorityRank: () => getTaskPriorityRank,
|
|
134589
|
+
getTaskRecommendationNoticeMailbox: () => getTaskRecommendationNoticeMailbox,
|
|
134467
134590
|
getTemplatesForRole: () => getTemplatesForRole,
|
|
134468
134591
|
getTotalAgentActiveMs: () => getTotalAgentActiveMs,
|
|
134469
134592
|
getTrait: () => getTrait,
|
|
@@ -134714,6 +134837,7 @@ __export(src_exports, {
|
|
|
134714
134837
|
normalizeWorkflowPromptOverrides: () => normalizeWorkflowPromptOverrides,
|
|
134715
134838
|
normalizeWorkflowReviewFindings: () => normalizeWorkflowReviewFindings,
|
|
134716
134839
|
notifyOperatorOfNonOperatorDelete: () => notifyOperatorOfNonOperatorDelete,
|
|
134840
|
+
notifyOperatorOfTaskRecommendations: () => notifyOperatorOfTaskRecommendations,
|
|
134717
134841
|
overseerAdviceSeverityRank: () => overseerAdviceSeverityRank,
|
|
134718
134842
|
parseAgentManifest: () => parseAgentManifest,
|
|
134719
134843
|
parseCompanyArchive: () => parseCompanyArchive,
|
|
@@ -134823,6 +134947,7 @@ __export(src_exports, {
|
|
|
134823
134947
|
registerStepParser: () => registerStepParser,
|
|
134824
134948
|
registerTaskDeleteNoticeMailbox: () => registerTaskDeleteNoticeMailbox,
|
|
134825
134949
|
registerTaskMoveDisposer: () => registerTaskMoveDisposer,
|
|
134950
|
+
registerTaskRecommendationNoticeMailbox: () => registerTaskRecommendationNoticeMailbox,
|
|
134826
134951
|
registerTraitHookImpl: () => registerTraitHookImpl,
|
|
134827
134952
|
rekeyFallbackProjectPartition: () => rekeyFallbackProjectPartition,
|
|
134828
134953
|
releaseEmbeddedRuntimeLease: () => releaseEmbeddedRuntimeLease,
|
|
@@ -135450,6 +135575,7 @@ var init_src2 = __esm({
|
|
|
135450
135575
|
init_task_document_concurrency();
|
|
135451
135576
|
init_task_delete_attribution();
|
|
135452
135577
|
init_task_delete_notice();
|
|
135578
|
+
init_task_recommendation_notice();
|
|
135453
135579
|
init_session_identity_registry();
|
|
135454
135580
|
init_task_lifecycle_event_retention();
|
|
135455
135581
|
init_task_lifecycle_consumer_identity();
|
|
@@ -136287,7 +136413,7 @@ var init_logger3 = __esm({
|
|
|
136287
136413
|
});
|
|
136288
136414
|
|
|
136289
136415
|
// ../engine/src/agents/agent-logger.ts
|
|
136290
|
-
import { createHash as
|
|
136416
|
+
import { createHash as createHash21 } from "node:crypto";
|
|
136291
136417
|
function truncateToolResultDetail(value2) {
|
|
136292
136418
|
if (value2.length <= TOOL_RESULT_DETAIL_LIMIT) return value2;
|
|
136293
136419
|
return `${value2.slice(0, TOOL_RESULT_DETAIL_LIMIT)}${TOOL_RESULT_DETAIL_TRUNCATION_NOTICE}`;
|
|
@@ -136376,7 +136502,7 @@ function summarizeToolArgs(name2, args) {
|
|
|
136376
136502
|
const json2 = JSON.stringify(args);
|
|
136377
136503
|
if (!json2 || json2 === "{}" || json2 === "[]") return void 0;
|
|
136378
136504
|
if (json2.length <= STRUCTURED_ARG_SUMMARY_MAX) return json2;
|
|
136379
|
-
const hash3 =
|
|
136505
|
+
const hash3 = createHash21("sha256").update(json2).digest("hex").slice(0, STRUCTURED_ARG_HASH_HEX_LEN);
|
|
136380
136506
|
const suffix = `\u2026#${hash3}`;
|
|
136381
136507
|
const keep = Math.max(0, STRUCTURED_ARG_SUMMARY_MAX - suffix.length);
|
|
136382
136508
|
return `${json2.slice(0, keep)}${suffix}`;
|
|
@@ -137156,7 +137282,7 @@ var init_gating_classifications = __esm({
|
|
|
137156
137282
|
});
|
|
137157
137283
|
|
|
137158
137284
|
// ../engine/src/agents/agent-action-gate.ts
|
|
137159
|
-
import { createHash as
|
|
137285
|
+
import { createHash as createHash22 } from "node:crypto";
|
|
137160
137286
|
function getExemptTools() {
|
|
137161
137287
|
if (!_exemptTools) {
|
|
137162
137288
|
_exemptTools = new Set(DEFAULT_EXEMPT_TOOLS);
|
|
@@ -137208,7 +137334,7 @@ function evaluateAgentActionGate(params) {
|
|
|
137208
137334
|
if (params.toolName === "bash") {
|
|
137209
137335
|
const command2 = extractShellCommand(args);
|
|
137210
137336
|
const git7 = classifyGitCommand(command2);
|
|
137211
|
-
resourceId = command2 ? `cmd:${
|
|
137337
|
+
resourceId = command2 ? `cmd:${createHash22("sha256").update(command2).digest("hex").slice(0, 16)}` : void 0;
|
|
137212
137338
|
if (git7?.write) {
|
|
137213
137339
|
category = "git_write";
|
|
137214
137340
|
operation = git7.operation;
|
|
@@ -140740,11 +140866,11 @@ var init_planning_handoff_recovery = __esm({
|
|
|
140740
140866
|
// ../engine/src/plan-review-continuation.ts
|
|
140741
140867
|
async function seedPreReleasePlanReviewContinuation(store, task, ir2, options = {}) {
|
|
140742
140868
|
const node = resolvePreReleasePlanReviewNode(ir2);
|
|
140743
|
-
if (!node || node.column !== task.column) return { seeded: false };
|
|
140869
|
+
if (!node || node.column !== task.column) return { seeded: false, reason: "no-pre-release-plan-review" };
|
|
140744
140870
|
if (isTaskBlockedOnApproval(task)) return { seeded: false, reason: "awaiting-approval" };
|
|
140745
140871
|
if (task.paused === true || task.userPaused === true) return { seeded: false, reason: "paused" };
|
|
140746
140872
|
const items = await store.listWorkflowWorkItemsForTask(task.id);
|
|
140747
|
-
const active2 = items.filter((item2) => ACTIVE_WORKFLOW_WORK_ITEM_STATES.includes(item2.state));
|
|
140873
|
+
const active2 = items.filter((item2) => ACTIVE_WORKFLOW_WORK_ITEM_STATES.includes(item2.state) && item2.id !== options.retirePredecessorId);
|
|
140748
140874
|
if (active2.length > 0) return { seeded: false, reason: "active-continuation" };
|
|
140749
140875
|
const continuationSequence = items.length;
|
|
140750
140876
|
const input = {
|
|
@@ -140760,6 +140886,9 @@ async function seedPreReleasePlanReviewContinuation(store, task, ir2, options =
|
|
|
140760
140886
|
targetColumn: task.column,
|
|
140761
140887
|
irHash: computeWorkflowIrPin(ir2, node.id).irHash
|
|
140762
140888
|
};
|
|
140889
|
+
if (options.retirePredecessorId) {
|
|
140890
|
+
return store.seedStrandedPlanReviewContinuation(input, { retirePredecessorId: options.retirePredecessorId });
|
|
140891
|
+
}
|
|
140763
140892
|
if (options.atomic) return store.seedStrandedPlanReviewContinuation(input);
|
|
140764
140893
|
const item = await store.replaceActiveTaskWorkflowContinuation(input);
|
|
140765
140894
|
return { seeded: true, workItemId: item.id };
|
|
@@ -140774,7 +140903,7 @@ async function resumeApprovedPlanReviewHandoff(store, task, ir2) {
|
|
|
140774
140903
|
if (seeded.seeded) return { resumed: true, reason: "seeded", workItemId: seeded.workItemId };
|
|
140775
140904
|
return {
|
|
140776
140905
|
resumed: false,
|
|
140777
|
-
reason: seeded.reason
|
|
140906
|
+
reason: seeded.reason === void 0 || seeded.reason === "no-pre-release-plan-review" ? "not-plan-in-place" : seeded.reason
|
|
140778
140907
|
};
|
|
140779
140908
|
}
|
|
140780
140909
|
function evaluateStrandedHoldContinuation(input) {
|
|
@@ -140812,7 +140941,7 @@ var init_plan_review_continuation = __esm({
|
|
|
140812
140941
|
});
|
|
140813
140942
|
|
|
140814
140943
|
// ../engine/src/execution/hold-release.ts
|
|
140815
|
-
import { createHash as
|
|
140944
|
+
import { createHash as createHash23 } from "node:crypto";
|
|
140816
140945
|
import { readFile as readFile31 } from "node:fs/promises";
|
|
140817
140946
|
function findColumn2(ir2, columnId) {
|
|
140818
140947
|
if (ir2.version !== "v2") return void 0;
|
|
@@ -140850,9 +140979,9 @@ async function checkAndRecordUnplannedExecutionBlock(store, task, ir2) {
|
|
|
140850
140979
|
promptContent = "";
|
|
140851
140980
|
}
|
|
140852
140981
|
}
|
|
140853
|
-
const promptMarker = promptContent.length > 0 ?
|
|
140982
|
+
const promptMarker = promptContent.length > 0 ? createHash23("sha256").update(promptContent).digest("hex") : "missing";
|
|
140854
140983
|
const dependencies = [...task.dependencies ?? []].sort();
|
|
140855
|
-
const episode =
|
|
140984
|
+
const episode = createHash23("sha256").update(JSON.stringify({
|
|
140856
140985
|
planReviewNode,
|
|
140857
140986
|
promptMarker,
|
|
140858
140987
|
dependencies,
|
|
@@ -170972,7 +171101,7 @@ ${getErrorStderr(error3) ?? ""}`;
|
|
|
170972
171101
|
});
|
|
170973
171102
|
|
|
170974
171103
|
// ../engine/src/worktree/secrets-env-writer.ts
|
|
170975
|
-
import { createHash as
|
|
171104
|
+
import { createHash as createHash24 } from "node:crypto";
|
|
170976
171105
|
import { execFile as execFile8 } from "node:child_process";
|
|
170977
171106
|
import { promises as fs6 } from "node:fs";
|
|
170978
171107
|
import path2 from "node:path";
|
|
@@ -170981,7 +171110,7 @@ function isValidFilename(filename) {
|
|
|
170981
171110
|
return !!filename && !filename.includes("/") && !filename.includes("\\") && !filename.includes("..") && !filename.includes("\0") && filename !== FINGERPRINT_FILE;
|
|
170982
171111
|
}
|
|
170983
171112
|
function sha2562(content) {
|
|
170984
|
-
return
|
|
171113
|
+
return createHash24("sha256").update(Buffer.from(content, "utf8")).digest("hex");
|
|
170985
171114
|
}
|
|
170986
171115
|
function quote(value2) {
|
|
170987
171116
|
return `"${value2.replaceAll("\\", "\\\\").replaceAll('"', '\\"').replaceAll("\n", "\\n").replaceAll("\r", "\\r").replaceAll(" ", "\\t")}"`;
|
|
@@ -179388,7 +179517,7 @@ var init_mission_feature_sync = __esm({
|
|
|
179388
179517
|
// ../engine/src/agent-tools.ts
|
|
179389
179518
|
import { appendFile as appendFile3, mkdir as mkdir28, readFile as readFile38, readdir as readdir11, realpath as realpath2, stat as stat11, writeFile as writeFile26 } from "node:fs/promises";
|
|
179390
179519
|
import { existsSync as existsSync53 } from "node:fs";
|
|
179391
|
-
import { createHash as
|
|
179520
|
+
import { createHash as createHash25, randomUUID as randomUUID47 } from "node:crypto";
|
|
179392
179521
|
import { tmpdir as tmpdir5 } from "node:os";
|
|
179393
179522
|
import { extname as extname4, isAbsolute as isAbsolute14, join as join66, relative as relative14, resolve as resolve38, sep as sep10 } from "node:path";
|
|
179394
179523
|
import { Type as Type2 } from "@earendil-works/pi-ai";
|
|
@@ -179432,7 +179561,7 @@ async function readAgentMemoryWorkspaceLongTerm(rootDir, agentId) {
|
|
|
179432
179561
|
}
|
|
179433
179562
|
}
|
|
179434
179563
|
function qmdAgentMemoryCollectionName2(rootDir, agentId) {
|
|
179435
|
-
const hash3 =
|
|
179564
|
+
const hash3 = createHash25("sha1").update(`${rootDir}:${agentId}`).digest("hex").slice(0, 12);
|
|
179436
179565
|
return `fusion-agent-memory-${sanitizeAgentMemoryId(agentId).toLowerCase()}-${hash3}`;
|
|
179437
179566
|
}
|
|
179438
179567
|
function buildQmdAgentMemoryCollectionAddArgs(rootDir, agentId) {
|
|
@@ -191009,7 +191138,7 @@ var init_agent_heartbeat_error_recovery = __esm({
|
|
|
191009
191138
|
|
|
191010
191139
|
// ../engine/src/agent-heartbeat.ts
|
|
191011
191140
|
import { Type as Type3 } from "@earendil-works/pi-ai";
|
|
191012
|
-
import { createHash as
|
|
191141
|
+
import { createHash as createHash26 } from "node:crypto";
|
|
191013
191142
|
async function resolveHeartbeatReboundColumn(taskStore, taskId) {
|
|
191014
191143
|
try {
|
|
191015
191144
|
return resolveReboundTarget(await resolveWorkflowIrForTask(taskStore, taskId)) ?? "todo";
|
|
@@ -191164,7 +191293,7 @@ function truncatePrompt(text3, maxChars) {
|
|
|
191164
191293
|
... (truncated, ${text3.length} chars)`;
|
|
191165
191294
|
}
|
|
191166
191295
|
function shortContentHash(value2) {
|
|
191167
|
-
return
|
|
191296
|
+
return createHash26("sha256").update(value2).digest("hex").slice(0, 8);
|
|
191168
191297
|
}
|
|
191169
191298
|
function buildIdentitySnapshot(args) {
|
|
191170
191299
|
const { agent, resolvedInstructions, workspaceMemory } = args;
|
|
@@ -199053,7 +199182,7 @@ var init_verification_utils = __esm({
|
|
|
199053
199182
|
|
|
199054
199183
|
// ../engine/src/merge/merge-dependency-sync.ts
|
|
199055
199184
|
import { exec as exec25 } from "node:child_process";
|
|
199056
|
-
import { createHash as
|
|
199185
|
+
import { createHash as createHash27 } from "node:crypto";
|
|
199057
199186
|
import { existsSync as existsSync56, readFileSync as readFileSync18, writeFileSync as writeFileSync6 } from "node:fs";
|
|
199058
199187
|
import { join as join69 } from "node:path";
|
|
199059
199188
|
import { promisify as promisify35 } from "node:util";
|
|
@@ -199080,7 +199209,7 @@ function computeLockfileHash(rootDir) {
|
|
|
199080
199209
|
const p2 = join69(rootDir, name2);
|
|
199081
199210
|
if (existsSync56(p2)) {
|
|
199082
199211
|
try {
|
|
199083
|
-
return
|
|
199212
|
+
return createHash27("sha256").update(readFileSync18(p2)).digest("hex");
|
|
199084
199213
|
} catch {
|
|
199085
199214
|
return null;
|
|
199086
199215
|
}
|
|
@@ -201622,7 +201751,7 @@ var init_mesh_lease_manager = __esm({
|
|
|
201622
201751
|
});
|
|
201623
201752
|
|
|
201624
201753
|
// ../engine/src/merge/merger-integration-worktree.ts
|
|
201625
|
-
import { createHash as
|
|
201754
|
+
import { createHash as createHash28 } from "node:crypto";
|
|
201626
201755
|
import { exec as exec31, execFile as execFile22 } from "node:child_process";
|
|
201627
201756
|
import { promisify as promisify45 } from "node:util";
|
|
201628
201757
|
function quoteAutostashArg(value2) {
|
|
@@ -201745,7 +201874,7 @@ async function gitDirtyFingerprintLocal(rootDir) {
|
|
|
201745
201874
|
)
|
|
201746
201875
|
]);
|
|
201747
201876
|
if (!diffOut && !statusOut) return "";
|
|
201748
|
-
return
|
|
201877
|
+
return createHash28("sha256").update(diffOut).update("\0").update(statusOut).digest("hex");
|
|
201749
201878
|
} catch {
|
|
201750
201879
|
return "";
|
|
201751
201880
|
}
|
|
@@ -202731,7 +202860,7 @@ import { execSync as execSync5, exec as exec33 } from "node:child_process";
|
|
|
202731
202860
|
import * as childProcess4 from "node:child_process";
|
|
202732
202861
|
import { promisify as promisify48 } from "node:util";
|
|
202733
202862
|
import { existsSync as existsSync59, readFileSync as readFileSync21, writeFileSync as writeFileSync8, unlinkSync as unlinkSync3, renameSync as renameSync4 } from "node:fs";
|
|
202734
|
-
import { createHash as
|
|
202863
|
+
import { createHash as createHash29 } from "node:crypto";
|
|
202735
202864
|
import { join as join73, resolve as resolve44 } from "node:path";
|
|
202736
202865
|
import { hostname as hostname2 } from "node:os";
|
|
202737
202866
|
import { Type as Type4 } from "typebox";
|
|
@@ -202979,7 +203108,7 @@ async function gitDirtyFingerprint(rootDir) {
|
|
|
202979
203108
|
)
|
|
202980
203109
|
]);
|
|
202981
203110
|
if (!diffOut && !statusOut) return "";
|
|
202982
|
-
return
|
|
203111
|
+
return createHash29("sha256").update(diffOut).update("\0").update(statusOut).digest("hex");
|
|
202983
203112
|
} catch {
|
|
202984
203113
|
return "";
|
|
202985
203114
|
}
|
|
@@ -225402,7 +225531,7 @@ You are ${assignedAgent.name}${assignedAgent.title?.trim() ? `, ${assignedAgent.
|
|
|
225402
225531
|
}
|
|
225403
225532
|
return;
|
|
225404
225533
|
}
|
|
225405
|
-
const duplicateReport = { outcome: "parked" };
|
|
225534
|
+
const duplicateReport = { outcome: "parked", planningWorkItemId };
|
|
225406
225535
|
if (await this.tryFinalizeExplicitDuplicateMarker(task, written, settings, {
|
|
225407
225536
|
isReplan,
|
|
225408
225537
|
feedback
|
|
@@ -225421,6 +225550,7 @@ You are ${assignedAgent.name}${assignedAgent.title?.trim() ? `, ${assignedAgent.
|
|
|
225421
225550
|
isReplan,
|
|
225422
225551
|
feedback
|
|
225423
225552
|
});
|
|
225553
|
+
finalizeReport.planningWorkItemId = planningWorkItemId;
|
|
225424
225554
|
this.options.onSpecifyComplete?.(task, finalizeReport);
|
|
225425
225555
|
} finally {
|
|
225426
225556
|
this.activeSessions.delete(task.id);
|
|
@@ -240992,6 +241122,38 @@ var init_execution_block_classifier = __esm({
|
|
|
240992
241122
|
}
|
|
240993
241123
|
});
|
|
240994
241124
|
|
|
241125
|
+
// ../engine/src/executor/completion-recommendation-notice.ts
|
|
241126
|
+
function dispatchAcceptedCompletionRecommendationNotice(args) {
|
|
241127
|
+
if (!args.recommendations?.length) return;
|
|
241128
|
+
const pending = (async () => {
|
|
241129
|
+
const settings = args.settings ?? await args.store.getSettings();
|
|
241130
|
+
const task = await args.store.getTask(args.taskId);
|
|
241131
|
+
if (!task || task.deletedAt) return;
|
|
241132
|
+
await notifyOperatorOfTaskRecommendations(
|
|
241133
|
+
args.store,
|
|
241134
|
+
{ id: args.taskId, title: args.taskTitle ?? task.title },
|
|
241135
|
+
args.recommendations,
|
|
241136
|
+
settings
|
|
241137
|
+
);
|
|
241138
|
+
})();
|
|
241139
|
+
pendingNotices.add(pending);
|
|
241140
|
+
void pending.catch((error3) => {
|
|
241141
|
+
args.log?.warn(
|
|
241142
|
+
`Failed to dispatch recommendation mailbox notice for ${args.taskId}: ${error3 instanceof Error ? error3.message : String(error3)}`
|
|
241143
|
+
);
|
|
241144
|
+
}).finally(() => {
|
|
241145
|
+
pendingNotices.delete(pending);
|
|
241146
|
+
});
|
|
241147
|
+
}
|
|
241148
|
+
var pendingNotices;
|
|
241149
|
+
var init_completion_recommendation_notice = __esm({
|
|
241150
|
+
"../engine/src/executor/completion-recommendation-notice.ts"() {
|
|
241151
|
+
"use strict";
|
|
241152
|
+
init_src2();
|
|
241153
|
+
pendingNotices = /* @__PURE__ */ new Set();
|
|
241154
|
+
}
|
|
241155
|
+
});
|
|
241156
|
+
|
|
240995
241157
|
// ../engine/src/executor/create-task-done-tool.ts
|
|
240996
241158
|
import { Type as Type9 } from "@earendil-works/pi-ai";
|
|
240997
241159
|
function createTaskDoneTool(deps, taskId, worktreePath, promptContent, codeReviewVerdicts, onDone, audit) {
|
|
@@ -241328,6 +241490,16 @@ ${rerunSuffix}`
|
|
|
241328
241490
|
bulkCompletionRefusalAt: null
|
|
241329
241491
|
});
|
|
241330
241492
|
await store.logEntry(taskId, "Task marked done by agent", void 0, deps.getRunContextFor(taskId));
|
|
241493
|
+
if (completionRecommendations !== void 0) {
|
|
241494
|
+
dispatchAcceptedCompletionRecommendationNotice({
|
|
241495
|
+
store,
|
|
241496
|
+
taskId,
|
|
241497
|
+
taskTitle: task.title,
|
|
241498
|
+
recommendations: completionRecommendations,
|
|
241499
|
+
settings,
|
|
241500
|
+
log: executorLog
|
|
241501
|
+
});
|
|
241502
|
+
}
|
|
241331
241503
|
const latestTask = await store.getTask(taskId);
|
|
241332
241504
|
let latestColumn = latestTask.column;
|
|
241333
241505
|
if (latestColumn === await resolveReboundColumnFor(store, taskId)) {
|
|
@@ -241366,6 +241538,7 @@ var init_create_task_done_tool = __esm({
|
|
|
241366
241538
|
init_completion_predicates();
|
|
241367
241539
|
init_task_done_refusal_handler();
|
|
241368
241540
|
init_validate_completion_recommendations();
|
|
241541
|
+
init_completion_recommendation_notice();
|
|
241369
241542
|
}
|
|
241370
241543
|
});
|
|
241371
241544
|
|
|
@@ -252692,6 +252865,16 @@ ${rerunSuffix}` });
|
|
|
252692
252865
|
if (latestColumn === await resolveWipTargetForTask(deps.store, task.id) && !hardPauseActive && beforeWatchdog && !beforeWatchdog.deletedAt && !(rejectIfPaused && (beforeWatchdog.paused || beforeWatchdog.userPaused))) {
|
|
252693
252866
|
deps.scheduleCompletedTaskWatchdog(task.id, "fn_task_done");
|
|
252694
252867
|
}
|
|
252868
|
+
if (recommendations !== void 0) {
|
|
252869
|
+
dispatchAcceptedCompletionRecommendationNotice({
|
|
252870
|
+
store: deps.store,
|
|
252871
|
+
taskId: task.id,
|
|
252872
|
+
taskTitle: task.title,
|
|
252873
|
+
recommendations,
|
|
252874
|
+
settings,
|
|
252875
|
+
log: executorLog
|
|
252876
|
+
});
|
|
252877
|
+
}
|
|
252695
252878
|
return { completed: true, hardPauseActive };
|
|
252696
252879
|
} catch (error3) {
|
|
252697
252880
|
await restoreNoCommitsExpected();
|
|
@@ -252750,6 +252933,7 @@ var init_plan_review_no_op = __esm({
|
|
|
252750
252933
|
init_src2();
|
|
252751
252934
|
init_logger3();
|
|
252752
252935
|
init_lifecycle_columns();
|
|
252936
|
+
init_completion_recommendation_notice();
|
|
252753
252937
|
}
|
|
252754
252938
|
});
|
|
252755
252939
|
|
|
@@ -256258,14 +256442,14 @@ ${stdout.trim()}`);
|
|
|
256258
256442
|
|
|
256259
256443
|
// ../engine/src/missions/mission-execution-loop.ts
|
|
256260
256444
|
import { EventEmitter as EventEmitter26 } from "node:events";
|
|
256261
|
-
import { createHash as
|
|
256445
|
+
import { createHash as createHash30 } from "node:crypto";
|
|
256262
256446
|
import { exec as exec56 } from "node:child_process";
|
|
256263
256447
|
import { promisify as promisify74 } from "node:util";
|
|
256264
256448
|
function quoteShellArg7(value2) {
|
|
256265
256449
|
return `'${value2.replace(/'/g, `'\\''`)}'`;
|
|
256266
256450
|
}
|
|
256267
256451
|
function fingerprintMissionValidationInput(landedSha, provider, modelId, systemPrompt, userPrompt) {
|
|
256268
|
-
return
|
|
256452
|
+
return createHash30("sha256").update(Buffer.from(JSON.stringify(["mission-validation-input-v1", landedSha, provider, modelId, systemPrompt, userPrompt]), "utf8")).digest("hex");
|
|
256269
256453
|
}
|
|
256270
256454
|
var execAsync53, loopLog, VALIDATION_TIMEOUT_MS, MAX_VALIDATION_RESPONSE_BYTES, MAX_VALIDATION_JSON_CANDIDATES, VALIDATION_FAILURE_BUDGET_PER_FINGERPRINT, MissionExecutionLoop;
|
|
256271
256455
|
var init_mission_execution_loop = __esm({
|
|
@@ -267804,9 +267988,9 @@ var init_routine_scheduler = __esm({
|
|
|
267804
267988
|
});
|
|
267805
267989
|
|
|
267806
267990
|
// ../engine/src/healing/stuck-task-detector.ts
|
|
267807
|
-
import { createHash as
|
|
267991
|
+
import { createHash as createHash31 } from "node:crypto";
|
|
267808
267992
|
function hashToolDetail(detail) {
|
|
267809
|
-
return
|
|
267993
|
+
return createHash31("sha256").update(detail).digest("hex").slice(0, TOOL_DETAIL_HASH_HEX_LEN);
|
|
267810
267994
|
}
|
|
267811
267995
|
function buildToolFingerprint(toolName, toolDetail) {
|
|
267812
267996
|
const name2 = toolName.trim().toLowerCase() || "tool";
|
|
@@ -271384,7 +271568,7 @@ var init_node_dispatch_validation = __esm({
|
|
|
271384
271568
|
});
|
|
271385
271569
|
|
|
271386
271570
|
// ../engine/src/runtimes/in-process-runtime.ts
|
|
271387
|
-
import { createHash as
|
|
271571
|
+
import { createHash as createHash32 } from "node:crypto";
|
|
271388
271572
|
import { EventEmitter as EventEmitter27 } from "node:events";
|
|
271389
271573
|
import { setImmediate as setImmediateCb4 } from "node:timers";
|
|
271390
271574
|
function createDiscoveryPluginLoaderOptions(scopedStore) {
|
|
@@ -271475,11 +271659,46 @@ async function reactToSpecificationComplete(deps) {
|
|
|
271475
271659
|
return;
|
|
271476
271660
|
}
|
|
271477
271661
|
deps.log(`Specified ${deps.taskId} \u2192 todo`);
|
|
271478
|
-
const
|
|
271479
|
-
|
|
271480
|
-
|
|
271481
|
-
|
|
271482
|
-
|
|
271662
|
+
const sleep10 = deps.sleep ?? ((ms2) => new Promise((resolve110) => setTimeout(resolve110, ms2)));
|
|
271663
|
+
const QUIET_PARK_REASONS = /* @__PURE__ */ new Set([
|
|
271664
|
+
"no-pre-release-plan-review",
|
|
271665
|
+
"awaiting-approval",
|
|
271666
|
+
"paused",
|
|
271667
|
+
"plan-review-passed"
|
|
271668
|
+
]);
|
|
271669
|
+
const RETRY_DELAYS_MS2 = [1e3, 5e3];
|
|
271670
|
+
for (let attempt = 0; ; attempt++) {
|
|
271671
|
+
let failure = null;
|
|
271672
|
+
try {
|
|
271673
|
+
const live = await deps.getTask(deps.taskId);
|
|
271674
|
+
if (!live || live.paused || live.userPaused) return;
|
|
271675
|
+
if (live.status === "needs-replan") {
|
|
271676
|
+
deps.log(`Plan Review handoff for ${deps.taskId} not armed (needs-replan)`);
|
|
271677
|
+
return;
|
|
271678
|
+
}
|
|
271679
|
+
const ir2 = await deps.resolveIr(live.id);
|
|
271680
|
+
const result2 = await deps.seed(live, ir2);
|
|
271681
|
+
if (result2.seeded) {
|
|
271682
|
+
deps.kick();
|
|
271683
|
+
return;
|
|
271684
|
+
}
|
|
271685
|
+
if (result2.reason && QUIET_PARK_REASONS.has(result2.reason)) {
|
|
271686
|
+
deps.log(`Plan Review handoff for ${deps.taskId} not armed (${result2.reason})`);
|
|
271687
|
+
return;
|
|
271688
|
+
}
|
|
271689
|
+
failure = result2.reason ?? "not-seeded";
|
|
271690
|
+
} catch (error3) {
|
|
271691
|
+
failure = error3 instanceof Error ? error3.message : String(error3);
|
|
271692
|
+
}
|
|
271693
|
+
if (attempt >= RETRY_DELAYS_MS2.length) {
|
|
271694
|
+
deps.warn(
|
|
271695
|
+
`Plan Review handoff for ${deps.taskId} failed after ${attempt + 1} attempts (${failure}) \u2014 stranded-continuation self-healing will recover it`
|
|
271696
|
+
);
|
|
271697
|
+
return;
|
|
271698
|
+
}
|
|
271699
|
+
deps.warn(`Plan Review handoff for ${deps.taskId} did not seed (${failure}) \u2014 retrying`);
|
|
271700
|
+
await sleep10(RETRY_DELAYS_MS2[attempt]);
|
|
271701
|
+
}
|
|
271483
271702
|
}
|
|
271484
271703
|
async function drainDuePlanningContinuations(deps) {
|
|
271485
271704
|
const items = await deps.listDue();
|
|
@@ -271614,7 +271833,7 @@ function stableNotificationJson(value2) {
|
|
|
271614
271833
|
return `{${fields.join(",")}}`;
|
|
271615
271834
|
}
|
|
271616
271835
|
function buildCliAgentNotificationDedupeKey(input) {
|
|
271617
|
-
const notificationFingerprint =
|
|
271836
|
+
const notificationFingerprint = createHash32("sha256").update(stableNotificationJson(input.info.notification ?? null)).digest("hex").slice(0, 16);
|
|
271618
271837
|
const waitingEpoch = input.session?.updatedAt ?? "unknown-waiting-epoch";
|
|
271619
271838
|
return [
|
|
271620
271839
|
"cli-agent",
|
|
@@ -271769,6 +271988,8 @@ var init_in_process_runtime = __esm({
|
|
|
271769
271988
|
messageStore;
|
|
271770
271989
|
/** FNXC:TaskDeleteNotice 2026-07-26-16:10: identity-guarded teardown for the delete-notice mailbox seam. */
|
|
271771
271990
|
unregisterTaskDeleteNoticeMailbox;
|
|
271991
|
+
/** FNXC:TaskRecommendations 2026-08-13-03:56: identity-guarded teardown for the store-scoped recommendation notice seam. */
|
|
271992
|
+
unregisterTaskRecommendationNoticeMailbox;
|
|
271772
271993
|
chatStore;
|
|
271773
271994
|
detachAgentLinkSync;
|
|
271774
271995
|
/**
|
|
@@ -271827,7 +272048,8 @@ var init_in_process_runtime = __esm({
|
|
|
271827
272048
|
createTaskStoreForBackend: createTaskStoreForBackend2,
|
|
271828
272049
|
buildConsumerId: buildConsumerId2,
|
|
271829
272050
|
createProjectScopedPluginMcpProvider: createProjectScopedPluginMcpProvider2,
|
|
271830
|
-
registerTaskDeleteNoticeMailbox: registerTaskDeleteNoticeMailbox2
|
|
272051
|
+
registerTaskDeleteNoticeMailbox: registerTaskDeleteNoticeMailbox2,
|
|
272052
|
+
registerTaskRecommendationNoticeMailbox: registerTaskRecommendationNoticeMailbox2
|
|
271831
272053
|
} = await Promise.resolve().then(() => (init_src2(), src_exports));
|
|
271832
272054
|
if (this.config.externalTaskStore) {
|
|
271833
272055
|
this.taskStore = this.config.externalTaskStore;
|
|
@@ -271886,6 +272108,10 @@ var init_in_process_runtime = __esm({
|
|
|
271886
272108
|
this.taskStore,
|
|
271887
272109
|
this.messageStore
|
|
271888
272110
|
);
|
|
272111
|
+
this.unregisterTaskRecommendationNoticeMailbox = registerTaskRecommendationNoticeMailbox2(
|
|
272112
|
+
this.taskStore,
|
|
272113
|
+
this.messageStore
|
|
272114
|
+
);
|
|
271889
272115
|
await yieldEventLoop4();
|
|
271890
272116
|
const pluginLayer = this.taskStore.getAsyncLayer();
|
|
271891
272117
|
if (!pluginLayer) {
|
|
@@ -272377,9 +272603,19 @@ var init_in_process_runtime = __esm({
|
|
|
272377
272603
|
outcome: report2.outcome,
|
|
272378
272604
|
getTask: (id) => Promise.resolve(this.taskStore.getTask(id)),
|
|
272379
272605
|
resolveIr: (id) => resolveWorkflowIrForTask(this.taskStore, id),
|
|
272380
|
-
|
|
272606
|
+
/*
|
|
272607
|
+
FNXC:PlanningHandoffAtomicity 2026-08-13-03:49:
|
|
272608
|
+
The report carries the planning session's own durable work item id so the
|
|
272609
|
+
seeder can retire that exact predecessor row atomically with the successor
|
|
272610
|
+
install. Without it the seeder raced triage's finally-block terminal
|
|
272611
|
+
transition and bailed on its own caller (529 stranded cards in 18 days).
|
|
272612
|
+
*/
|
|
272613
|
+
seed: (task, ir2) => seedPreReleasePlanReviewContinuation(this.taskStore, task, ir2, {
|
|
272614
|
+
retirePredecessorId: report2.planningWorkItemId
|
|
272615
|
+
}),
|
|
272381
272616
|
kick: () => this.kickWorkflowContinuationProcessor(),
|
|
272382
|
-
log: (message) => runtimeLog.log(message)
|
|
272617
|
+
log: (message) => runtimeLog.log(message),
|
|
272618
|
+
warn: (message) => runtimeLog.warn(message)
|
|
272383
272619
|
}).catch((error3) => {
|
|
272384
272620
|
runtimeLog.error(`Failed to start Todo plan review for ${t.id}:`, error3);
|
|
272385
272621
|
});
|
|
@@ -272667,6 +272903,8 @@ var init_in_process_runtime = __esm({
|
|
|
272667
272903
|
this.backendShutdown = void 0;
|
|
272668
272904
|
this.unregisterTaskDeleteNoticeMailbox?.();
|
|
272669
272905
|
this.unregisterTaskDeleteNoticeMailbox = void 0;
|
|
272906
|
+
this.unregisterTaskRecommendationNoticeMailbox?.();
|
|
272907
|
+
this.unregisterTaskRecommendationNoticeMailbox = void 0;
|
|
272670
272908
|
let stopError;
|
|
272671
272909
|
try {
|
|
272672
272910
|
if (this.workflowContinuationTimer) {
|
|
@@ -280460,9 +280698,9 @@ import { access as access10, unlink as unlink11, writeFile as writeFile33 } from
|
|
|
280460
280698
|
import net2 from "node:net";
|
|
280461
280699
|
import { platform as platform3, tmpdir as tmpdir12 } from "node:os";
|
|
280462
280700
|
import { join as join91 } from "node:path";
|
|
280463
|
-
import { createHash as
|
|
280701
|
+
import { createHash as createHash33 } from "node:crypto";
|
|
280464
280702
|
function projectHash(projectId2) {
|
|
280465
|
-
return
|
|
280703
|
+
return createHash33("sha1").update(projectId2).digest("hex").slice(0, 16);
|
|
280466
280704
|
}
|
|
280467
280705
|
function computeEngineSocketPath(projectId2) {
|
|
280468
280706
|
const hash3 = projectHash(projectId2);
|
|
@@ -300272,9 +300510,9 @@ __export(import_translate_service_exports, {
|
|
|
300272
300510
|
selectEligibleItems: () => selectEligibleItems,
|
|
300273
300511
|
translateImportItems: () => translateImportItems
|
|
300274
300512
|
});
|
|
300275
|
-
import { createHash as
|
|
300513
|
+
import { createHash as createHash34 } from "node:crypto";
|
|
300276
300514
|
function hashSourceContent(title2, body) {
|
|
300277
|
-
return
|
|
300515
|
+
return createHash34("sha256").update(`${title2}\0${body}`).digest("hex");
|
|
300278
300516
|
}
|
|
300279
300517
|
function resolveTargetLocale(settingsLocale, requestLocale, globalLanguage) {
|
|
300280
300518
|
if (isLocale(settingsLocale)) return settingsLocale;
|
|
@@ -307276,7 +307514,7 @@ var init_auth_middleware = __esm({
|
|
|
307276
307514
|
});
|
|
307277
307515
|
|
|
307278
307516
|
// ../dashboard/src/routes/register-task-workflow-routes.ts
|
|
307279
|
-
import { createHash as
|
|
307517
|
+
import { createHash as createHash35 } from "node:crypto";
|
|
307280
307518
|
import { createReadStream } from "node:fs";
|
|
307281
307519
|
import { readFile as readFile53, stat as stat13 } from "node:fs/promises";
|
|
307282
307520
|
import { join as join96 } from "node:path";
|
|
@@ -307682,7 +307920,7 @@ function buildWorkflowReviewItemId(task, result2, findingId, resolution) {
|
|
|
307682
307920
|
findingId,
|
|
307683
307921
|
resolution
|
|
307684
307922
|
});
|
|
307685
|
-
return `workflow-review-${
|
|
307923
|
+
return `workflow-review-${createHash35("sha256").update(identity).digest("hex").slice(0, 24)}`;
|
|
307686
307924
|
}
|
|
307687
307925
|
async function buildWorkflowReviewItems(task, store) {
|
|
307688
307926
|
const declaredTopLevelReviewResultSources = await getDeclaredTopLevelReviewResultSources(task, store);
|
|
@@ -308131,6 +308369,32 @@ function registerTaskWorkflowRoutes(ctx, deps) {
|
|
|
308131
308369
|
rethrowAsApiError8(err);
|
|
308132
308370
|
}
|
|
308133
308371
|
});
|
|
308372
|
+
router.get("/tasks/recommendations", async (req, res) => {
|
|
308373
|
+
try {
|
|
308374
|
+
const { store: scopedStore } = await getProjectContext2(req);
|
|
308375
|
+
const parsePageNumber = (value2, name2) => {
|
|
308376
|
+
if (value2 === void 0) return void 0;
|
|
308377
|
+
if (typeof value2 !== "string" || value2.trim() === "" || !Number.isInteger(Number(value2)) || Number(value2) < 0) {
|
|
308378
|
+
throw badRequest(`${name2} must be a non-negative integer`);
|
|
308379
|
+
}
|
|
308380
|
+
return Number(value2);
|
|
308381
|
+
};
|
|
308382
|
+
const requestedLimit = parsePageNumber(req.query.limit, "limit");
|
|
308383
|
+
const offset = parsePageNumber(req.query.offset, "offset");
|
|
308384
|
+
if (requestedLimit === 0) throw badRequest("limit must be a positive integer");
|
|
308385
|
+
const limit2 = requestedLimit === void 0 ? void 0 : Math.min(200, requestedLimit);
|
|
308386
|
+
let completeColumns;
|
|
308387
|
+
try {
|
|
308388
|
+
completeColumns = await resolveProjectColumnsForRoles(scopedStore, ["complete"]);
|
|
308389
|
+
} catch {
|
|
308390
|
+
completeColumns = /* @__PURE__ */ new Set(["done"]);
|
|
308391
|
+
}
|
|
308392
|
+
res.json(await scopedStore.listTaskRecommendations({ completeColumns, limit: limit2, offset }));
|
|
308393
|
+
} catch (err) {
|
|
308394
|
+
if (err instanceof ApiError) throw err;
|
|
308395
|
+
rethrowAsApiError8(err);
|
|
308396
|
+
}
|
|
308397
|
+
});
|
|
308134
308398
|
router.post("/tasks/duplicate-check", async (req, res) => {
|
|
308135
308399
|
try {
|
|
308136
308400
|
const { store: scopedStore } = await getProjectContext2(req);
|
|
@@ -357318,8 +357582,8 @@ var init_register_settings_sync_routes = __esm({
|
|
|
357318
357582
|
exportedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
357319
357583
|
version: 1
|
|
357320
357584
|
};
|
|
357321
|
-
const { createHash:
|
|
357322
|
-
const checksum =
|
|
357585
|
+
const { createHash: createHash39 } = await import("node:crypto");
|
|
357586
|
+
const checksum = createHash39("sha256").update(JSON.stringify(payloadWithoutChecksum)).digest("hex");
|
|
357323
357587
|
const localPeerInfo = await central.getLocalPeerInfo();
|
|
357324
357588
|
await fetchFromRemoteNode(node, "/api/settings/sync-receive", {
|
|
357325
357589
|
method: "POST",
|
|
@@ -357390,7 +357654,7 @@ var init_register_settings_sync_routes = __esm({
|
|
|
357390
357654
|
});
|
|
357391
357655
|
return;
|
|
357392
357656
|
}
|
|
357393
|
-
const { createHash:
|
|
357657
|
+
const { createHash: createHash39 } = await import("node:crypto");
|
|
357394
357658
|
const exportedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
357395
357659
|
const payloadWithoutChecksum = {
|
|
357396
357660
|
global: remoteSettings.global,
|
|
@@ -357399,7 +357663,7 @@ var init_register_settings_sync_routes = __esm({
|
|
|
357399
357663
|
exportedAt,
|
|
357400
357664
|
version: 1
|
|
357401
357665
|
};
|
|
357402
|
-
const checksum =
|
|
357666
|
+
const checksum = createHash39("sha256").update(JSON.stringify(payloadWithoutChecksum)).digest("hex");
|
|
357403
357667
|
const result2 = await central.applyRemoteSettings({
|
|
357404
357668
|
...payloadWithoutChecksum,
|
|
357405
357669
|
checksum
|
|
@@ -384153,7 +384417,7 @@ var init_report_scrub = __esm({
|
|
|
384153
384417
|
});
|
|
384154
384418
|
|
|
384155
384419
|
// ../dashboard/src/report-pipeline.ts
|
|
384156
|
-
import { createHash as
|
|
384420
|
+
import { createHash as createHash36 } from "node:crypto";
|
|
384157
384421
|
function resolveReportMode(actionType, settings) {
|
|
384158
384422
|
return settings.reportModeByAction?.[actionType] ?? settings.reportMode ?? "draft-review";
|
|
384159
384423
|
}
|
|
@@ -384269,7 +384533,7 @@ async function embedScreenshot(args) {
|
|
|
384269
384533
|
try {
|
|
384270
384534
|
const extension = EXT_BY_MIME[attachment.mimeType];
|
|
384271
384535
|
if (!extension) return args.report;
|
|
384272
|
-
const safeId2 =
|
|
384536
|
+
const safeId2 = createHash36("sha256").update(`${args.report.sessionToken ?? ""}:${attachment.artifactId}`).digest("hex").slice(0, 32);
|
|
384273
384537
|
const path14 = `.fusion-reports/${safeId2}/screenshot.${extension}`;
|
|
384274
384538
|
const uploaded = await args.client.uploadImageAsset({ owner: args.owner, repo: args.repo, path: path14, contentBase64: Buffer.from(attachment.bytes).toString("base64"), message: "chore: add Fusion report screenshot", mimeType: attachment.mimeType });
|
|
384275
384539
|
const alt = markdownEscapeImageAlt(scrubReportText(attachment.filename, args.scrubContext) || "Report screenshot");
|
|
@@ -387383,7 +387647,7 @@ var init_types6 = __esm({
|
|
|
387383
387647
|
});
|
|
387384
387648
|
|
|
387385
387649
|
// ../dashboard/src/stt/model-manager.ts
|
|
387386
|
-
import { createHash as
|
|
387650
|
+
import { createHash as createHash37, randomUUID as randomUUID68 } from "node:crypto";
|
|
387387
387651
|
import { mkdir as mkdir40, open as open4, readFile as readFile63, readdir as readdir16, rename as rename12, rm as rm24, stat as stat18, writeFile as writeFile39 } from "node:fs/promises";
|
|
387388
387652
|
import { join as join125, relative as relative26, resolve as resolve75, sep as sep20 } from "node:path";
|
|
387389
387653
|
function parseSafeTarListing(listing) {
|
|
@@ -387472,7 +387736,7 @@ function createVoiceModelManager(options = {}) {
|
|
|
387472
387736
|
if (!response.ok || !response.body) throw Object.assign(new Error("download failed"), { voiceReason: "network" });
|
|
387473
387737
|
if (!current(g2, signal)) return state;
|
|
387474
387738
|
const total = Number(response.headers.get("content-length")) || void 0;
|
|
387475
|
-
const hash3 =
|
|
387739
|
+
const hash3 = createHash37("sha256");
|
|
387476
387740
|
let bytes = 0;
|
|
387477
387741
|
for await (const chunk of response.body) {
|
|
387478
387742
|
if (!current(g2, signal)) return state;
|
|
@@ -402718,7 +402982,7 @@ var init_extension = __esm({
|
|
|
402718
402982
|
});
|
|
402719
402983
|
|
|
402720
402984
|
// src/commands/task-lifecycle.ts
|
|
402721
|
-
import { createHash as
|
|
402985
|
+
import { createHash as createHash38 } from "node:crypto";
|
|
402722
402986
|
import { exec as exec63 } from "node:child_process";
|
|
402723
402987
|
import * as childProcess5 from "node:child_process";
|
|
402724
402988
|
import { mkdir as mkdir43, realpath as realpath7, rm as rm25 } from "node:fs/promises";
|
|
@@ -402891,7 +403155,7 @@ async function refreshAutomatedPrHead(input) {
|
|
|
402891
403155
|
await mkdir43(refreshWorktreesDir, { recursive: true });
|
|
402892
403156
|
temporary = join135(
|
|
402893
403157
|
refreshWorktreesDir,
|
|
402894
|
-
`pr-refresh-${
|
|
403158
|
+
`pr-refresh-${createHash38("sha256").update(input.headBranch).digest("hex").slice(0, 16)}`
|
|
402895
403159
|
);
|
|
402896
403160
|
const reservationDir = join135(root, ".fusion", "pr-refresh-reservations");
|
|
402897
403161
|
await mkdir43(reservationDir, { recursive: true });
|