@runfusion/fusion 0.43.0 → 0.43.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.
Files changed (91) hide show
  1. package/dist/bin.js +167 -27
  2. package/dist/client/.vite/manifest.json +70 -70
  3. package/dist/client/assets/AgentDetailView-BGN03dyz.css +1 -0
  4. package/dist/client/assets/{AgentDetailView-FUKwQxBP.js → AgentDetailView-DKMz3r04.js} +1 -1
  5. package/dist/client/assets/{AgentPermissionPolicyEditor-DMDUhF1n.js → AgentPermissionPolicyEditor-BiY1a4KR.js} +1 -1
  6. package/dist/client/assets/{AgentsView-BrQLd-yI.js → AgentsView-Co-k4vjh.js} +3 -3
  7. package/dist/client/assets/{ChatView-Wz_0goif.js → ChatView-BkAG99bj.js} +1 -1
  8. package/dist/client/assets/{DevServerView-DRqQpHsc.js → DevServerView-C6DC0URX.js} +1 -1
  9. package/dist/client/assets/{DirectoryPicker-BFot4CVM.js → DirectoryPicker-CkcGjyv0.js} +1 -1
  10. package/dist/client/assets/{DocumentsView-hamhUcvL.js → DocumentsView-OCK1Vsw_.js} +1 -1
  11. package/dist/client/assets/{EvalsView-DAXqDqn2.js → EvalsView-CUfyj5GW.js} +1 -1
  12. package/dist/client/assets/{ExperimentalAgentOnboardingModal-B4aZ1y0n.js → ExperimentalAgentOnboardingModal-Dau9RTU_.js} +1 -1
  13. package/dist/client/assets/{GoalsView-2QOp9DA0.js → GoalsView-CNLTn0rX.js} +1 -1
  14. package/dist/client/assets/{InsightsView-D5fzFy-F.js → InsightsView-BQPxHxKI.js} +1 -1
  15. package/dist/client/assets/{MemoryView-B082KoR-.js → MemoryView-D3xQIFjj.js} +1 -1
  16. package/dist/client/assets/{NodesView-BA3pKMZu.js → NodesView-CSMvGwDU.js} +1 -1
  17. package/dist/client/assets/{PiExtensionsManager-C4I11iKm.js → PiExtensionsManager-BtqXF3fl.js} +1 -1
  18. package/dist/client/assets/{PluginManager-BzTzTMXZ.js → PluginManager-CSSDb3VO.js} +1 -1
  19. package/dist/client/assets/{PullRequestView-11xJ565q.js → PullRequestView-Bjyfffdu.js} +1 -1
  20. package/dist/client/assets/{ReliabilityView-CpELpGqw.js → ReliabilityView-QKMUDebT.js} +1 -1
  21. package/dist/client/assets/{ResearchView-BHiXfjzE.js → ResearchView-CRU_NPho.js} +1 -1
  22. package/dist/client/assets/{SecretsView-CC5OYoCn.js → SecretsView-Bs8ySyC5.js} +1 -1
  23. package/dist/client/assets/SecretsView-Djo1rahi.css +1 -0
  24. package/dist/client/assets/{SessionTerminal-G70Jwkzs.js → SessionTerminal-Dk1NgmN2.js} +1 -1
  25. package/dist/client/assets/{SettingsModal-C0M1CqOu.js → SettingsModal-JCaNvdAb.js} +3 -3
  26. package/dist/client/assets/{SettingsModal-BKEbtdqR.js → SettingsModal-Nw5cTKAK.js} +1 -1
  27. package/dist/client/assets/{SetupWizardModal-CBfItlP6.js → SetupWizardModal-CE79myEy.js} +1 -1
  28. package/dist/client/assets/{SkillsView-DbcW87-E.js → SkillsView-Dc8YskAX.js} +1 -1
  29. package/dist/client/assets/{StashRecoveryView-CH9RPtzX.js → StashRecoveryView-CqKOFiXT.js} +1 -1
  30. package/dist/client/assets/{TodoView-ToviJ0SV.js → TodoView-BqIRwcZw.js} +1 -1
  31. package/dist/client/assets/{WorkflowNodeEditor-BTu0D9c5.js → WorkflowNodeEditor-2jDuk2FR.js} +1 -1
  32. package/dist/client/assets/{dashboard-view-DtgLZ_LM.js → dashboard-view-BhbN8LPh.js} +1 -1
  33. package/dist/client/assets/{folder-open-BlPyIWyf.js → folder-open-Bw1mxVfa.js} +1 -1
  34. package/dist/client/assets/{index-bZCpHtGq.js → index-CpTBp1RG.js} +192 -192
  35. package/dist/client/assets/{upload-B-qmm1NH.js → upload-BCmd-1I0.js} +1 -1
  36. package/dist/client/assets/{users-D6C5TXf2.js → users-DO_t3V1p.js} +1 -1
  37. package/dist/client/index.html +1 -1
  38. package/dist/client/version.json +1 -1
  39. package/dist/droid-cli/package.json +1 -1
  40. package/dist/extension.js +166 -27
  41. package/dist/pi-claude-cli/package.json +1 -1
  42. package/dist/plugin-sdk/index.d.ts +2 -0
  43. package/dist/plugins/fusion-plugin-acp-runtime/package.json +1 -1
  44. package/dist/plugins/fusion-plugin-cli-printing-press/package.json +1 -1
  45. package/dist/plugins/fusion-plugin-compound-engineering/package.json +1 -1
  46. package/dist/plugins/fusion-plugin-cursor-runtime/package.json +1 -1
  47. package/dist/plugins/fusion-plugin-dependency-graph/package.json +1 -1
  48. package/dist/plugins/fusion-plugin-droid-runtime/package.json +1 -1
  49. package/dist/plugins/fusion-plugin-hermes-runtime/package.json +1 -1
  50. package/dist/plugins/fusion-plugin-openclaw-runtime/package.json +1 -1
  51. package/dist/plugins/fusion-plugin-paperclip-runtime/package.json +1 -1
  52. package/dist/plugins/fusion-plugin-reports/package.json +1 -1
  53. package/dist/plugins/fusion-plugin-roadmap/package.json +1 -1
  54. package/dist/plugins/fusion-plugin-whatsapp-chat/package.json +1 -1
  55. package/package.json +1 -1
  56. package/dist/automation-store-EKXXEE2S.js +0 -10
  57. package/dist/automation-store-PLNG3X72.js +0 -10
  58. package/dist/automation-store-RDDYZFUJ.js +0 -10
  59. package/dist/chunk-2JI3F6MG.js +0 -948
  60. package/dist/chunk-4L6CLWJC.js +0 -8345
  61. package/dist/chunk-4VNS5WPM.js +0 -42
  62. package/dist/chunk-5RGECGQL.js +0 -1139
  63. package/dist/chunk-6JDLN7IL.js +0 -409
  64. package/dist/chunk-AICJATVW.js +0 -948
  65. package/dist/chunk-AWKNRUOR.js +0 -1148
  66. package/dist/chunk-BHM3UYWS.js +0 -4651
  67. package/dist/chunk-BMUXDSBF.js +0 -4647
  68. package/dist/chunk-GETECT6V.js +0 -353
  69. package/dist/chunk-GUV4QQT3.js +0 -1143
  70. package/dist/chunk-JKQO7YYZ.js +0 -8369
  71. package/dist/chunk-LYZVU6UV.js +0 -409
  72. package/dist/chunk-MAN4WYHO.js +0 -353
  73. package/dist/chunk-MCUG2Z7M.js +0 -4651
  74. package/dist/chunk-PSDYB45U.js +0 -948
  75. package/dist/chunk-RR2HM46R.js +0 -8345
  76. package/dist/chunk-RXMQ5OMY.js +0 -9226
  77. package/dist/chunk-S2EVJUY3.js +0 -353
  78. package/dist/chunk-UXR5XZFZ.js +0 -409
  79. package/dist/client/assets/AgentDetailView-DiWELtb1.css +0 -1
  80. package/dist/client/assets/SecretsView-D5bHZ-wM.css +0 -1
  81. package/dist/extract-zip-WL55Z3AU.js +0 -2497
  82. package/dist/index.min-CHQ3ABYJ.js +0 -2926
  83. package/dist/memory-dreams-7USISKVE.js +0 -32
  84. package/dist/memory-dreams-PBPISUDD.js +0 -32
  85. package/dist/memory-dreams-XNO2B2QF.js +0 -32
  86. package/dist/migration-EH2YOCYQ.js +0 -15
  87. package/dist/migration-PLGTTKL5.js +0 -15
  88. package/dist/migration-WZEZK22R.js +0 -15
  89. package/dist/routine-store-GIJ6MXWY.js +0 -10
  90. package/dist/routine-store-HTVC2PUQ.js +0 -10
  91. package/dist/routine-store-KGHZBPDF.js +0 -10
