@adhdev/daemon-standalone 0.9.82-rc.267 → 0.9.82-rc.268

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/public/index.html CHANGED
@@ -7,7 +7,7 @@
7
7
  <meta name="description" content="ADHDev self-hosted dashboard for controlling AI agents" />
8
8
  <link rel="icon" href="/otter-logo.png" />
9
9
  <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&display=swap" rel="stylesheet" />
10
- <script type="module" crossorigin src="/assets/index-Chc3cgJI.js"></script>
10
+ <script type="module" crossorigin src="/assets/index-DelY1D_j.js"></script>
11
11
  <link rel="modulepreload" crossorigin href="/assets/vendor-BHUMCOj6.js">
12
12
  <link rel="stylesheet" crossorigin href="/assets/index-CbR_x7-3.css">
13
13
  </head>
@@ -784,6 +784,42 @@ function buildCompactQueueMaintenanceReport(maintenance) {
784
784
  cleanupCandidatesHint: "Per-row cleanup candidates are omitted in compact mode; call mesh_view_queue with verbose=true for the full maintenance/cleanupDryRun rows."
785
785
  };
786
786
  }
787
+ var COMPACT_MAX_ACTIVE_QUEUE_ROWS = 15;
788
+ var COMPACT_QUEUE_MESSAGE_CAP = 140;
789
+ var COMPACT_MAX_ACTIVE_WORK_ROWS = 12;
790
+ function truncateForCompact(value, cap) {
791
+ if (typeof value !== "string") return value;
792
+ return value.length > cap ? value.slice(0, cap) + "\u2026" : value;
793
+ }
794
+ function compactQueueRow(task) {
795
+ if (!task || typeof task !== "object") return task;
796
+ const slim = {};
797
+ for (const [k, v] of Object.entries(task)) {
798
+ if (k === "message") slim[k] = truncateForCompact(v, COMPACT_QUEUE_MESSAGE_CAP);
799
+ else slim[k] = elideLargeNestedValue(k, v);
800
+ }
801
+ return slim;
802
+ }
803
+ function compactQueueRows(rows) {
804
+ const capped = rows.slice(0, COMPACT_MAX_ACTIVE_QUEUE_ROWS).map(compactQueueRow);
805
+ return { rows: capped, omitted: Math.max(0, rows.length - capped.length) };
806
+ }
807
+ function compactActiveWorkRecord(record) {
808
+ if (!record || typeof record !== "object") return record;
809
+ const slim = {};
810
+ for (const [k, v] of Object.entries(record)) {
811
+ if (k === "message") slim[k] = truncateForCompact(v, COMPACT_QUEUE_MESSAGE_CAP);
812
+ else if (k === "taskSummary") slim[k] = truncateForCompact(v, COMPACT_QUEUE_MESSAGE_CAP);
813
+ else if (k === "taskTitle") slim[k] = truncateForCompact(v, COMPACT_QUEUE_MESSAGE_CAP);
814
+ else slim[k] = elideLargeNestedValue(k, v);
815
+ }
816
+ return slim;
817
+ }
818
+ function compactActiveWorkRecords(records) {
819
+ if (!Array.isArray(records)) return { records, omitted: 0 };
820
+ const capped = records.slice(0, COMPACT_MAX_ACTIVE_WORK_ROWS).map(compactActiveWorkRecord);
821
+ return { records: capped, omitted: Math.max(0, records.length - capped.length) };
822
+ }
787
823
  function annotateQueueStaleness(queue, mesh) {
788
824
  const liveness = buildQueueLivenessIndex(mesh);
789
825
  const now = Date.now();
@@ -1119,6 +1155,105 @@ function buildCompactGitSnapshot(status) {
1119
1155
  }
1120
1156
  return slim;
1121
1157
  }
