@runfusion/fusion 0.45.0 → 0.46.0

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 (116) hide show
  1. package/dist/bin.js +531 -99
  2. package/dist/client/.vite/manifest.json +244 -244
  3. package/dist/client/assets/{AgentDetailView-DJTi6hKC.js → AgentDetailView-D1cA9Bfj.js} +1 -1
  4. package/dist/client/assets/{AgentPermissionPolicyEditor-C5DR9dUS.js → AgentPermissionPolicyEditor-DE0wv8-L.js} +1 -1
  5. package/dist/client/assets/{AgentsView-BNd90PSx.js → AgentsView-Bm_FA_1w.js} +3 -3
  6. package/dist/client/assets/{ChatView-B7JaZCL_.js → ChatView-CHEkov6q.js} +1 -1
  7. package/dist/client/assets/CommandCenter-Cfgek-dC.js +71 -0
  8. package/dist/client/assets/{CommandCenter-Xs5Ftv8s.css → CommandCenter-DDjpYkPe.css} +1 -1
  9. package/dist/client/assets/DevServerView-DgDksVH2.css +1 -0
  10. package/dist/client/assets/DevServerView-_or2KLVw.js +1 -0
  11. package/dist/client/assets/{DirectoryPicker-DegxT8ia.js → DirectoryPicker-etVwa-6X.js} +1 -1
  12. package/dist/client/assets/{DocumentsView-kVVQYISc.js → DocumentsView-e8ZTdPIZ.js} +1 -1
  13. package/dist/client/assets/{EvalsView-C9-iTSat.js → EvalsView-CjDRQFMQ.js} +1 -1
  14. package/dist/client/assets/{ExperimentalAgentOnboardingModal-DjP_xNkc.js → ExperimentalAgentOnboardingModal-DXR0OAsR.js} +1 -1
  15. package/dist/client/assets/{GoalsView-VoIHJJ5l.js → GoalsView-WWDKVslN.js} +1 -1
  16. package/dist/client/assets/{InsightsView-BIZaUcpd.js → InsightsView-DxIfxOzx.js} +1 -1
  17. package/dist/client/assets/{MemoryView-7v7rv6ns.js → MemoryView-BVW2hkWf.js} +1 -1
  18. package/dist/client/assets/{PiExtensionsManager-CB89rV4U.js → PiExtensionsManager-CpSfMok2.js} +1 -1
  19. package/dist/client/assets/{PluginManager-BNSuW_R4.js → PluginManager-CpBCy656.js} +1 -1
  20. package/dist/client/assets/{PullRequestView-CI5jdKBL.js → PullRequestView-BMspX1ga.js} +1 -1
  21. package/dist/client/assets/{ResearchView-BT5dR_m8.js → ResearchView--YEtcv_s.js} +1 -1
  22. package/dist/client/assets/{SecretsView-WPYI58Uo.js → SecretsView-CC6QDMWN.js} +1 -1
  23. package/dist/client/assets/{SessionTerminal-C6gyOWLt.js → SessionTerminal-DJGtgIls.js} +1 -1
  24. package/dist/client/assets/{SettingsModal-Bq_3AbaB.js → SettingsModal-4d_p8D7W.js} +1 -1
  25. package/dist/client/assets/SettingsModal-ino68pI2.css +1 -0
  26. package/dist/client/assets/SettingsModal-wABa7xmZ.js +21 -0
  27. package/dist/client/assets/{SetupWizardModal-CrgbnR_d.js → SetupWizardModal-DHe2tXzx.js} +2 -2
  28. package/dist/client/assets/{ShadcnColorPicker-1icHuwhC.js → ShadcnColorPicker-HX3j1v66.js} +1 -1
  29. package/dist/client/assets/{SkillsView-byuSe3e0.js → SkillsView-mdFVTX-r.js} +1 -1
  30. package/dist/client/assets/{TodoView-CQ9GjYBg.js → TodoView-DQVugDpW.js} +1 -1
  31. package/dist/client/assets/{WorkflowNodeEditor-DW7sJZUX.js → WorkflowNodeEditor-CeERQHHu.js} +1 -1
  32. package/dist/client/assets/{agentSkills-CeytXLHF.js → agentSkills-C2v1wbxh.js} +1 -1
  33. package/dist/client/assets/{app-7-5DWLtg.js → app-BJGkp7Tt.js} +3 -3
  34. package/dist/client/assets/{app-CZ2LTFce.js → app-BKLUvvm8.js} +3 -3
  35. package/dist/client/assets/{app-Cv9xEnll.js → app-BaoNC9zg.js} +1 -1
  36. package/dist/client/assets/{app-x_yPcO5Y.js → app-CZQ_fFNf.js} +3 -3
  37. package/dist/client/assets/{app-CSvE5Noc.js → app-DAu3AzsS.js} +3 -3
  38. package/dist/client/assets/{app-3wbZ08YC.js → app-DgezOJub.js} +1 -1
  39. package/dist/client/assets/{architectureDiagram-3BPJPVTR-BRI0QwDf.js → architectureDiagram-3BPJPVTR-CGEhhgX_.js} +1 -1
  40. package/dist/client/assets/{blockDiagram-GPEHLZMM-BXkN8Hv_.js → blockDiagram-GPEHLZMM-D0DTo0HT.js} +1 -1
  41. package/dist/client/assets/{c4Diagram-AAUBKEIU-C_Kcokep.js → c4Diagram-AAUBKEIU-DNykNaRb.js} +1 -1
  42. package/dist/client/assets/channel-Dwf1FoGU.js +1 -0
  43. package/dist/client/assets/{chunk-2J33WTMH-BGeuCz9C.js → chunk-2J33WTMH-5oQfAhmr.js} +1 -1
  44. package/dist/client/assets/{chunk-4BX2VUAB-DcVdctr0.js → chunk-4BX2VUAB-BqLZXgFw.js} +1 -1
  45. package/dist/client/assets/{chunk-55IACEB6-Dg6gDigQ.js → chunk-55IACEB6-C1oIjX3T.js} +1 -1
  46. package/dist/client/assets/{chunk-727SXJPM-B9B-vlEb.js → chunk-727SXJPM-BaovQTgk.js} +1 -1
  47. package/dist/client/assets/{chunk-AQP2D5EJ-LrWQ-2yi.js → chunk-AQP2D5EJ-B4ikBK42.js} +1 -1
  48. package/dist/client/assets/{chunk-FMBD7UC4-Bnd6hAED.js → chunk-FMBD7UC4-5zgtNnG2.js} +1 -1
  49. package/dist/client/assets/{chunk-ND2GUHAM-nAw93UB5.js → chunk-ND2GUHAM-ByrypRna.js} +1 -1
  50. package/dist/client/assets/{chunk-QZHKN3VN-CgprKcZo.js → chunk-QZHKN3VN-B7D1exsu.js} +1 -1
  51. package/dist/client/assets/classDiagram-4FO5ZUOK-WqSUwcK_.js +1 -0
  52. package/dist/client/assets/classDiagram-v2-Q7XG4LA2-WqSUwcK_.js +1 -0
  53. package/dist/client/assets/{cose-bilkent-S5V4N54A-Bhn0g_iK.js → cose-bilkent-S5V4N54A-CQmiNzGr.js} +1 -1
  54. package/dist/client/assets/{dagre-BM42HDAG-CP4kfwqd.js → dagre-BM42HDAG-BH8Uk0Up.js} +1 -1
  55. package/dist/client/assets/{dashboard-view-CM6Xin_H.js → dashboard-view-CWJ-b59n.js} +1 -1
  56. package/dist/client/assets/{dashboard-view-DV1nEhh9.js → dashboard-view-D3PWY2PH.js} +1 -1
  57. package/dist/client/assets/{diagram-2AECGRRQ-DPhzVEUf.js → diagram-2AECGRRQ-CDoHfkxY.js} +1 -1
  58. package/dist/client/assets/{diagram-5GNKFQAL-8QOC3K_L.js → diagram-5GNKFQAL-DARILCuD.js} +1 -1
  59. package/dist/client/assets/{diagram-KO2AKTUF-C1twgEch.js → diagram-KO2AKTUF-CNP-qi0y.js} +1 -1
  60. package/dist/client/assets/{diagram-LMA3HP47-3bEegSuf.js → diagram-LMA3HP47-SCiVmkcf.js} +1 -1
  61. package/dist/client/assets/{diagram-OG6HWLK6-BJ_x0rm6.js → diagram-OG6HWLK6-iTJLXH61.js} +1 -1
  62. package/dist/client/assets/{erDiagram-TEJ5UH35-DNiiS5q6.js → erDiagram-TEJ5UH35-ByMpiPIa.js} +1 -1
  63. package/dist/client/assets/{flowDiagram-I6XJVG4X-DoouPklt.js → flowDiagram-I6XJVG4X-DW3m3ZpM.js} +1 -1
  64. package/dist/client/assets/{folder-open-CuUs2W7f.js → folder-open-G-9vPAdv.js} +1 -1
  65. package/dist/client/assets/{ganttDiagram-6RSMTGT7-BrR6VnP5.js → ganttDiagram-6RSMTGT7-BJeYH7Ol.js} +1 -1
  66. package/dist/client/assets/{gitGraphDiagram-PVQCEYII-BV8_J6Ee.js → gitGraphDiagram-PVQCEYII-CK_Chj4m.js} +1 -1
  67. package/dist/client/assets/index-ccFe_1av.js +1459 -0
  68. package/dist/client/assets/{infoDiagram-5YYISTIA-DGwIIFkR.js → infoDiagram-5YYISTIA-D8Wg1IgN.js} +1 -1
  69. package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-D5dEH4RE.js → ishikawaDiagram-YF4QCWOH-DWROR2aX.js} +1 -1
  70. package/dist/client/assets/{journeyDiagram-JHISSGLW-BuuSWPw5.js → journeyDiagram-JHISSGLW-Bns9774_.js} +1 -1
  71. package/dist/client/assets/{kanban-definition-UN3LZRKU-DA34uUla.js → kanban-definition-UN3LZRKU-QtURfAoI.js} +1 -1
  72. package/dist/client/assets/{mermaid.core-Ch4HatqA.js → mermaid.core-DqgrgWWm.js} +4 -4
  73. package/dist/client/assets/{mindmap-definition-RKZ34NQL-DUCG-qD3.js → mindmap-definition-RKZ34NQL-jLaDb5_X.js} +1 -1
  74. package/dist/client/assets/{pieDiagram-4H26LBE5-DWvFGiLa.js → pieDiagram-4H26LBE5-CjbHuIje.js} +1 -1
  75. package/dist/client/assets/{quadrantDiagram-W4KKPZXB-OPTVW3WT.js → quadrantDiagram-W4KKPZXB-xgHbylQr.js} +1 -1
  76. package/dist/client/assets/{requirementDiagram-4Y6WPE33-D7feZvlU.js → requirementDiagram-4Y6WPE33-CHdD7W41.js} +1 -1
  77. package/dist/client/assets/{sankeyDiagram-5OEKKPKP-AtnSsEX1.js → sankeyDiagram-5OEKKPKP-C3me87g9.js} +1 -1
  78. package/dist/client/assets/{sequenceDiagram-3UESZ5HK-BZjHUeI5.js → sequenceDiagram-3UESZ5HK-DSHfs1kU.js} +1 -1
  79. package/dist/client/assets/{shield-alert-CzaF9ROV.js → shield-alert-DkGlhVjI.js} +1 -1
  80. package/dist/client/assets/{stateDiagram-AJRCARHV-C8j23Pvn.js → stateDiagram-AJRCARHV-C08n7sMP.js} +1 -1
  81. package/dist/client/assets/{stateDiagram-v2-BHNVJYJU-CiZR_S5-.js → stateDiagram-v2-BHNVJYJU-BosoAbfO.js} +1 -1
  82. package/dist/client/assets/{timeline-definition-PNZ67QCA-DvfNz25n.js → timeline-definition-PNZ67QCA-C21h9Zqh.js} +1 -1
  83. package/dist/client/assets/{upload-DTsYywhN.js → upload-B9B-tYt9.js} +1 -1
  84. package/dist/client/assets/{users-yAd09tKP.js → users-C_BA3C7E.js} +1 -1
  85. package/dist/client/assets/{vennDiagram-CIIHVFJN-CG2aMt3v.js → vennDiagram-CIIHVFJN-Bv3G0dwI.js} +1 -1
  86. package/dist/client/assets/{wardley-L42UT6IY-BnhBteen.js → wardley-L42UT6IY-WX0hHKcN.js} +1 -1
  87. package/dist/client/assets/{wardleyDiagram-YWT4CUSO-DwqTzM3T.js → wardleyDiagram-YWT4CUSO-CMwIPWm7.js} +1 -1
  88. package/dist/client/assets/{xychartDiagram-2RQKCTM6-5Cv2ZKMV.js → xychartDiagram-2RQKCTM6-CZvFdt6j.js} +1 -1
  89. package/dist/client/index.html +1 -1
  90. package/dist/client/version.json +1 -1
  91. package/dist/droid-cli/package.json +1 -1
  92. package/dist/extension.js +472 -94
  93. package/dist/pi-claude-cli/package.json +1 -1
  94. package/dist/plugin-sdk/index.d.ts +11 -0
  95. package/dist/plugins/fusion-plugin-acp-runtime/package.json +1 -1
  96. package/dist/plugins/fusion-plugin-cli-printing-press/package.json +1 -1
  97. package/dist/plugins/fusion-plugin-compound-engineering/package.json +1 -1
  98. package/dist/plugins/fusion-plugin-cursor-runtime/package.json +1 -1
  99. package/dist/plugins/fusion-plugin-dependency-graph/package.json +1 -1
  100. package/dist/plugins/fusion-plugin-droid-runtime/package.json +1 -1
  101. package/dist/plugins/fusion-plugin-hermes-runtime/package.json +1 -1
  102. package/dist/plugins/fusion-plugin-openclaw-runtime/package.json +1 -1
  103. package/dist/plugins/fusion-plugin-paperclip-runtime/package.json +1 -1
  104. package/dist/plugins/fusion-plugin-reports/package.json +1 -1
  105. package/dist/plugins/fusion-plugin-roadmap/package.json +1 -1
  106. package/dist/plugins/fusion-plugin-whatsapp-chat/package.json +1 -1
  107. package/package.json +1 -1
  108. package/dist/client/assets/CommandCenter-CHO21xEW.js +0 -74
  109. package/dist/client/assets/DevServerView-B_p91Mj_.css +0 -1
  110. package/dist/client/assets/DevServerView-H9OkT1ld.js +0 -1
  111. package/dist/client/assets/SettingsModal-BZokaNyx.css +0 -1
  112. package/dist/client/assets/SettingsModal-JHACoQJe.js +0 -21
  113. package/dist/client/assets/channel-Clzpzu32.js +0 -1
  114. package/dist/client/assets/classDiagram-4FO5ZUOK-CzYHP-af.js +0 -1
  115. package/dist/client/assets/classDiagram-v2-Q7XG4LA2-CzYHP-af.js +0 -1
  116. package/dist/client/assets/index-CZcWjLAb.js +0 -1459