package/dist/bin.js CHANGED
@@ -2295,6 +2295,25 @@ var init_redact_secrets = __esm({
2295
2295
  }
2296
2296
  });
2297
2297
 
2298
+ // ../core/src/near-duplicate-canonical.ts
2299
+ function isActiveNearDuplicateColumn(column) {
2300
+ return column !== "archived" && column !== "done";
2301
+ }
2302
+ function isNearDuplicateCanonicalInactive(canonical) {
2303
+ if (!canonical) {
2304
+ return true;
2305
+ }
2306
+ if (canonical.deletedAt) {
2307
+ return true;
2308
+ }
2309
+ return !isActiveNearDuplicateColumn(canonical.column);
2310
+ }
2311
+ var init_near_duplicate_canonical = __esm({
2312
+ "../core/src/near-duplicate-canonical.ts"() {
2313
+ "use strict";
2314
+ }
2315
+ });
2316
+
2298
2317
  // ../core/src/frontend-ux-policy.ts
2299
2318
  function applyFrontendUxCriteria(promptMarkdown, fileScopePaths) {
2300
2319
  if (promptMarkdown.includes(FRONTEND_UX_HEADING)) {
@@ -48225,6 +48244,7 @@ var init_store = __esm({
48225
48244
  init_stalled_review_detector();
48226
48245
  init_retry_summary();
48227
48246
  init_duplicate_intake();
48247
+ init_near_duplicate_canonical();
48228
48248
  init_task_id_integrity();
48229
48249
  init_mesh_task_replication();
48230
48250
  init_step_parsers();
@@ -52545,6 +52565,65 @@ ${newTask.description}
52545
52565
  `).all(trimmedFingerprint, cutoffIso);
52546
52566
  return rows.map((row) => this.rowToTask(row));
52547
52567
  }
52568
+ /**
52569
+ * FNXC:NearDuplicateDetection 2026-06-14-12:00:
52570
+ * FN-6439 requires the store to reconcile persisted duplicate flags after a canonical becomes inactive.
52571
+ * sourceMetadataPatch only merges, so this reverse lookup performs a bounded read-modify-write that strips stale near-duplicate keys without pausing or failing the referencing tasks.
52572
+ */
52573
+ async clearNearDuplicateReferencesTo(canonicalId, inactiveState) {
52574
+ if (!isNearDuplicateCanonicalInactive(inactiveState)) {
52575
+ return [];
52576
+ }
52577
+ const selectClause = this.getTaskSelectClause(false, "t");
52578
+ const rows = this.db.prepare(`
52579
+ SELECT ${selectClause}
52580
+ FROM tasks t
52581
+ WHERE t."deletedAt" IS NULL
52582
+ AND t."column" != 'archived'
52583
+ AND t."column" != 'done'
52584
+ AND json_extract(t.sourceMetadata, '$.nearDuplicateOf') = ?
52585
+ ORDER BY t.createdAt ASC
52586
+ `).all(canonicalId);
52587
+ const updatedTasks = [];
52588
+ for (const row of rows) {
52589
+ const task = this.rowToTask(row);
52590
+ const nextSourceMetadata = { ...task.sourceMetadata ?? {} };
52591
+ delete nextSourceMetadata.nearDuplicateOf;
52592
+ delete nextSourceMetadata.nearDuplicateScore;
52593
+ delete nextSourceMetadata.nearDuplicateSharedTokens;
52594
+ delete nextSourceMetadata.nearDuplicateDismissed;
52595
+ task.sourceMetadata = Object.keys(nextSourceMetadata).length > 0 ? nextSourceMetadata : void 0;
52596
+ const updatedAt = (/* @__PURE__ */ new Date()).toISOString();
52597
+ task.updatedAt = updatedAt;
52598
+ task.log = [
52599
+ ...task.log ?? [],
52600
+ {
52601
+ timestamp: updatedAt,
52602
+ action: `Near-duplicate canonical ${canonicalId} is now inactive (${inactiveState.reason}); cleared duplicate flag (informational, no decision required)`
52603
+ }
52604
+ ];
52605
+ this.db.transactionImmediate(() => {
52606
+ this.upsertTaskWithFtsRecovery(task);
52607
+ this.db.bumpLastModified();
52608
+ });
52609
+ await this.writeTaskJsonFile(this.taskDir(task.id), task);
52610
+ if (this.isWatching) this.taskCache.set(task.id, { ...task });
52611
+ this.emit("task:updated", task);
52612
+ updatedTasks.push(task);
52613
+ }
52614
+ return updatedTasks;
52615
+ }
52616
+ async clearNearDuplicateReferencesToFailSoft(canonicalId, inactiveState) {
52617
+ try {
52618
+ await this.clearNearDuplicateReferencesTo(canonicalId, inactiveState);
52619
+ } catch (error) {
52620
+ storeLog.warn("Failed to clear stale near-duplicate references (degraded)", {
52621
+ taskId: canonicalId,
52622
+ reason: inactiveState.reason,
52623
+ error: error instanceof Error ? error.message : String(error)
52624
+ });
52625
+ }
52626
+ }
52548
52627
  async getTasksByAssignedAgent(agentId, options) {
52549
52628
  const whereClauses = ["assignedAgentId = ?", _TaskStore.ACTIVE_TASKS_WHERE];
52550
52629
  const params = [agentId];
@@ -52928,6 +53007,12 @@ ${newTask.description}
52928
53007
  if (this.isWatching) this.taskCache.set(id, { ...task });
52929
53008
  this.emit("task:updated", task);
52930
53009
  }
53010
+ if (toColumn === "done") {
53011
+ await this.clearNearDuplicateReferencesToFailSoft(id, {
53012
+ column: "done",
53013
+ reason: "done"
53014
+ });
53015
+ }
52931
53016
  return task;
52932
53017
  }
52933
53018
  const fromColumn = task.column;
@@ -53311,6 +53396,12 @@ ${newTask.description}
53311
53396
  if (fromColumn !== toColumn) {
53312
53397
  this.emit("task:moved", { task, from: fromColumn, to: toColumn, source: moveSource });
53313
53398
  }
53399
+ if (toColumn === "done") {
53400
+ await this.clearNearDuplicateReferencesToFailSoft(id, {
53401
+ column: "done",
53402
+ reason: "done"
53403
+ });
53404
+ }
53314
53405
  return task;
53315
53406
  }
53316
53407
  /**
@@ -55756,7 +55847,7 @@ ${newTask.description}
55756
55847
  * a no-op and does not re-emit task:deleted.
55757
55848
  */
55758
55849
  async deleteTask(id, options) {
55759
- return this.withTaskLock(id, async () => {
55850
+ const deletedTask = await this.withTaskLock(id, async () => {
55760
55851
  this.flushAgentLogBuffer();
55761
55852
  const task = this.readTaskFromDb(id, { includeDeleted: true });
55762
55853
  if (!task) {
@@ -55831,6 +55922,12 @@ ${newTask.description}
55831
55922
  this.emit("task:deleted", task, { githubIssueAction: options?.githubIssueAction ?? "auto" });
55832
55923
  return task;
55833
55924
  });
55925
+ await this.clearNearDuplicateReferencesToFailSoft(id, {
55926
+ column: "archived",
55927
+ deletedAt: deletedTask.deletedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
55928
+ reason: "deleted"
55929
+ });
55930
+ return deletedTask;
55834
55931
  }
55835
55932
  deleteTaskById(taskId) {
55836
55933
  this.clearLinkedAgentTaskIds(taskId);
@@ -56289,7 +56386,7 @@ ${newTask.description}
56289
56386
  * or an options object that also allows removeLineageReferences.
56290
56387
  */
56291
56388
  async archiveTask(id, optionsOrCleanup = true) {
56292
- return this.withTaskLock(id, async () => {
56389
+ const archivedTask = await this.withTaskLock(id, async () => {
56293
56390
  const dir2 = this.taskDir(id);
56294
56391
  const task = await this.readTaskJson(dir2);
56295
56392
  if (!task.log) {
@@ -56360,6 +56457,11 @@ ${newTask.description}
56360
56457
  this.emit("task:moved", { task, from: fromColumn, to: "archived", source: "engine" });
56361
56458
  return this.archiveEntryToTask(entry, false);
56362
56459
  });
56460
+ await this.clearNearDuplicateReferencesToFailSoft(id, {
56461
+ column: "archived",
56462
+ reason: "archived"
56463
+ });
56464
+ return archivedTask;
56363
56465
  }
56364
56466
  /**
56365
56467
  * Archive a task and immediately clean up its directory.
@@ -60413,6 +60515,7 @@ var init_near_duplicate = __esm({
60413
60515
  "../core/src/near-duplicate.ts"() {
60414
60516
  "use strict";
60415
60517
  init_duplicate_detection();
60518
+ init_near_duplicate_canonical();
60416
60519
  DEFAULT_WINDOW_MS3 = 7 * 24 * 60 * 60 * 1e3;
60417
60520
  DEFAULT_LIMIT2 = 5;
60418
60521
  DEFAULT_MIN_SHARED_TOKENS = 2;
@@ -82743,6 +82846,7 @@ __export(src_exports, {
82743
82846
  importSettings: () => importSettings,
82744
82847
  installQmd: () => installQmd,
82745
82848
  instanceNodeId: () => instanceNodeId,
82849
+ isActiveNearDuplicateColumn: () => isActiveNearDuplicateColumn,
82746
82850
  isAgentPermissionPolicyPresetId: () => isAgentPermissionPolicyPresetId,
82747
82851
  isApiTrigger: () => isApiTrigger,
82748
82852
  isBranchGroupComplete: () => isBranchGroupComplete,
@@ -82772,6 +82876,7 @@ __export(src_exports, {
82772
82876
  isMeshIntentState: () => isMeshIntentState,
82773
82877
  isMeshWriteClass: () => isMeshWriteClass,
82774
82878
  isMovedSettingsKey: () => isMovedSettingsKey,
82879
+ isNearDuplicateCanonicalInactive: () => isNearDuplicateCanonicalInactive,
82775
82880
  isPolicyBroaderThanDefault: () => isPolicyBroaderThanDefault,
82776
82881
  isPrBacked: () => isPrBacked,
82777
82882
  isPrEntityActionable: () => isPrEntityActionable,
@@ -83076,6 +83181,7 @@ var init_src = __esm({
83076
83181
  init_branch_assignment();
83077
83182
  init_custom_provider_key();
83078
83183
  init_redact_secrets();
83184
+ init_near_duplicate_canonical();
83079
83185
  init_frontend_ux_policy();
83080
83186
  init_mock_provider_constants();
83081
83187
  init_zai_provider();
@@ -120224,9 +120330,13 @@ var init_self_healing = __esm({
120224
120330
  * Terminal contract for stuck-loop exhaustion and no-progress churn:
120225
120331
  * - `STUCK_LOOP_EXHAUSTED`: increments the kill budget until exhausted. Once
120226
120332
  * exhausted, tasks with incomplete steps are moved back to `todo` with
120227
- * progress preserved and pause metadata reapplied for manual resume or
120333
+ * progress preserved, marked failed, and paused for manual resume or
120228
120334
  * decomposition; tasks with only terminal steps keep the legacy failed
120229
120335
  * `in-review` handoff path.
120336
+ *
120337
+ * FNXC:SelfHealing 2026-06-14-10:51:
120338
+ * Incomplete stuck-loop exhaustion must park work in a failed/paused state before moving columns, because a post-move patch failure must not leave the task scheduler-runnable.
120339
+ * Engine-owned recovery must not mutate `userPaused`; user intent stays authoritative across races.
120230
120340
  * - `STUCK_NO_PROGRESS_CHURN`: skips the budget entirely and terminalizes on
120231
120341
  * the first trigger with operator guidance to decompose or rescope.
120232
120342
  *
@@ -120313,8 +120423,25 @@ var init_self_healing = __esm({
120313
120423
  );
120314
120424
  return false;
120315
120425
  }
120316
- log22.warn(`${taskId} exceeded stuck kill budget (${newCount}/${maxKills}, reason=${reason}) with incomplete steps \u2014 re-queueing in todo with progress preserved`);
120317
- await this.store.updateTask(taskId, { stuckKillCount: newCount });
120426
+ log22.warn(`${taskId} exceeded stuck kill budget (${newCount}/${maxKills}, reason=${reason}) with incomplete steps \u2014 parking in todo with progress preserved`);
120427
+ const exhaustedError2 = `STUCK_LOOP_EXHAUSTED: incomplete task exhausted stuck kill budget (${newCount}/${maxKills}) after last reason=${reason}. Progress was preserved; manually retry, decompose, or rescope before execution resumes.`;
120428
+ const parkUpdate = {
120429
+ stuckKillCount: newCount,
120430
+ status: "failed",
120431
+ error: exhaustedError2,
120432
+ paused: true,
120433
+ pausedReason: "stuck-loop-exhausted-manual-intervention-required",
120434
+ pausedByAgentId: "self-healing",
120435
+ assignedAgentId: null,
120436
+ checkedOutBy: null,
120437
+ checkedOutAt: null,
120438
+ checkoutNodeId: null,
120439
+ checkoutRunId: null,
120440
+ checkoutLeaseRenewedAt: null,
120441
+ checkoutLeaseEpoch: 0,
120442
+ nextRecoveryAt: null
120443
+ };
120444
+ await this.store.updateTask(taskId, parkUpdate);
120318
120445
  try {
120319
120446
  await this.store.moveTask(taskId, "todo", {
120320
120447
  preserveProgress: true,
@@ -120325,33 +120452,43 @@ var init_self_healing = __esm({
120325
120452
  });
120326
120453
  } catch (moveErr) {
120327
120454
  const moveErrMessage = moveErr instanceof Error ? moveErr.message : String(moveErr);
120328
- log22.warn(`${taskId} moveTask(todo) failed (${moveErrMessage}) after incomplete STUCK_LOOP_EXHAUSTED terminalization \u2014 falling back to executor stuck-kill requeue`);
120455
+ log22.warn(`${taskId} moveTask(todo) failed (${moveErrMessage}) after incomplete STUCK_LOOP_EXHAUSTED terminalization \u2014 marking failed/paused in place`);
120456
+ try {
120457
+ await this.store.updateTask(taskId, parkUpdate);
120458
+ } catch (patchErr) {
120459
+ const patchErrMessage = patchErr instanceof Error ? patchErr.message : String(patchErr);
120460
+ log22.warn(`${taskId} in-place park patch failed after moveTask(todo) failure during incomplete STUCK_LOOP_EXHAUSTED terminalization: ${patchErrMessage}`);
120461
+ await this.store.logEntry(
120462
+ taskId,
120463
+ `STUCK_LOOP_EXHAUSTED: incomplete task failed to move to todo (${moveErrMessage}), and the in-place park patch also failed (${patchErrMessage}); pre-move park metadata was already applied, but operator verification is required before retry.`
120464
+ );
120465
+ return false;
120466
+ }
120467
+ try {
120468
+ await this.store.logEntry(
120469
+ taskId,
120470
+ `STUCK_LOOP_EXHAUSTED: incomplete task exhausted stuck kill budget (${newCount}/${maxKills}), last reason=${reason}. Failed to move task to todo (${moveErrMessage}); task was marked failed/paused in place and will not be automatically retried.`
120471
+ );
120472
+ } catch (logErr) {
120473
+ const logErrMessage = logErr instanceof Error ? logErr.message : String(logErr);
120474
+ log22.warn(`${taskId} failed to log in-place stuck-loop park success after moveTask(todo) failure: ${logErrMessage}`);
120475
+ }
120476
+ return false;
120477
+ }
120478
+ try {
120479
+ await this.store.updateTask(taskId, parkUpdate);
120329
120480
  await this.store.logEntry(
120330
120481
  taskId,
120331
- `STUCK_LOOP_EXHAUSTED: incomplete task exhausted stuck kill budget (${newCount}/${maxKills}), last reason=${reason}. Failed to move task to todo (${moveErrMessage}); falling back to executor stuck-kill requeue.`
120482
+ `STUCK_LOOP_EXHAUSTED: incomplete task exhausted stuck kill budget (${newCount}/${maxKills}), last reason=${reason}. Parked in todo with progress preserved; no further automatic retries will run until an operator manually retries, decomposes, or rescopes the task.`
120332
120483
  );
120333
- return true;
120334
- }
120335
- const requeueUpdate = {
120336
- stuckKillCount: newCount,
120337
- paused: false,
120338
- pausedReason: null,
120339
- status: "queued"
120340
- };
120341
- try {
120342
- await this.store.updateTask(taskId, requeueUpdate);
120343
120484
  } catch (patchErr) {
120344
120485
  const patchErrMessage = patchErr instanceof Error ? patchErr.message : String(patchErr);
120345
- log22.warn(`${taskId} post-move requeue patch failed after incomplete STUCK_LOOP_EXHAUSTED terminalization: ${patchErrMessage}`);
120486
+ log22.warn(`${taskId} post-move park patch failed after incomplete STUCK_LOOP_EXHAUSTED terminalization: ${patchErrMessage}`);
120346
120487
  await this.store.logEntry(
120347
120488
  taskId,
120348
- `STUCK_LOOP_EXHAUSTED: incomplete task moved to todo with progress preserved, but post-move requeue patch failed (${patchErrMessage}); scheduler retry may wait for the next state repair pass.`
120489
+ `STUCK_LOOP_EXHAUSTED: incomplete task moved to todo with progress preserved, but post-move park patch failed (${patchErrMessage}); operator repair is required before retry.`
120349
120490
  );
120350
120491
  }
120351
- await this.store.logEntry(
120352
- taskId,
120353
- `STUCK_LOOP_EXHAUSTED: incomplete task exhausted stuck kill budget (${newCount}/${maxKills}), last reason=${reason}. Re-queued in todo with progress preserved; scheduler may retry without manual unpause.`
120354
- );
120355
120492
  return false;
120356
120493
  }
120357
120494
  log22.warn(`${taskId} exceeded stuck kill budget (${newCount}/${maxKills}, reason=${reason}) \u2014 marking failed`);
@@ -129635,6 +129772,10 @@ Take a completely different approach to writing this specification. Do NOT repea
129635
129772
  if (!canonicalTask) {
129636
129773
  return;
129637
129774
  }
129775
+ if (isNearDuplicateCanonicalInactive(canonicalTask)) {
129776
+ planLog.log(`${task.id}: near-duplicate candidate ${canonical.id} is inactive; skipping near-duplicate flag`);
129777
+ return;
129778
+ }
129638
129779
  if (isStrictlyOlderOrTieCanonical(canonicalTask)) {
129639
129780
  await this.store.updateTask(task.id, {
129640
129781
  sourceMetadataPatch: {
@@ -173693,15 +173834,13 @@ async function submitResponse(sessionId, responses, rootDir, promptOverrides, st
173693
173834
  thinkingOutput: session.lastGeneratedThinking || ""
173694
173835
  };
173695
173836
  session.error = void 0;
173837
+ session.history.push(historyEntry);
173696
173838
  persistSession(session, "generating");
173697
173839
  if (!session.agent) {
173698
- await ensureSessionAgent(session, rootDir, session.history, promptOverrides, store);
173840
+ await ensureSessionAgent(session, rootDir, session.history.slice(0, -1), promptOverrides, store);
173699
173841
  }
173700
173842
  const message = formatResponseForAgent(currentQuestion, responses);
173701
173843
  await continueAgentConversation(session, message);
173702
- if (!session.error) {
173703
- session.history.push(historyEntry);
173704
- }
173705
173844
  }
173706
173845
  if (session.summary) {
173707
173846
  return { type: "complete", data: session.summary };
@@ -286412,6 +286551,7 @@ export default definePlugin({
286412
286551
  version: "0.1.0",
286413
286552
  description: "A standalone Fusion plugin",
286414
286553
  },
286554
+ state: "installed",
286415
286555
  hooks: {
286416
286556
  onLoad: async (ctx) => {
286417
286557
  ctx.logger.info("${titleCase} plugin loaded");