1158
+ function summarizeCompactSubmodules(submodules) {
1159
+ if (!Array.isArray(submodules) || submodules.length === 0) return void 0;
1160
+ const outOfSync = submodules.filter((s) => s?.outOfSync).map((s) => s?.path).filter(Boolean);
1161
+ return {
1162
+ count: submodules.length,
1163
+ ...outOfSync.length > 0 ? { outOfSyncPaths: outOfSync } : {}
1164
+ };
1165
+ }
1166
+ function compactMeshStatusNode(entry) {
1167
+ if (!entry || typeof entry !== "object") return entry;
1168
+ const next = { ...entry };
1169
+ if (next.git !== void 0) {
1170
+ const slimGit = buildCompactGitSnapshot(next.git);
1171
+ if (slimGit) {
1172
+ if (slimGit.submodules !== void 0) {
1173
+ const subSummary = summarizeCompactSubmodules(slimGit.submodules);
1174
+ if (subSummary) slimGit.submodules = subSummary;
1175
+ else delete slimGit.submodules;
1176
+ }
1177
+ next.git = slimGit;
1178
+ }
1179
+ }
1180
+ if (next.machine && typeof next.machine === "object") {
1181
+ const m = next.machine;
1182
+ next.machine = {
1183
+ daemonId: m.daemonId,
1184
+ machineId: m.machineId,
1185
+ hostname: m.hostname,
1186
+ displayName: m.displayName,
1187
+ sameMachine: m.sameMachine,
1188
+ locality: m.locality
1189
+ };
1190
+ }
1191
+ if (typeof next.submoduleWarning === "string") {
1192
+ next.submodulesOutOfSync = true;
1193
+ delete next.submoduleWarning;
1194
+ }
1195
+ if (next.staleDaemonBuild && typeof next.staleDaemonBuild === "object") {
1196
+ const b = next.staleDaemonBuild;
1197
+ next.staleDaemonBuild = {
1198
+ scope: b.scope,
1199
+ isDaemonAffecting: b.isDaemonAffecting !== false,
1200
+ seeStaleDaemonBuilds: true
1201
+ };
1202
+ }
1203
+ for (const k of Object.keys(next)) {
1204
+ if (k === "git" || k === "machine" || k === "branchConvergence" || k === "staleDaemonBuild" || k === "sessions") continue;
1205
+ next[k] = elideLargeNestedValue(k, next[k]);
1206
+ }
1207
+ return next;
1208
+ }
1209
+ var COMPACT_DETAILED_NODES_BYTE_BUDGET = 9e3;
1210
+ var COMPACT_NODES_TOTAL_BYTE_BUDGET = 13e3;
1211
+ function compactNodeSeverity(entry) {
1212
+ if (!entry || typeof entry !== "object") return 0;
1213
+ if (entry.error || entry.health && entry.health !== "online" && entry.health !== "dirty") return 5;
1214
+ if (entry.launchReady === false) return 4;
1215
+ if (entry.isDirty === true || entry.health === "dirty") return 3;
1216
+ if (entry.branchConvergence?.needsConvergence === true) return 2;
1217
+ if (entry.staleDaemonBuild || entry.submodulesOutOfSync || entry.recoveryHints) return 1;
1218
+ return 0;
1219
+ }
1220
+ function isNoteworthyCompactNode(entry) {
1221
+ if (!entry || typeof entry !== "object") return true;
1222
+ if (entry.health && entry.health !== "online") return true;
1223
+ if (entry.isDirty === true) return true;
1224
+ if (entry.error) return true;
1225
+ if (entry.launchReady === false) return true;
1226
+ if (entry.staleDaemonBuild) return true;
1227
+ if (entry.submoduleWarning || entry.submodulesOutOfSync) return true;
1228
+ if (entry.recoveryHints) return true;
1229
+ if (Array.isArray(entry.nextStepHints) && entry.nextStepHints.length > 0) return true;
1230
+ if (entry.branchConvergence?.needsConvergence === true) return true;
1231
+ const sessionCount = Array.isArray(entry.sessions) ? entry.sessions.length : entry.sessionSummary?.total ?? 0;
1232
+ if (sessionCount > 0) return true;
1233
+ return false;
1234
+ }
1235
+ function minimalCompactNode(entry) {
1236
+ if (!entry || typeof entry !== "object") return entry;
1237
+ const bc = entry.branchConvergence && typeof entry.branchConvergence === "object" ? {
1238
+ status: entry.branchConvergence.status,
1239
+ needsConvergence: entry.branchConvergence.needsConvergence,
1240
+ reason: entry.branchConvergence.reason,
1241
+ branch: entry.branchConvergence.branch
1242
+ } : void 0;
1243
+ return {
1244
+ nodeId: entry.nodeId,
1245
+ workspace: entry.workspace,
1246
+ daemonId: entry.daemonId,
1247
+ health: entry.health,
1248
+ branch: entry.branch,
1249
+ launchReady: entry.launchReady,
1250
+ ...entry.providerPriority !== void 0 ? { providerPriority: entry.providerPriority } : {},
1251
+ ...entry.launchBlockedReason !== void 0 ? { launchBlockedReason: entry.launchBlockedReason } : {},
1252
+ ...bc ? { branchConvergence: bc } : {},
1253
+ ...entry.sessionSummary ? { sessionSummary: entry.sessionSummary } : {},
1254
+ folded: true
1255
+ };
1256
+ }
1122
1257
  function summarizeNodeSessions(sessions) {
1123
1258
  const list = Array.isArray(sessions) ? sessions : [];
1124
1259
  const byStatus = {};
@@ -1910,20 +2045,36 @@ function buildBranchConvergence(mesh, node, status, dirty, uncommittedChanges) {
1910
2045
  nextStep: `Review and merge branch '${branch}' into ${defaultBranch}; do not report the task as fully complete while it remains off main.`
1911
2046
  };
1912
2047
  }