package/dist/extension.js CHANGED
@@ -433,6 +433,9 @@ var init_settings_schema = __esm({
433
433
  defaultProvider: void 0,
434
434
  defaultModelId: void 0,
435
435
  testMode: void 0,
436
+ modelPricingOverrides: void 0,
437
+ modelPricingFetchedAt: void 0,
438
+ modelPricingSource: void 0,
436
439
  modelRouterEnabled: void 0,
437
440
  modelRouterCheapProvider: void 0,
438
441
  modelRouterCheapModelId: void 0,
@@ -49376,6 +49379,9 @@ import { randomUUID as randomUUID15 } from "node:crypto";
49376
49379
  import { mkdir as mkdir7, readdir as readdir5, readFile as readFile8, stat as stat3, writeFile as writeFile6, rename as rename4, unlink as unlink3 } from "node:fs/promises";
49377
49380
  import { join as join20 } from "node:path";
49378
49381
  import { existsSync as existsSync16, watch } from "node:fs";
49382
+ function isWorkflowColumnsCompatibilityFlagEnabled(settings) {
49383
+ return settings?.experimentalFeatures?.workflowColumns === true;
49384
+ }
49379
49385
  function defineTaskColumn(column, serialize, sqlIdentifier = column) {
49380
49386
  return { column, sqlIdentifier, serialize };
49381
49387
  }
@@ -49690,7 +49696,6 @@ var init_store = __esm({
49690
49696
  init_moved_settings();
49691
49697
  init_workflow_ir();
49692
49698
  init_workflow_steps_to_ir();
49693
- init_workflow_columns_settings();
49694
49699
  init_workflow_transitions();
49695
49700
  init_plugin_gate_verdict();
49696
49701
  init_trait_registry();
@@ -50488,7 +50493,7 @@ var init_store = __esm({
50488
50493
  }
50489
50494
  try {
50490
50495
  const settings = await this.getSettingsFast();
50491
- if (isWorkflowColumnsEnabled(settings)) {
50496
+ if (isWorkflowColumnsCompatibilityFlagEnabled(settings)) {
50492
50497
  await this.runWorkflowColumnsIntegrityPass();
50493
50498
  await this.recoverStaleTransitionPending();
50494
50499
  } else {
@@ -52292,7 +52297,7 @@ ${TASK_UPSERT_SQL_ASSIGNMENTS}
52292
52297
  await this.writeConfig(config);
52293
52298
  const updatedMerged = { ...DEFAULT_SETTINGS, ...globalSettings, ...updatedProjectSettings };
52294
52299
  this.emit("settings:updated", { settings: updatedMerged, previous: previousMerged });
52295
- if (isWorkflowColumnsEnabled(previousMerged) && !isWorkflowColumnsEnabled(updatedMerged)) {
52300
+ if (isWorkflowColumnsCompatibilityFlagEnabled(previousMerged) && !isWorkflowColumnsCompatibilityFlagEnabled(updatedMerged)) {
52296
52301
  try {
52297
52302
  await this.evacuateCustomColumnsToLegacy("flag-toggled-off");
52298
52303
  } catch (err) {
@@ -52375,7 +52380,7 @@ ${TASK_UPSERT_SQL_ASSIGNMENTS}
52375
52380
  merged.secretsSyncPassphraseConfigured = false;
52376
52381
  }
52377
52382
  this.emit("settings:updated", { settings: merged, previous });
52378
- if (isWorkflowColumnsEnabled(previous) && !isWorkflowColumnsEnabled(merged)) {
52383
+ if (isWorkflowColumnsCompatibilityFlagEnabled(previous) && !isWorkflowColumnsCompatibilityFlagEnabled(merged)) {
52379
52384
  try {
52380
52385
  await this.evacuateCustomColumnsToLegacy("flag-toggled-off");
52381
52386
  } catch (err) {
@@ -54619,7 +54624,8 @@ ${newTask.description}
54619
54624
  return { kind: "engine" };
54620
54625
  }
54621
54626
  resolveWorkflowBypassGuards(moveSource, options) {
54622
- return options?.recoveryRehome === true || (options?.bypassGuards ?? (moveSource === "engine" || moveSource === "scheduler" || options?.skipMergeBlocker === true));
54627
+ void moveSource;
54628
+ return options?.recoveryRehome === true || (options?.bypassGuards ?? (options?.moveSource === "engine" || options?.moveSource === "scheduler" || options?.skipMergeBlocker === true));
54623
54629
  }
54624
54630
  shouldSkipWorkflowMovePolicies(params) {
54625
54631
  if (params.bypassGuards) return true;
@@ -54630,7 +54636,7 @@ ${newTask.description}
54630
54636
  const task = await this.readTaskForMove(id);
54631
54637
  const moveSource = options?.moveSource ?? "engine";
54632
54638
  const mergedSettingsForMove = await this.getSettingsFast();
54633
- if (!isWorkflowColumnsEnabled(mergedSettingsForMove)) return void 0;
54639
+ if (!isWorkflowColumnsCompatibilityFlagEnabled(mergedSettingsForMove)) return void 0;
54634
54640
  if (task.column === toColumn) return void 0;
54635
54641
  const workflowIr = this.resolveTaskWorkflowIrSync(id);
54636
54642
  const workflowSignature = serializeWorkflowIr(workflowIr);
@@ -54714,7 +54720,7 @@ ${newTask.description}
54714
54720
  const task = currentTask ?? await this.readTaskForMove(id);
54715
54721
  const moveSource = options?.moveSource ?? "engine";
54716
54722
  const mergedSettingsForMove = await this.getSettingsFast();
54717
- const useWorkflow = isWorkflowColumnsEnabled(mergedSettingsForMove);
54723
+ const useWorkflow = isWorkflowColumnsCompatibilityFlagEnabled(mergedSettingsForMove);
54718
54724
  const bypassGuards = this.resolveWorkflowBypassGuards(moveSource, options);
54719
54725
  const workflowIr = useWorkflow ? this.resolveTaskWorkflowIrSync(id) : void 0;
54720
54726
  if (task.column === toColumn) {
@@ -59341,12 +59347,32 @@ ${newTask.description}
59341
59347
  /**
59342
59348
  * FNXC:ArtifactRegistry 2026-06-19-22:04:
59343
59349
  * Cross-agent registry query path for filtering artifacts across tasks, authors, and media types. LEFT JOIN keeps task-less registry artifacts visible while excluding artifacts attached to soft-deleted tasks.
59350
+ *
59351
+ * FNXC:ArtifactRegistry 2026-06-23-12:48:
59352
+ * Agent execution can list artifacts frequently while large generated outputs are stored inline. The registry list is metadata-only, so avoid selecting artifact content here and require callers to use getArtifact for the full payload.
59344
59353
  */
59345
59354
  async listArtifacts(options) {
59346
59355
  const limit = Math.min(Math.max(1, options?.limit ?? 200), 1e3);
59347
59356
  const offset = Math.max(0, options?.offset ?? 0);
59348
59357
  let sql = `
59349
- SELECT a.*, t.title as taskTitle, t.description as taskDescription, t.column as taskColumn
59358
+ SELECT
59359
+ a.id,
59360
+ a.type,
59361
+ a.title,
59362
+ a.description,
59363
+ a.mimeType,
59364
+ a.sizeBytes,
59365
+ a.uri,
59366
+ NULL as content,
59367
+ a.authorId,
59368
+ a.authorType,
59369
+ a.taskId,
59370
+ a.metadata,
59371
+ a.createdAt,
59372
+ a.updatedAt,
59373
+ t.title as taskTitle,
59374
+ t.description as taskDescription,
59375
+ t.column as taskColumn
59350
59376
  FROM artifacts a
59351
59377
  LEFT JOIN tasks t ON a.taskId = t.id
59352
59378
  WHERE (a.taskId IS NULL OR t.${_TaskStore.ACTIVE_TASKS_WHERE})
@@ -61006,9 +61032,9 @@ ${stepsSection}`;
61006
61032
  // always route through `moveTask` with `moveSource: "engine"` + `bypassGuards`
61007
61033
  // (a recovery-class move, KTD-9) — never a raw column write — so capacity
61008
61034
  // (KTD-10) and the single transition authority (KTD-3) are honored.
61009
- /** True when the `workflowColumns` flag is ON (merged global + project). */
61035
+ /** True when the raw `workflowColumns` compatibility flag is ON (merged global + project). */
61010
61036
  async workflowColumnsFlagOn() {
61011
- return isWorkflowColumnsEnabled(await this.getSettingsFast());
61037
+ return isWorkflowColumnsCompatibilityFlagEnabled(await this.getSettingsFast());
61012
61038
  }
61013
61039
  /** The active (non-deleted) task ids currently selecting `workflowId`. A
61014
61040
  * built-in/default workflow additionally owns every task with NO selection
@@ -62970,18 +62996,70 @@ var init_agent_token_usage = __esm({
62970
62996
  function normalize4(s3) {
62971
62997
  return (s3 ?? "").trim().toLowerCase();
62972
62998
  }
62973
- function lookupPricing(ref) {
62999
+ function findBareModelPricing(model, entries) {
63000
+ for (const [key, entry] of Object.entries(entries)) {
63001
+ if (key.endsWith(`:${model}`)) return entry;
63002
+ }
63003
+ return void 0;
63004
+ }
63005
+ function lookupPricing(ref, overrides2) {
62974
63006
  const provider = normalize4(ref.provider);
62975
63007
  const model = normalize4(ref.model);
62976
63008
  if (!model) return void 0;
63009
+ if (provider) {
63010
+ const exactOverride = overrides2?.[`${provider}:${model}`];
63011
+ if (exactOverride) return exactOverride;
63012
+ }
63013
+ const bareOverride = overrides2 ? findBareModelPricing(model, overrides2) : void 0;
63014
+ if (bareOverride) return bareOverride;
62977
63015
  if (provider) {
62978
63016
  const exact = MODEL_PRICING[`${provider}:${model}`];
62979
63017
  if (exact) return exact;
62980
63018
  }
62981
- for (const [key, entry] of Object.entries(MODEL_PRICING)) {
62982
- if (key.endsWith(`:${model}`)) return entry;
62983
- }
62984
- return void 0;
63019
+ return findBareModelPricing(model, MODEL_PRICING);
63020
+ }
63021
+ function litellmProviderToFusionProvider(provider) {
63022
+ if (typeof provider !== "string") return null;
63023
+ const normalized = normalize4(provider);
63024
+ if (normalized === "openai") return "openai";
63025
+ if (normalized === "anthropic") return "anthropic";
63026
+ if (normalized === "gemini" || normalized.startsWith("gemini")) return "google";
63027
+ if (normalized === "vertex_ai" || normalized.startsWith("vertex_ai")) return "google";
63028
+ if (normalized === "vertex_ai-language-models") return "google";
63029
+ return null;
63030
+ }
63031
+ function numericField(entry, key) {
63032
+ const value = entry[key];
63033
+ return typeof value === "number" && Number.isFinite(value) ? value : void 0;
63034
+ }
63035
+ function parseLiteLLMPricing(json) {
63036
+ const overrides2 = {};
63037
+ if (json === null || typeof json !== "object" || Array.isArray(json)) {
63038
+ return { overrides: overrides2, count: 0 };
63039
+ }
63040
+ for (const [modelId, value] of Object.entries(json)) {
63041
+ if (modelId === "sample_spec") continue;
63042
+ if (value === null || typeof value !== "object" || Array.isArray(value)) continue;
63043
+ const entry = value;
63044
+ if (entry.mode !== "chat") continue;
63045
+ const provider = litellmProviderToFusionProvider(entry.litellm_provider);
63046
+ if (!provider) continue;
63047
+ const inputCost = numericField(entry, "input_cost_per_token");
63048
+ const outputCost = numericField(entry, "output_cost_per_token");
63049
+ if (inputCost === void 0 || outputCost === void 0) continue;
63050
+ const inputPer1M = inputCost * 1e6;
63051
+ const outputPer1M = outputCost * 1e6;
63052
+ const cacheRead = numericField(entry, "cache_read_input_token_cost");
63053
+ const cacheWrite = numericField(entry, "cache_creation_input_token_cost");
63054
+ overrides2[`${provider}:${normalize4(modelId)}`] = {
63055
+ inputPer1M,
63056
+ outputPer1M,
63057
+ cacheReadPer1M: cacheRead === void 0 ? inputPer1M : cacheRead * 1e6,
63058
+ cacheWritePer1M: cacheWrite === void 0 ? inputPer1M : cacheWrite * 1e6,
63059
+ source: LITELLM_PRICING_SOURCE_LABEL
63060
+ };
63061
+ }
63062
+ return { overrides: overrides2, count: Object.keys(overrides2).length };
62985
63063
  }
62986
63064
  function isStale(now) {
62987
63065
  if (now === void 0) return false;
@@ -62989,21 +63067,23 @@ function isStale(now) {
62989
63067
  if (Number.isNaN(asOf)) return false;
62990
63068
  return now - asOf > PRICING_STALE_AFTER_MS;
62991
63069
  }
62992
- function costFor(usage, model, now) {
63070
+ function costFor(usage, model, now, overrides2) {
62993
63071
  const stale = isStale(now);
62994
- const pricing = lookupPricing(model);
63072
+ const pricing = lookupPricing(model, overrides2);
62995
63073
  if (!pricing) {
62996
63074
  return { usd: null, unavailable: true, stale };
62997
63075
  }
62998
63076
  const usd = (usage.inputTokens * pricing.inputPer1M + usage.outputTokens * pricing.outputPer1M + usage.cachedTokens * pricing.cacheReadPer1M + usage.cacheWriteTokens * pricing.cacheWritePer1M) / 1e6;
62999
63077
  return { usd, unavailable: false, stale };
63000
63078
  }
63001
- var pricingAsOf, PRICING_STALE_AFTER_MS, MODEL_PRICING;
63079
+ var pricingAsOf, PRICING_STALE_AFTER_MS, LITELLM_PRICING_SOURCE_URL, LITELLM_PRICING_SOURCE_LABEL, MODEL_PRICING;
63002
63080
  var init_model_pricing = __esm({
63003
63081
  "../core/src/model-pricing.ts"() {
63004
63082
  "use strict";
63005
63083
  pricingAsOf = "2026-06-21";
63006
63084
  PRICING_STALE_AFTER_MS = 180 * 24 * 60 * 60 * 1e3;
63085
+ LITELLM_PRICING_SOURCE_URL = "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json";
63086
+ LITELLM_PRICING_SOURCE_LABEL = "litellm/model_prices_and_context_window.json";
63007
63087
  MODEL_PRICING = {
63008
63088
  // ── Anthropic Claude ────────────────────────────────────────────────
63009
63089
  // input / output / cacheRead(0.1×) / cacheWrite(1.25×, 5-min TTL)
@@ -63250,7 +63330,7 @@ function groupKeyFor(row, groupBy) {
63250
63330
  function emptyCostAccumulator() {
63251
63331
  return { usd: 0, anyPriced: false, anyUnavailable: false, anyStale: false };
63252
63332
  }
63253
- function addRowCost(acc, row, now) {
63333
+ function addRowCost(acc, row, now, pricingOverrides) {
63254
63334
  const result = costFor(
63255
63335
  {
63256
63336
  inputTokens: row.inputTokens ?? 0,
@@ -63262,7 +63342,8 @@ function addRowCost(acc, row, now) {
63262
63342
  provider: row.tokenUsageModelProvider ?? row.modelProvider,
63263
63343
  model: row.tokenUsageModelId ?? row.modelId
63264
63344
  },
63265
- now
63345
+ now,
63346
+ pricingOverrides
63266
63347
  );
63267
63348
  if (result.stale) acc.anyStale = true;
63268
63349
  if (result.unavailable || result.usd === null) {
@@ -63371,9 +63452,10 @@ function aggregateTokenAnalytics(db, query = {}) {
63371
63452
  const groupBy = query.groupBy;
63372
63453
  const granularity = query.granularity;
63373
63454
  const now = query.now;
63455
+ const pricingOverrides = query.pricingOverrides;
63374
63456
  for (const row of rows) {
63375
63457
  addRow(totals, row);
63376
- addRowCost(totalCost, row, now);
63458
+ addRowCost(totalCost, row, now, pricingOverrides);
63377
63459
  if (groupBy) {
63378
63460
  const groupRows = groupBy === "model" || groupBy === "provider" ? parsePerModelRows(row) : [];
63379
63461
  const rowsForGroup = groupRows.length > 0 ? groupRows : [row];
@@ -63386,7 +63468,7 @@ function aggregateTokenAnalytics(db, query = {}) {
63386
63468
  groupCostMap.set(key, emptyCostAccumulator());
63387
63469
  }
63388
63470
  addRow(group, groupRow);
63389
- addRowCost(groupCostMap.get(key), groupRow, now);
63471
+ addRowCost(groupCostMap.get(key), groupRow, now, pricingOverrides);
63390
63472
  }
63391
63473
  }
63392
63474
  if (granularity) {
@@ -63398,7 +63480,7 @@ function aggregateTokenAnalytics(db, query = {}) {
63398
63480
  seriesCostMap.set(bucket, emptyCostAccumulator());
63399
63481
  }
63400
63482
  addRow(point, row);
63401
- addRowCost(seriesCostMap.get(bucket), row, now);
63483
+ addRowCost(seriesCostMap.get(bucket), row, now, pricingOverrides);
63402
63484
  }
63403
63485
  }
63404
63486
  for (const [key, group] of groupMap) {
@@ -64049,7 +64131,7 @@ function addTokenRow(totals, row) {
64049
64131
  totals.totalTokens += row.totalTokens ?? (row.inputTokens ?? 0) + (row.outputTokens ?? 0) + (row.cachedTokens ?? 0) + (row.cacheWriteTokens ?? 0);
64050
64132
  totals.nTasks += 1;
64051
64133
  }
64052
- function addRowCost2(acc, row, now) {
64134
+ function addRowCost2(acc, row, now, pricingOverrides) {
64053
64135
  const result = costFor(
64054
64136
  {
64055
64137
  inputTokens: row.inputTokens ?? 0,
@@ -64058,7 +64140,8 @@ function addRowCost2(acc, row, now) {
64058
64140
  cacheWriteTokens: row.cacheWriteTokens ?? 0
64059
64141
  },
64060
64142
  { provider: row.modelProvider, model: row.modelId },
64061
- now
64143
+ now,
64144
+ pricingOverrides
64062
64145
  );
64063
64146
  if (result.stale) acc.anyStale = true;
64064
64147
  if (result.unavailable || result.usd === null) {
@@ -64117,6 +64200,7 @@ function aggregateTeamAnalytics(db, query = {}) {
64117
64200
  const costAccumulators = /* @__PURE__ */ new Map();
64118
64201
  const totalTokens = emptyTokenTotals();
64119
64202
  const totalCost = emptyCostAccumulator2();
64203
+ const pricingOverrides = query.pricingOverrides;
64120
64204
  const agents = db.prepare(`SELECT id, name, role, state FROM agents ORDER BY id`).all();
64121
64205
  for (const agent of agents) {
64122
64206
  summaries.set(agent.id, makeSummary(agent.id, agent));
@@ -64152,8 +64236,8 @@ function aggregateTeamAnalytics(db, query = {}) {
64152
64236
  costAccumulators.set(row.agentId, agentCost);
64153
64237
  addTokenRow(summary.tokens, row);
64154
64238
  addTokenRow(totalTokens, row);
64155
- addRowCost2(agentCost, row, query.now);
64156
- addRowCost2(totalCost, row, query.now);
64239
+ addRowCost2(agentCost, row, query.now, pricingOverrides);
64240
+ addRowCost2(totalCost, row, query.now, pricingOverrides);
64157
64241
  }
64158
64242
  const completedClauses = ["assignedAgentId IS NOT NULL", `"column" = 'done'`, "columnMovedAt IS NOT NULL"];
64159
64243
  const completedParams = [];
@@ -86357,6 +86441,8 @@ __export(src_exports, {
86357
86441
  InvalidMergeQueueLeaseDurationError: () => InvalidMergeQueueLeaseDurationError,
86358
86442
  InvalidRehomeTargetError: () => InvalidRehomeTargetError,
86359
86443
  LEGACY_AGENT_PERMISSION_POLICY_ACTION_CATEGORY_ALIASES: () => LEGACY_AGENT_PERMISSION_POLICY_ACTION_CATEGORY_ALIASES,
86444
+ LITELLM_PRICING_SOURCE_LABEL: () => LITELLM_PRICING_SOURCE_LABEL,
86445
+ LITELLM_PRICING_SOURCE_URL: () => LITELLM_PRICING_SOURCE_URL,
86360
86446
  LinkedWorktreeBootstrapRefusedError: () => LinkedWorktreeBootstrapRefusedError,
86361
86447
  MANUAL_RETRY_RESET_COUNTER_KEYS: () => MANUAL_RETRY_RESET_COUNTER_KEYS,
86362
86448
  MASTER_KEY_FILENAME: () => MASTER_KEY_FILENAME,
@@ -86897,6 +86983,7 @@ __export(src_exports, {
86897
86983
  parseInsightExtractionResponse: () => parseInsightExtractionResponse,
86898
86984
  parseInstanceNodeId: () => parseInstanceNodeId,
86899
86985
  parseJsonSteps: () => parseJsonSteps,
86986
+ parseLiteLLMPricing: () => parseLiteLLMPricing,
86900
86987
  parseNoOpCompletionMarker: () => parseNoOpCompletionMarker,
86901
86988
  parseProjectManifest: () => parseProjectManifest,
86902
86989
  parseRepoFromRemote: () => parseRepoFromRemote,
@@ -87398,6 +87485,74 @@ var init_logger2 = __esm({
87398
87485
  });
87399
87486
 
87400
87487
  // ../engine/src/agent-logger.ts
87488
+ function truncateToolResultDetail(value) {
87489
+ if (value.length <= TOOL_RESULT_DETAIL_LIMIT) return value;
87490
+ return `${value.slice(0, TOOL_RESULT_DETAIL_LIMIT)}${TOOL_RESULT_DETAIL_TRUNCATION_NOTICE}`;
87491
+ }
87492
+ function summarizeToolResultValue(value, state) {
87493
+ if (state.remainingChars <= 0) return "[truncated]";
87494
+ if (value === null || value === void 0) return value;
87495
+ if (typeof value === "string") {
87496
+ const truncated = value.length > state.remainingChars ? `${value.slice(0, state.remainingChars)}${TOOL_RESULT_DETAIL_TRUNCATION_NOTICE}` : value;
87497
+ state.remainingChars -= Math.min(value.length, state.remainingChars);
87498
+ return truncated;
87499
+ }
87500
+ if (typeof value === "number" || typeof value === "boolean") return value;
87501
+ if (typeof value === "bigint") return value.toString();
87502
+ if (typeof value === "function" || typeof value === "symbol") return `[${typeof value}]`;
87503
+ if (value instanceof Error) {
87504
+ return {
87505
+ name: value.name,
87506
+ message: summarizeToolResultValue(value.message, state),
87507
+ ...value.stack ? { stack: summarizeToolResultValue(value.stack, state) } : {}
87508
+ };
87509
+ }
87510
+ if (typeof Buffer !== "undefined" && Buffer.isBuffer(value)) {
87511
+ return `<Buffer ${value.byteLength} bytes>`;
87512
+ }
87513
+ if (ArrayBuffer.isView(value)) {
87514
+ return `<${value.constructor.name} ${value.byteLength} bytes>`;
87515
+ }
87516
+ if (value instanceof ArrayBuffer) {
87517
+ return `<ArrayBuffer ${value.byteLength} bytes>`;
87518
+ }
87519
+ if (typeof value !== "object") return String(value);
87520
+ if (state.seen.has(value)) return "[Circular]";
87521
+ state.seen.add(value);
87522
+ if (Array.isArray(value)) {
87523
+ const summarized2 = value.slice(0, TOOL_RESULT_MAX_ARRAY_ITEMS).map((item) => summarizeToolResultValue(item, state));
87524
+ if (value.length > TOOL_RESULT_MAX_ARRAY_ITEMS) summarized2.push(`[${value.length - TOOL_RESULT_MAX_ARRAY_ITEMS} more items truncated]`);
87525
+ return summarized2;
87526
+ }
87527
+ const summarized = {};
87528
+ let count2 = 0;
87529
+ for (const key of Object.keys(value)) {
87530
+ if (count2 >= TOOL_RESULT_MAX_OBJECT_KEYS) {
87531
+ summarized.__truncatedKeys = true;
87532
+ break;
87533
+ }
87534
+ summarized[key] = summarizeToolResultValue(value[key], state);
87535
+ count2 += 1;
87536
+ if (state.remainingChars <= 0) {
87537
+ summarized.__truncated = true;
87538
+ break;
87539
+ }
87540
+ }
87541
+ return summarized;
87542
+ }
87543
+ function summarizeToolResultDetail(result) {
87544
+ if (result === void 0 || result === null) return void 0;
87545
+ if (typeof result === "string") return truncateToolResultDetail(result);
87546
+ try {
87547
+ const preview = summarizeToolResultValue(result, {
87548
+ remainingChars: TOOL_RESULT_DETAIL_LIMIT,
87549
+ seen: /* @__PURE__ */ new WeakSet()
87550
+ });
87551
+ return truncateToolResultDetail(JSON.stringify(preview));
87552
+ } catch {
87553
+ return truncateToolResultDetail(String(result));
87554
+ }
87555
+ }
87401
87556
  function summarizeToolArgs(name, args) {
87402
87557
  if (!args) return void 0;
87403
87558
  const lowerName = name.toLowerCase();
@@ -87414,7 +87569,7 @@ function summarizeToolArgs(name, args) {
87414
87569
  }
87415
87570
  return void 0;
87416
87571
  }
87417
- var FLUSH_SIZE_BYTES, FLUSH_INTERVAL_MS, ENTRY_BATCH_SIZE, AgentLogger;
87572
+ var FLUSH_SIZE_BYTES, FLUSH_INTERVAL_MS, ENTRY_BATCH_SIZE, TOOL_RESULT_DETAIL_LIMIT, TOOL_RESULT_DETAIL_TRUNCATION_NOTICE, TOOL_RESULT_MAX_ARRAY_ITEMS, TOOL_RESULT_MAX_OBJECT_KEYS, AgentLogger;
87418
87573
  var init_agent_logger = __esm({
87419
87574
  "../engine/src/agent-logger.ts"() {
87420
87575
  "use strict";
@@ -87423,6 +87578,10 @@ var init_agent_logger = __esm({
87423
87578
  FLUSH_SIZE_BYTES = 1024;
87424
87579
  FLUSH_INTERVAL_MS = 500;
87425
87580
  ENTRY_BATCH_SIZE = 50;
87581
+ TOOL_RESULT_DETAIL_LIMIT = 4096;
87582
+ TOOL_RESULT_DETAIL_TRUNCATION_NOTICE = "\n\n[tool output truncated to keep dashboard log views responsive]";
87583
+ TOOL_RESULT_MAX_ARRAY_ITEMS = 25;
87584
+ TOOL_RESULT_MAX_OBJECT_KEYS = 50;
87426
87585
  AgentLogger = class {
87427
87586
  textBuffer = "";
87428
87587
  thinkingBuffer = "";
@@ -87568,10 +87727,7 @@ var init_agent_logger = __esm({
87568
87727
  */
87569
87728
  onToolEnd(name, isError, result) {
87570
87729
  const type = isError ? "tool_error" : "tool_result";
87571
- let detail;
87572
- if (result !== void 0 && result !== null) {
87573
- detail = typeof result === "string" ? result : JSON.stringify(result);
87574
- }
87730
+ const detail = summarizeToolResultDetail(result);
87575
87731
  this.writeEntry(name, type, detail, `Failed to log tool end "${name}" (${type}) for ${this.taskId}`);
87576
87732
  const startedAt = this.toolStartedAt.get(name);
87577
87733
  if (startedAt !== void 0) this.toolStartedAt.delete(name);
@@ -88618,7 +88774,6 @@ function countCapacitySlot(allTasks, effectiveWorkflowIdByTask, targetColumn, wo
88618
88774
  async function runHoldReleaseSweep(store, deps) {
88619
88775
  const result = { released: [], held: [] };
88620
88776
  const settings = await store.getSettings();
88621
- if (!isWorkflowColumnsEnabled(settings)) return result;
88622
88777
  const allTasks = await store.listTasks({ includeArchived: false });
88623
88778
  const irCache = /* @__PURE__ */ new Map();
88624
88779
  const effectiveWorkflowIdByTask = /* @__PURE__ */ new Map();
@@ -107616,10 +107771,83 @@ var init_unlinked_missions_advisory_reporter = __esm({
107616
107771
  }
107617
107772
  });
107618
107773
 
107774
+ // ../engine/src/task-agent-sync.ts
107775
+ function hasFreshActiveHeartbeatRun(activeRun, now = Date.now(), freshRunMs = PARKED_AGENT_LINK_FRESH_RUN_MS) {
107776
+ const runStartedAt = activeRun?.startedAt;
107777
+ const runAgeMs = runStartedAt ? now - Date.parse(runStartedAt) : Number.POSITIVE_INFINITY;
107778
+ return {
107779
+ hasFreshRun: Boolean(activeRun) && Number.isFinite(runAgeMs) && runAgeMs <= freshRunMs,
107780
+ runAgeMs
107781
+ };
107782
+ }
107783
+ function isParkedTaskColumn(task) {
107784
+ return task?.column === "todo" || task?.column === "triage";
107785
+ }
107786
+ function evaluateParkedAgentTaskLink(options) {
107787
+ const { hasFreshRun, runAgeMs } = hasFreshActiveHeartbeatRun(options.activeRun, options.now);
107788
+ const hasActiveExecution = options.hasActiveAgentExecution?.(options.agent.id) === true;
107789
+ return {
107790
+ hasFreshRun,
107791
+ hasActiveExecution,
107792
+ shouldPreserveParkedLink: isParkedTaskColumn(options.linkedTask) && (hasFreshRun || hasActiveExecution),
107793
+ runAgeMs
107794
+ };
107795
+ }
107796
+ function attachAgentLinkSync(opts) {
107797
+ const logger3 = opts.logger ?? console;
107798
+ const handler = async ({ task, from, to: to2 }) => {
107799
+ if (!CLEAR_COLUMNS.has(to2)) {
107800
+ return;
107801
+ }
107802
+ try {
107803
+ const agents = await opts.agentStore.listAgents({ includeEphemeral: false });
107804
+ const linkedAgents = agents.filter((agent) => agent.taskId === task.id);
107805
+ for (const agent of linkedAgents) {
107806
+ if (to2 === "todo" || to2 === "triage") {
107807
+ const activeRun = await opts.agentStore.getActiveHeartbeatRun?.(agent.id);
107808
+ const proof = evaluateParkedAgentTaskLink({
107809
+ agent,
107810
+ linkedTask: { column: to2 },
107811
+ activeRun,
107812
+ hasActiveAgentExecution: opts.hasActiveAgentExecution
107813
+ });
107814
+ if (proof.shouldPreserveParkedLink) {
107815
+ continue;
107816
+ }
107817
+ }
107818
+ if (agent.state === "running") {
107819
+ await opts.agentStore.updateAgentState(agent.id, "active");
107820
+ }
107821
+ await opts.agentStore.syncExecutionTaskLink(agent.id, void 0);
107822
+ logger3.log(`taskAgentLinkSync: cleared agent ${agent.id} taskId from ${task.id} after move ${from} \u2192 ${to2}`);
107823
+ }
107824
+ } catch (error) {
107825
+ logger3.warn(
107826
+ `taskAgentLinkSync: failed to sync agents for task ${task.id} after move ${from} \u2192 ${to2}: ${error instanceof Error ? error.message : String(error)}`
107827
+ );
107828
+ }
107829
+ };
107830
+ opts.store.on("task:moved", handler);
107831
+ return () => {
107832
+ opts.store.off("task:moved", handler);
107833
+ };
107834
+ }
107835
+ var PARKED_AGENT_LINK_FRESH_RUN_MS, CLEAR_COLUMNS;
107836
+ var init_task_agent_sync = __esm({
107837
+ "../engine/src/task-agent-sync.ts"() {
107838
+ "use strict";
107839
+ PARKED_AGENT_LINK_FRESH_RUN_MS = 5 * 6e4;
107840
+ CLEAR_COLUMNS = /* @__PURE__ */ new Set(["done", "archived", "todo", "triage"]);
107841
+ }
107842
+ });
107843
+
107619
107844
  // ../engine/src/scheduler.ts
107620
107845
  import { existsSync as existsSync37 } from "node:fs";
107621
107846
  import { readFile as readFile20 } from "node:fs/promises";
107622
107847
  import { join as join42 } from "node:path";
107848
+ function shouldRunWorkflowColumnScheduler(_settings) {
107849
+ return true;
107850
+ }
107623
107851
  function pathsOverlap2(a, b2) {
107624
107852
  for (const pa of a) {
107625
107853
  const prefixA = pa.endsWith("/*") ? pa.slice(0, -1) : null;
@@ -107860,6 +108088,7 @@ var init_scheduler = __esm({
107860
108088
  init_run_audit();
107861
108089
  init_src();
107862
108090
  init_hold_release();
108091
+ init_task_agent_sync();
107863
108092
  COORDINATION_SAFE_SCOPE_EXACT = /* @__PURE__ */ new Set([
107864
108093
  // Literal glob scope entries from PROMPT.md are kept here; concrete
107865
108094
  // `.changeset/<name>.md` files are covered by COORDINATION_SAFE_SCOPE_PREFIXES.
@@ -108306,12 +108535,27 @@ var init_scheduler = __esm({
108306
108535
  async rollbackRunningAgentsForQueuedTodoTask(taskId) {
108307
108536
  const agentStore = this.options.agentStore;
108308
108537
  if (!agentStore) return;
108309
- const runningAgents = await agentStore.listAgents({ state: "running", includeEphemeral: true });
108538
+ const runningAgents = await agentStore.listAgents({ state: "running", includeEphemeral: false });
108310
108539
  const linkedAgents = runningAgents.filter((agent) => agent.taskId === taskId);
108311
108540
  for (const agent of linkedAgents) {
108541
+ const activeRun = await agentStore.getActiveHeartbeatRun?.(agent.id);
108542
+ const proof = evaluateParkedAgentTaskLink({
108543
+ agent,
108544
+ linkedTask: { column: "todo" },
108545
+ activeRun,
108546
+ hasActiveAgentExecution: this.options.hasActiveAgentExecution
108547
+ });
108548
+ if (proof.shouldPreserveParkedLink) {
108549
+ schedulerLog.log(
108550
+ `Preserved running agent ${agent.id} for queued ${taskId}; live proof freshRun=${proof.hasFreshRun} activeExecution=${proof.hasActiveExecution}`
108551
+ );
108552
+ continue;
108553
+ }
108312
108554
  await agentStore.updateAgentState(agent.id, "active");
108313
108555
  await agentStore.syncExecutionTaskLink(agent.id, void 0);
108314
- schedulerLog.log(`Rolled back running agent ${agent.id} after overlap requeue of ${taskId}`);
108556
+ schedulerLog.log(
108557
+ `Cleared stale running agent ${agent.id} after overlap requeue of ${taskId}; file-scope lease remains queued`
108558
+ );
108315
108559
  }
108316
108560
  }
108317
108561
  /**
@@ -108431,7 +108675,7 @@ var init_scheduler = __esm({
108431
108675
  schedulerLog.log("Engine pause cleared \u2014 scheduling resumed");
108432
108676
  }
108433
108677
  this.wasEnginePaused = false;
108434
- if (isWorkflowColumnsEnabled(settings)) {
108678
+ if (shouldRunWorkflowColumnScheduler(settings)) {
108435
108679
  await this.runHoldReleaseSweepPass(tasks, settings);
108436
108680
  tasks = await this.store.listTasks({ slim: true, includeArchived: false, startupMemo: false });
108437
108681
  settings = await this.store.getSettings();
@@ -109457,6 +109701,7 @@ var init_scheduler = __esm({
109457
109701
  blockedBy: null,
109458
109702
  overlapBlockedBy: overlappingTaskId
109459
109703
  });
109704
+ await this.rollbackRunningAgentsForQueuedTodoTask(task.id);
109460
109705
  await this.logDispatchQueuedReason(
109461
109706
  task.id,
109462
109707
  `queued \u2014 blocked by active file-scope lease ${overlappingTaskId} (column=${activeLeaseColumn})`
@@ -124385,6 +124630,7 @@ var init_self_healing = __esm({
124385
124630
  init_notifier();
124386
124631
  init_dependency_blocked_todo_reporter();
124387
124632
  init_scheduler();
124633
+ init_task_agent_sync();
124388
124634
  init_transient_merge_error_classifier();
124389
124635
  init_transient_merge_error_classifier();
124390
124636
  log22 = createLogger2("self-healing");
@@ -124451,7 +124697,7 @@ var init_self_healing = __esm({
124451
124697
  DURABLE_ERROR_RECOVERY_MAX_RETRIES = 5;
124452
124698
  DURABLE_ERROR_RECOVERY_BASE_COOLDOWN_MS = 3e4;
124453
124699
  DURABLE_ERROR_RECOVERY_MAX_COOLDOWN_MS = 15 * 6e4;
124454
- RUNNING_ON_INACTIVE_TASK_STALE_RUN_MS = 5 * 6e4;
124700
+ RUNNING_ON_INACTIVE_TASK_STALE_RUN_MS = PARKED_AGENT_LINK_FRESH_RUN_MS;
124455
124701
  SelfHealingManager = class _SelfHealingManager {
124456
124702
  constructor(store, options) {
124457
124703
  this.store = store;
@@ -131279,6 +131525,36 @@ var init_self_healing = __esm({
131279
131525
  const exponential = DURABLE_ERROR_RECOVERY_BASE_COOLDOWN_MS * Math.pow(2, clampedAttempts - 1);
131280
131526
  return Math.min(exponential, DURABLE_ERROR_RECOVERY_MAX_COOLDOWN_MS);
131281
131527
  }
131528
+ async emitStaleAgentAssignmentAudit(options) {
131529
+ try {
131530
+ await createRunAuditor(this.store, {
131531
+ runId: generateSyntheticRunId("self-healing-stale-agent-assignment", options.taskId),
131532
+ agentId: "self-healing",
131533
+ taskId: options.taskId,
131534
+ taskLineageId: options.linkedTask?.lineageId,
131535
+ phase: "reconcile-stale-agent-assignment"
131536
+ }).database({
131537
+ type: "task:reconcile-stale-agent-assignment",
131538
+ target: options.agent.id,
131539
+ metadata: {
131540
+ agentId: options.agent.id,
131541
+ taskId: options.taskId,
131542
+ taskColumn: options.linkedTask?.column ?? null,
131543
+ agentState: options.agent.state,
131544
+ status: options.linkedTask?.status ?? null,
131545
+ blockedBy: options.linkedTask?.blockedBy ?? null,
131546
+ overlapBlockedBy: options.linkedTask?.overlapBlockedBy ?? null,
131547
+ hadFreshRun: options.hadFreshRun,
131548
+ hadActiveExecution: options.hadActiveExecution,
131549
+ reason: options.reason
131550
+ }
131551
+ });
131552
+ } catch (error) {
131553
+ log22.warn(
131554
+ `Failed to emit stale agent assignment audit for ${options.agent.id}/${options.taskId}: ${error instanceof Error ? error.message : String(error)}`
131555
+ );
131556
+ }
131557
+ }
131282
131558
  async recoverAgentsRunningOnInactiveTasks() {
131283
131559
  const agentStore = this.options.agentStore;
131284
131560
  if (!agentStore) {
@@ -131296,16 +131572,30 @@ var init_self_healing = __esm({
131296
131572
  continue;
131297
131573
  }
131298
131574
  const activeRun = await agentStore.getActiveHeartbeatRun(agent.id);
131299
- const runStartedAt = activeRun?.startedAt;
131300
- const runAgeMs = runStartedAt ? now - Date.parse(runStartedAt) : Number.POSITIVE_INFINITY;
131301
- const hasFreshRun = Boolean(activeRun) && Number.isFinite(runAgeMs) && runAgeMs <= RUNNING_ON_INACTIVE_TASK_STALE_RUN_MS;
131302
- if (hasFreshRun || this.options.hasActiveAgentExecution?.(agent.id) === true) {
131575
+ const proof = evaluateParkedAgentTaskLink({
131576
+ agent,
131577
+ linkedTask: linkedTask ?? { column: "todo" },
131578
+ activeRun,
131579
+ hasActiveAgentExecution: this.options.hasActiveAgentExecution,
131580
+ now
131581
+ });
131582
+ if (proof.hasFreshRun || proof.hasActiveExecution) {
131303
131583
  continue;
131304
131584
  }
131585
+ const reason = linkedTask ? `running durable agent linked to inactive ${linkedTask.column} task without live execution proof` : "running durable agent linked to missing task without live execution proof";
131586
+ const staleAgentState = agent.state;
131305
131587
  await agentStore.updateAgentState(agent.id, "active");
131306
131588
  await agentStore.syncExecutionTaskLink(agent.id, void 0);
131589
+ await this.emitStaleAgentAssignmentAudit({
131590
+ agent: { id: agent.id, state: staleAgentState },
131591
+ taskId: agent.taskId,
131592
+ linkedTask,
131593
+ hadFreshRun: proof.hasFreshRun,
131594
+ hadActiveExecution: proof.hasActiveExecution,
131595
+ reason
131596
+ });
131307
131597
  recoveredAgentIds.add(agent.id);
131308
- log22.log(`Recovered running durable agent ${agent.id} on inactive task ${agent.taskId}`);
131598
+ log22.log(`Recovered running durable agent ${agent.id} on inactive task ${agent.taskId}; file-scope lease preserved when present`);
131309
131599
  }
131310
131600
  return recoveredAgentIds.size;
131311
131601
  }
@@ -131325,6 +131615,8 @@ var init_self_healing = __esm({
131325
131615
  const linkedTask = await this.store.getTask(linkedTaskId);
131326
131616
  let shouldClear = false;
131327
131617
  let reason = "";
131618
+ let hadFreshRun = false;
131619
+ let hadActiveExecution = false;
131328
131620
  if (!linkedTask) {
131329
131621
  shouldClear = true;
131330
131622
  reason = "linked task missing";
@@ -131336,21 +131628,38 @@ var init_self_healing = __esm({
131336
131628
  reason = `linked task assigned to ${linkedTask.assignedAgentId}`;
131337
131629
  } else if (linkedTask.column === "todo" || linkedTask.column === "triage") {
131338
131630
  const activeRun = await agentStore.getActiveHeartbeatRun(agent.id);
131339
- const runStartedAt = activeRun?.startedAt;
131340
- const runAgeMs = runStartedAt ? now - Date.parse(runStartedAt) : Number.POSITIVE_INFINITY;
131341
- const hasFreshRun = Boolean(activeRun) && Number.isFinite(runAgeMs) && runAgeMs <= RUNNING_ON_INACTIVE_TASK_STALE_RUN_MS;
131342
- const hasActiveExecution = this.options.hasActiveAgentExecution?.(agent.id) === true;
131343
- if (!hasFreshRun && !hasActiveExecution) {
131631
+ const proof = evaluateParkedAgentTaskLink({
131632
+ agent,
131633
+ linkedTask,
131634
+ activeRun,
131635
+ hasActiveAgentExecution: this.options.hasActiveAgentExecution,
131636
+ now
131637
+ });
131638
+ hadFreshRun = proof.hasFreshRun;
131639
+ hadActiveExecution = proof.hasActiveExecution;
131640
+ if (!proof.shouldPreserveParkedLink) {
131344
131641
  shouldClear = true;
131345
- reason = `linked task in queued column ${linkedTask.column} without fresh run`;
131642
+ reason = `linked task in queued column ${linkedTask.column} without fresh run or active execution`;
131346
131643
  }
131347
131644
  }
131348
131645
  if (!shouldClear) {
131349
131646
  continue;
131350
131647
  }
131648
+ const staleAgentState = agent.state;
131649
+ if (agent.state === "running") {
131650
+ await agentStore.updateAgentState(agent.id, "active");
131651
+ }
131351
131652
  await agentStore.syncExecutionTaskLink(agent.id, void 0);
131653
+ await this.emitStaleAgentAssignmentAudit({
131654
+ agent: { id: agent.id, state: staleAgentState },
131655
+ taskId: linkedTaskId,
131656
+ linkedTask,
131657
+ hadFreshRun,
131658
+ hadActiveExecution,
131659
+ reason
131660
+ });
131352
131661
  clearedAgentIds.add(agent.id);
131353
- log22.log(`Cleared drifted durable agent task link for ${agent.id} (${linkedTaskId}): ${reason}`);
131662
+ log22.log(`Cleared drifted durable agent task link for ${agent.id} (${linkedTaskId}): ${reason}; file-scope lease preserved when present`);
131354
131663
  }
131355
131664
  log22.log(`Recovered ${clearedAgentIds.size} drifted durable agent task link(s)`);
131356
131665
  return clearedAgentIds.size;
@@ -134505,6 +134814,10 @@ Remove or replace these ids and call fn_task_create again.`
134505
134814
  // Project-level validator fallback
134506
134815
  projectValidatorFallbackProvider: currentSettings.validatorFallbackProvider,
134507
134816
  projectValidatorFallbackModelId: currentSettings.validatorFallbackModelId,
134817
+ // FNXC:SpecReviewerFallback 2026-06-23-08:50:
134818
+ // Spec review must inherit global/default fallback reviewer model settings when no validator-specific fallback is configured, plus the project settings/prompt payload that reviewer sessions use for memory and custom prompt behavior.
134819
+ fallbackProvider: currentSettings.fallbackProvider,
134820
+ fallbackModelId: currentSettings.fallbackModelId,
134508
134821
  // Global validator lane
134509
134822
  globalValidatorProvider: currentSettings.validatorGlobalProvider,
134510
134823
  globalValidatorModelId: currentSettings.validatorGlobalModelId,
@@ -134516,8 +134829,10 @@ Remove or replace these ids and call fn_task_create again.`
134516
134829
  taskId,
134517
134830
  task: currentDetail,
134518
134831
  userComments: currentUserComments.length > 0 ? currentUserComments : void 0,
134832
+ agentPrompts: currentSettings.agentPrompts,
134519
134833
  agentStore: this.options.agentStore,
134520
134834
  rootDir,
134835
+ settings: currentSettings,
134521
134836
  // Track the spec reviewer's session under this task so it's
134522
134837
  // disposed alongside the main triage session on global pause.
134523
134838
  onSessionCreated: (s3) => this.registerSubagentSession(taskId, s3),
@@ -152927,7 +153242,14 @@ Review the work done in this worktree and evaluate it against the criteria in yo
152927
153242
  const errorMessage = err instanceof Error ? err.message : String(err);
152928
153243
  executorLog.warn(`Child agent ${agentId} failed: ${errorMessage}`);
152929
153244
  } finally {
152930
- this.childSessions.delete(agentId);
153245
+ if (this.childSessions.get(agentId) === childSession) {
153246
+ try {
153247
+ await childSession.dispose();
153248
+ } catch (disposeErr) {
153249
+ executorLog.warn(`Child agent ${agentId} session dispose failed: ${disposeErr instanceof Error ? disposeErr.message : String(disposeErr)}`);
153250
+ }
153251
+ this.childSessions.delete(agentId);
153252
+ }
152931
153253
  this.totalSpawnedCount = Math.max(0, this.totalSpawnedCount - 1);
152932
153254
  }
152933
153255
  }
@@ -157616,6 +157938,7 @@ var init_agent_heartbeat = __esm({
157616
157938
  init_heartbeat_prompt_trim();
157617
157939
  init_room_ambiguity();
157618
157940
  init_room_coordination();
157941
+ init_task_agent_sync();
157619
157942
  promptSizeLog = createLogger2("prompt-size");
157620
157943
  REPORTS_STALE_INTERVAL_MULTIPLIER = 1.5;
157621
157944
  MIN_HEARTBEAT_STALENESS_MS = 10 * 6e4;
@@ -158322,6 +158645,37 @@ Critical: a heartbeat without observable progress (or an explicit no-op reason)
158322
158645
  void this.checkMissedHeartbeats();
158323
158646
  }, this.pollIntervalMs);
158324
158647
  }
158648
+ async emitStaleAgentAssignmentAudit(options) {
158649
+ if (!this.taskStore) return;
158650
+ try {
158651
+ await createRunAuditor(this.taskStore, {
158652
+ runId: generateSyntheticRunId("heartbeat-stale-agent-assignment", options.taskId),
158653
+ agentId: "heartbeat-monitor",
158654
+ taskId: options.taskId,
158655
+ taskLineageId: options.linkedTask?.lineageId,
158656
+ phase: "reconcile-stale-agent-assignment"
158657
+ }).database({
158658
+ type: "task:reconcile-stale-agent-assignment",
158659
+ target: options.agent.id,
158660
+ metadata: {
158661
+ agentId: options.agent.id,
158662
+ taskId: options.taskId,
158663
+ taskColumn: options.linkedTask?.column ?? null,
158664
+ agentState: options.agent.state,
158665
+ status: options.linkedTask?.status ?? null,
158666
+ blockedBy: options.linkedTask?.blockedBy ?? null,
158667
+ overlapBlockedBy: options.linkedTask?.overlapBlockedBy ?? null,
158668
+ hadFreshRun: options.hadFreshRun,
158669
+ hadActiveExecution: options.hadActiveExecution,
158670
+ reason: options.reason
158671
+ }
158672
+ });
158673
+ } catch (error) {
158674
+ heartbeatLog.warn(
158675
+ `Failed to emit stale agent assignment audit for ${options.agent.id}/${options.taskId}: ${error instanceof Error ? error.message : String(error)}`
158676
+ );
158677
+ }
158678
+ }
158325
158679
  /**
158326
158680
  * Find agents in `state="running"` that are not actually running and flip
158327
158681
  * them to `"active"`. An agent is considered orphaned when either:
@@ -158339,8 +158693,8 @@ Critical: a heartbeat without observable progress (or an explicit no-op reason)
158339
158693
  * logged but do not block the caller.
158340
158694
  *
158341
158695
  * Complements SelfHealingManager.recoverAgentsRunningOnInactiveTasks():
158342
- * heartbeat reconciliation handles stale/no-run conditions, while self-healing
158343
- * handles task-column mismatches (for example running agents linked to todo tasks).
158696
+ * heartbeat reconciliation handles stale/no-run conditions and the prompt-critical
158697
+ * parked todo/triage assignment drift before Reports Health Check renders.
158344
158698
  */
158345
158699
  async reconcileOrphanedRunningAgents() {
158346
158700
  try {
@@ -158348,10 +158702,29 @@ Critical: a heartbeat without observable progress (or an explicit no-op reason)
158348
158702
  const now = Date.now();
158349
158703
  for (const agent of runningAgents) {
158350
158704
  let reason = null;
158705
+ let clearTaskLink = false;
158706
+ let taskIdToClear = null;
158707
+ let parkedProof = null;
158708
+ let linkedTask = null;
158351
158709
  const activeRun = await this.store.getActiveHeartbeatRun(agent.id);
158352
- if (!activeRun) {
158710
+ if (!isEphemeralAgent(agent) && agent.taskId && this.taskStore) {
158711
+ linkedTask = await this.taskStore.getTask(agent.taskId);
158712
+ parkedProof = evaluateParkedAgentTaskLink({
158713
+ agent,
158714
+ linkedTask,
158715
+ activeRun,
158716
+ hasActiveAgentExecution: (agentId) => this.trackedAgents.has(agentId),
158717
+ now
158718
+ });
158719
+ if (isParkedTaskColumn(linkedTask) && !parkedProof.shouldPreserveParkedLink) {
158720
+ reason = `parked ${linkedTask.column} task ${agent.taskId} without live execution proof`;
158721
+ clearTaskLink = true;
158722
+ taskIdToClear = agent.taskId;
158723
+ }
158724
+ }
158725
+ if (!reason && !activeRun) {
158353
158726
  reason = "no active run";
158354
- } else if (!this.trackedAgents.has(agent.id)) {
158727
+ } else if (!reason && activeRun && !this.trackedAgents.has(agent.id)) {
158355
158728
  const timeoutMs = this.resolveAgentConfig(agent.id).heartbeatTimeoutMs;
158356
158729
  const heartbeatAgeMs = getHeartbeatAgeMs(agent, now);
158357
158730
  if (!Number.isFinite(heartbeatAgeMs) || heartbeatAgeMs > timeoutMs * 3) {
@@ -158370,9 +158743,21 @@ Critical: a heartbeat without observable progress (or an explicit no-op reason)
158370
158743
  }
158371
158744
  if (!reason) continue;
158372
158745
  try {
158746
+ const staleAgentState = agent.state;
158373
158747
  await this.store.updateAgentState(agent.id, "active");
158748
+ if (clearTaskLink) {
158749
+ await this.store.syncExecutionTaskLink(agent.id, void 0);
158750
+ await this.emitStaleAgentAssignmentAudit({
158751
+ agent: { id: agent.id, state: staleAgentState },
158752
+ taskId: taskIdToClear,
158753
+ linkedTask,
158754
+ hadFreshRun: parkedProof?.hasFreshRun ?? false,
158755
+ hadActiveExecution: parkedProof?.hasActiveExecution ?? false,
158756
+ reason
158757
+ });
158758
+ }
158374
158759
  this.clearRunState(agent.id);
158375
- heartbeatLog.log(`Reconciled orphaned running agent ${agent.id} \u2192 active (${reason})`);
158760
+ heartbeatLog.log(`Reconciled orphaned running agent ${agent.id} \u2192 active (${reason})${clearTaskLink ? "; stale task link cleared" : ""}`);
158376
158761
  } catch (err) {
158377
158762
  heartbeatLog.warn(`Failed to reconcile orphaned running agent ${agent.id}: ${err instanceof Error ? err.message : String(err)}`);
158378
158763
  }
@@ -159925,8 +160310,35 @@ ${trimPromptMd(taskDetail.prompt, promptTemplate)}` : "No PROMPT.md available.",
159925
160310
  );
159926
160311
  const lastHeartbeatTs = report.lastHeartbeatAt ? Date.parse(report.lastHeartbeatAt) : NaN;
159927
160312
  const heartbeatAgeMs = Number.isFinite(lastHeartbeatTs) ? Math.max(0, now - lastHeartbeatTs) : Infinity;
160313
+ let renderedState = report.state;
160314
+ let renderedTask = report.taskId ?? "\u2014";
160315
+ let staleParkedAssignment = false;
160316
+ if (report.state === "running" && !isEphemeralAgent(report) && report.taskId && this.taskStore) {
160317
+ try {
160318
+ const linkedTask = await this.taskStore.getTask(report.taskId);
160319
+ if (isParkedTaskColumn(linkedTask)) {
160320
+ const activeRun = await agentStore.getActiveHeartbeatRun(report.id);
160321
+ const proof = evaluateParkedAgentTaskLink({
160322
+ agent: report,
160323
+ linkedTask,
160324
+ activeRun,
160325
+ hasActiveAgentExecution: (candidateId) => this.trackedAgents.has(candidateId),
160326
+ now
160327
+ });
160328
+ if (!proof.shouldPreserveParkedLink) {
160329
+ staleParkedAssignment = true;
160330
+ renderedState = "active";
160331
+ renderedTask = `${report.taskId} (queued/no live run)`;
160332
+ }
160333
+ }
160334
+ } catch (error) {
160335
+ heartbeatLog.warn(`[reports-health] failed to validate task link for ${report.id}/${report.taskId}: ${error instanceof Error ? error.message : String(error)}`);
160336
+ }
160337
+ }
159928
160338
  let health = "healthy";
159929
- if (report.state === "paused") {
160339
+ if (staleParkedAssignment) {
160340
+ health = "**stale** assignment";
160341
+ } else if (report.state === "paused") {
159930
160342
  health = report.pauseReason ? `paused (${report.pauseReason})` : "paused";
159931
160343
  } else if (report.state === "error") {
159932
160344
  health = "**stuck**";
@@ -159936,8 +160348,8 @@ ${trimPromptMd(taskDetail.prompt, promptTemplate)}` : "No PROMPT.md available.",
159936
160348
  health = "**stale**";
159937
160349
  heartbeatLog.log(`[reports-health] stale report ${report.id} intervalSource=${intervalSource} staleThresholdMs=${staleThresholdMs} heartbeatAgeMs=${heartbeatAgeMs}`);
159938
160350
  }
159939
- const task = report.taskId ?? "\u2014";
159940
- const state = report.state;
160351
+ const task = renderedTask;
160352
+ const state = renderedState;
159941
160353
  const heartbeat = formatRelativeTime(report.lastHeartbeatAt);
159942
160354
  return `| ${report.name} | ${state} | ${task} | ${heartbeat} | ${health} |`;
159943
160355
  }));
@@ -168018,42 +168430,6 @@ var init_node_dispatch_validation = __esm({
168018
168430
  }
168019
168431
  });
168020
168432
 
168021
- // ../engine/src/task-agent-sync.ts
168022
- function attachAgentLinkSync(opts) {
168023
- const logger3 = opts.logger ?? console;
168024
- const handler = async ({ task, from, to: to2 }) => {
168025
- if (!CLEAR_COLUMNS.has(to2)) {
168026
- return;
168027
- }
168028
- try {
168029
- const agents = await opts.agentStore.listAgents({ includeEphemeral: false });
168030
- const linkedAgents = agents.filter((agent) => agent.taskId === task.id);
168031
- for (const agent of linkedAgents) {
168032
- if ((to2 === "todo" || to2 === "triage") && opts.hasActiveAgentExecution?.(agent.id) === true) {
168033
- continue;
168034
- }
168035
- await opts.agentStore.syncExecutionTaskLink(agent.id, void 0);
168036
- logger3.log(`taskAgentLinkSync: cleared agent ${agent.id} taskId from ${task.id} after move ${from} \u2192 ${to2}`);
168037
- }
168038
- } catch (error) {
168039
- logger3.warn(
168040
- `taskAgentLinkSync: failed to sync agents for task ${task.id} after move ${from} \u2192 ${to2}: ${error instanceof Error ? error.message : String(error)}`
168041
- );
168042
- }
168043
- };
168044
- opts.store.on("task:moved", handler);
168045
- return () => {
168046
- opts.store.off("task:moved", handler);
168047
- };
168048
- }
168049
- var CLEAR_COLUMNS;
168050
- var init_task_agent_sync = __esm({
168051
- "../engine/src/task-agent-sync.ts"() {
168052
- "use strict";
168053
- CLEAR_COLUMNS = /* @__PURE__ */ new Set(["done", "archived", "todo", "triage"]);
168054
- }
168055
- });
168056
-
168057
168433
  // ../engine/src/runtimes/in-process-runtime.ts
168058
168434
  import { EventEmitter as EventEmitter21 } from "node:events";
168059
168435
  import { setImmediate as setImmediateCb4 } from "node:timers";
@@ -168308,6 +168684,7 @@ var init_in_process_runtime = __esm({
168308
168684
  maxWorktrees: this.config.maxWorktrees,
168309
168685
  semaphore: this.globalSemaphore,
168310
168686
  agentStore: this.agentStore,
168687
+ hasActiveAgentExecution: (agentId) => this.heartbeatMonitor?.getTrackedAgents().includes(agentId) ?? false,
168311
168688
  missionStore,
168312
168689
  missionAutopilot,
168313
168690
  missionExecutionLoop,
@@ -191936,6 +192313,7 @@ var init_register_command_center_routes = __esm({
191936
192313
  init_src();
191937
192314
  init_api_error();
191938
192315
  init_command_center_csv();
192316
+ init_project_store_resolver();
191939
192317
  }
191940
192318
  });
191941
192319