1913
- function summarizeBranchConvergence(nodes) {
1914
- const followUps = nodes.filter((node) => node?.branchConvergence?.needsConvergence === true).map((node) => ({
2048
+ var COMPACT_MAX_CONVERGENCE_FOLLOWUPS = 12;
2049
+ function summarizeBranchConvergence(nodes, compact = false) {
2050
+ const allFollowUps = nodes.filter((node) => node?.branchConvergence?.needsConvergence === true).map((node) => ({
1915
2051
  nodeId: node.nodeId,
1916
- workspace: node.workspace,
2052
+ // workspace is a long absolute path redundant with nodeId — drop it in
2053
+ // compact mode to keep this summary bounded.
2054
+ ...compact ? {} : { workspace: node.workspace },
1917
2055
  branch: node.branchConvergence.branch,
1918
2056
  status: node.branchConvergence.status,
1919
2057
  reason: node.branchConvergence.reason,
1920
- nextStep: node.branchConvergence.nextStep
2058
+ // The per-node nextStep is long prose that repeats node ids/branch names.
2059
+ // In compact mode drop it (the status+reason carry the actionable signal;
2060
+ // verbose still surfaces the full nextStep) so this summary stays bounded
2061
+ // as node count grows.
2062
+ ...compact ? {} : { nextStep: node.branchConvergence.nextStep }
1921
2063
  }));
2064
+ const byStatus = {};
2065
+ for (const f of allFollowUps) {
2066
+ const s = typeof f.status === "string" ? f.status : "unknown";
2067
+ byStatus[s] = (byStatus[s] ?? 0) + 1;
2068
+ }
2069
+ const followUps = compact ? allFollowUps.slice(0, COMPACT_MAX_CONVERGENCE_FOLLOWUPS) : allFollowUps;
2070
+ const omitted = allFollowUps.length - followUps.length;
1922
2071
  return {
1923
- needsFollowUp: followUps.length > 0,
1924
- unresolvedCount: followUps.length,
2072
+ needsFollowUp: allFollowUps.length > 0,
2073
+ unresolvedCount: allFollowUps.length,
2074
+ byStatus,
1925
2075
  requiredFinalStates: ["merged_to_main", "pushed_feature_branch_needs_merge", "blocked_review", "cleanup_candidate", "not_mergeable"],
1926
- followUps
2076
+ followUps,
2077
+ ...omitted > 0 ? { followUpsOmitted: omitted, followUpsHint: "Per-node followUp rows are capped in compact mode; counts above are complete. Use verbose=true for the full list." } : {}
1927
2078
  };
1928
2079
  }
1929
2080
  async function commandForNode(ctx, node, command, args = {}) {
@@ -2652,25 +2803,83 @@ async function meshStatus(ctx, args = {}) {
2652
2803
  head: behind.head,
2653
2804
  isDaemonAffecting,
2654
2805
  ...Array.isArray(behind.affectedPackages) && behind.affectedPackages.length > 0 ? { affectedPackages: behind.affectedPackages } : {},
2655
- warning: behind.warning
2806
+ // The full ~300-char warning prose is identical for every entry and is
2807
+ // already emitted ONCE at the top level as `staleDaemonBuildWarning`.
2808
+ // Keep it per-entry only in verbose to avoid N× duplication in compact.
2809
+ ...compact ? {} : { warning: behind.warning }
2656
2810
  });
2657
2811
  }
2658
2812
  const daemonAffectingStaleBuilds = staleDaemonBuilds.filter((b) => b.isDaemonAffecting !== false);
2659
2813
  const webOnlyStaleBuilds = staleDaemonBuilds.filter((b) => b.isDaemonAffecting === false);
2660
- const nodesForResponse = compact ? results.map((entry) => {
2661
- if (!entry || typeof entry !== "object") return entry;
2662
- const next = { ...entry };
2663
- if (next.git !== void 0) {
2664
- const slimGit = buildCompactGitSnapshot(next.git);
2665
- if (slimGit) next.git = slimGit;
2814
+ let stubbedNodeCount = 0;
2815
+ let foldedNodesSummary;
2816
+ const nodesForResponse = compact ? (() => {
2817
+ const compacted = results.map((entry) => {
2818
+ const next = compactMeshStatusNode(entry);
2819
+ if (!next || typeof next !== "object") return next;
2820
+ if (Array.isArray(next.sessions)) {
2821
+ next.sessionSummary = summarizeNodeSessions(next.sessions);
2822
+ if (!includeSessions) delete next.sessions;
2823
+ }
2824
+ if (next.daemonBuild !== void 0) delete next.daemonBuild;
2825
+ return next;
2826
+ });
2827
+ const noteworthy = compacted.filter((n) => n && typeof n === "object" && isNoteworthyCompactNode(n));
2828
+ const ranked = [...noteworthy].sort((a, b) => compactNodeSeverity(b) - compactNodeSeverity(a));
2829
+ const detailedIds = /* @__PURE__ */ new Set();
2830
+ let detailSpent = 0;
2831
+ for (const n of ranked) {
2832
+ const cost = JSON.stringify(n).length + 1;
2833
+ if (detailedIds.size === 0 || detailSpent + cost <= COMPACT_DETAILED_NODES_BYTE_BUDGET) {
2834
+ detailedIds.add(String(n.nodeId));
2835
+ detailSpent += cost;
2836
+ }
2666
2837
  }
2667
- if (Array.isArray(next.sessions)) {
2668
- next.sessionSummary = summarizeNodeSessions(next.sessions);
2669
- if (!includeSessions) delete next.sessions;
2838
+ const stubOrder = [...compacted].filter((n) => n && typeof n === "object").sort((a, b) => compactNodeSeverity(b) - compactNodeSeverity(a));
2839
+ const keptIds = new Set(detailedIds);
2840
+ let totalSpent = detailSpent;
2841
+ for (const n of stubOrder) {
2842
+ const id = String(n.nodeId);
2843
+ if (keptIds.has(id)) continue;
2844
+ const stubCost = JSON.stringify(minimalCompactNode(n)).length + 1;
2845
+ if (totalSpent + stubCost <= COMPACT_NODES_TOTAL_BYTE_BUDGET) {
2846
+ keptIds.add(id);
2847
+ totalSpent += stubCost;
2848
+ }
2849
+ }
2850
+ const fullyFolded = [];
2851
+ const out = compacted.map((n) => {
2852
+ if (!n || typeof n !== "object") return n;
2853
+ const id = String(n.nodeId);
2854
+ if (detailedIds.has(id)) return n;
2855
+ if (keptIds.has(id)) {
2856
+ stubbedNodeCount += 1;
2857
+ return minimalCompactNode(n);
2858
+ }
2859
+ fullyFolded.push(n);
2860
+ return null;
2861
+ }).filter((n) => n !== null);
2862
+ if (fullyFolded.length > 0) {
2863
+ const byBranchConvergence = {};
2864
+ const byHealth = {};
2865
+ const nodeIds = [];
2866
+ for (const n of fullyFolded) {
2867
+ const bc = typeof n?.branchConvergence?.status === "string" ? n.branchConvergence.status : "unknown";
2868
+ byBranchConvergence[bc] = (byBranchConvergence[bc] ?? 0) + 1;
2869
+ const h = typeof n?.health === "string" ? n.health : "unknown";
2870
+ byHealth[h] = (byHealth[h] ?? 0) + 1;
2871
+ if (n?.nodeId) nodeIds.push(String(n.nodeId));
2872
+ }
2873
+ foldedNodesSummary = {
2874
+ count: fullyFolded.length,
2875
+ note: "Node-array byte budget reached: these nodes are listed by id only. Query a specific node_id or use verbose=true for their detail.",
2876
+ byHealth,
2877
+ byBranchConvergence,
2878
+ nodeIds
2879
+ };
2670
2880
  }
2671
- if (next.daemonBuild !== void 0) delete next.daemonBuild;
2672
- return next;
2673
- }) : results;
2881
+ return out;
2882
+ })() : results;
2674
2883
  const response = {
2675
2884
  meshId: mesh.id,
2676
2885
  meshName: mesh.name,
@@ -2685,6 +2894,10 @@ async function meshStatus(ctx, args = {}) {
2685
2894
  historicalEvidenceOnly: ["recoveryHints", "ledgerSummary"]
2686
2895
  },
2687
2896
  nodes: nodesForResponse,
2897
+ ...compact && stubbedNodeCount > 0 ? {
2898
+ stubbedNodesNote: `${stubbedNodeCount} node(s) in the array above are reduced to a minimal stub (marked folded:true) in compact mode \u2014 healthy/clean nodes plus any beyond the detail byte-budget. They remain addressable by node_id; use verbose=true for their full detail.`
2899
+ } : {},
2900
+ ...compact && foldedNodesSummary ? { foldedNodes: foldedNodesSummary } : {},
2688
2901
  ...compact && Object.keys(daemonSessions).length > 0 ? { daemonSessions } : {},
2689
2902
  ...Object.keys(daemonBuilds).length > 0 ? { daemonBuilds } : {},
2690
2903
  ...staleDaemonBuilds.length > 0 ? { staleDaemonBuilds } : {},
@@ -2702,7 +2915,7 @@ async function meshStatus(ctx, args = {}) {
2702
2915
  activeWorkSummary: activeWorkEvidence.summary,
2703
2916
  ...pollingGuidance ? { pollingGuidance } : {},
2704
2917
  ...rateResult.rateLimitExceeded ? { pollingRateAdvisory: { type: "rate_limit_exceeded", tool: "mesh_status", callsInWindow: rateResult.callsInWindow, message: rateResult.advisory } } : {},
2705
- branchConvergenceSummary: summarizeBranchConvergence(results),
2918
+ branchConvergenceSummary: summarizeBranchConvergence(results, compact),
2706
2919
  ...coordinatorSessions.length > 0 ? {
2707
2920
  coordinatorSessions,
2708
2921
  selfIdentification: {
@@ -3132,9 +3345,12 @@ async function meshViewQueue(ctx, args) {
3132
3345
  const staleAssignedTasks = maintenance.staleAssignedTasks || [];
3133
3346
  const requestedHistoricalRows = queue.some((task) => HISTORICAL_QUEUE_STATUSES.has(String(task?.status || "")));
3134
3347
  const pollingGuidance = buildActiveWorkPollingGuidance(activeWorkEvidence.summary);
3135
- const visibleQueue = compact ? queue.filter((task) => !HISTORICAL_QUEUE_STATUSES.has(String(task?.status || ""))) : queue;
3348
+ const activeOnlyQueue = queue.filter((task) => !HISTORICAL_QUEUE_STATUSES.has(String(task?.status || "")));
3349
+ const compactQueueResult = compact ? compactQueueRows(activeOnlyQueue) : { rows: activeOnlyQueue, omitted: 0 };
3350
+ const visibleQueue = compact ? compactQueueResult.rows : queue;
3136
3351
  const wantActiveQueueArray = view === "active" || statusFilter?.some((status) => ACTIVE_QUEUE_STATUSES.has(status));
3137
3352
  const wantHistoricalQueueArray = !compact && (view === "historical" || requestedHistoricalRows);
3353
+ const activeWorkResult = compact ? compactActiveWorkRecords(activeWorkEvidence.activeWork) : { records: activeWorkEvidence.activeWork, omitted: 0 };
3138
3354
  const staleDirectWorkSummary = (0, import_daemon_core.buildCompactStaleDirectWorkSummary)(activeWorkEvidence.staleDirectWork, {
3139
3355
  note: activeWorkEvidence.staleDirectWorkNote,
3140
3356
  detailHint: "Full stale direct entries are omitted from mesh_view_queue in compact mode. Call mesh_view_queue with verbose=true, or inspect mesh_task_history for ledger detail."
@@ -3156,7 +3372,15 @@ async function meshViewQueue(ctx, args) {
3156
3372
  },
3157
3373
  queue: visibleQueue,
3158
3374
  ...compact ? { historicalRowsOmitted: true, historicalRowsHint: "Completed/failed/cancelled rows are omitted in compact mode; see historicalCounts. Call mesh_view_queue with verbose=true (or view=historical, compact=false) for full rows." } : {},
3159
- activeWork: activeWorkEvidence.activeWork,
3375
+ ...compact && compactQueueResult.omitted > 0 ? {
3376
+ activeRowsOmitted: compactQueueResult.omitted,
3377
+ activeRowsHint: `Showing the first ${COMPACT_MAX_ACTIVE_QUEUE_ROWS} active rows (per-row messages truncated). ${compactQueueResult.omitted} more active row(s) omitted \u2014 see activeCount/activeCounts for the complete total or use verbose=true.`
3378
+ } : {},
3379
+ activeWork: activeWorkResult.records,
3380
+ ...compact && activeWorkResult.omitted > 0 ? {
3381
+ activeWorkOmitted: activeWorkResult.omitted,
3382
+ activeWorkHint: `Showing the first ${COMPACT_MAX_ACTIVE_WORK_ROWS} active-work records (messages truncated). ${activeWorkResult.omitted} more omitted \u2014 see activeWorkSummary for complete counts or use verbose=true.`
3383
+ } : {},
3160
3384
  staleDirectWorkSummary,
3161
3385
  ...compact ? {} : { staleDirectWork: activeWorkEvidence.staleDirectWork },
3162
3386
  activeWorkSummary: activeWorkEvidence.summary,
@@ -3172,7 +3396,7 @@ async function meshViewQueue(ctx, args) {
3172
3396
  historicalCount: summary.historicalCount,
3173
3397
  visibleActiveCount: visibleSummary.activeCount,
3174
3398
  visibleHistoricalCount: visibleSummary.historicalCount,
3175
- staleAssignedTasks,
3399
+ staleAssignedTasks: compact ? staleAssignedTasks.slice(0, 10).map(compactQueueRow) : staleAssignedTasks,
3176
3400
  staleAssignedCount: maintenance.staleAssignedCount,
3177
3401
  queueMaintenance: maintenanceForResponse,
3178
3402
  cleanupDryRun: maintenanceForResponse,
@@ -3181,14 +3405,18 @@ async function meshViewQueue(ctx, args) {
3181
3405
  dispatchFailureCount: recentDispatchFailures.length,
3182
3406
  dispatchFailureNote: "Remote P2P dispatch attempts that failed. Affected tasks remain pending and may require mesh_queue_requeue if no idle session picks them up."
3183
3407
  } : {},
3184
- ...wantActiveQueueArray ? {
3408
+ ...wantActiveQueueArray && !compact ? {
3185
3409
  activeQueue: queue.filter((task) => ACTIVE_QUEUE_STATUSES.has(String(task?.status || "")))
3186
3410
  } : {},
3411
+ // In compact mode the `queue` field already holds exactly the slimmed+
3412
+ // capped active rows, so the separate activeQueue array would be a verbatim
3413
+ // duplicate (it doubled the payload). Point callers at `queue` instead.
3414
+ ...wantActiveQueueArray && compact ? { activeQueueHint: "In compact mode the active rows are in `queue` (already filtered to pending/assigned). Use verbose=true for the separate full activeQueue array." } : {},
3187
3415
  ...wantHistoricalQueueArray ? {
3188
3416
  historicalQueue: queue.filter((task) => HISTORICAL_QUEUE_STATUSES.has(String(task?.status || "")))
3189
3417
  } : {},
3190
3418
  // Back-compat alias for callers already reading the first hardening payload.
3191
- staleAssignments: staleAssignedTasks
3419
+ staleAssignments: compact ? staleAssignedTasks.slice(0, 10).map(compactQueueRow) : staleAssignedTasks
3192
3420
  }, null, 2);
3193
3421
  } catch (e) {
3194
3422
  return JSON.stringify({ success: false, error: e.message });