@runfusion/fusion 0.76.0-beta.1 → 0.76.0-beta.2

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 (138) hide show
  1. package/dist/bin.js +503 -213
  2. package/dist/child-process-worker.js +466 -207
  3. package/dist/client/.vite/manifest.json +260 -260
  4. package/dist/client/assets/{AgentDetailView-Cbl1sw6i.js → AgentDetailView-gak4EWTI.js} +1 -1
  5. package/dist/client/assets/{AgentPermissionPolicyEditor-DD1U5M9p.js → AgentPermissionPolicyEditor-DP1QbZL-.js} +1 -1
  6. package/dist/client/assets/{AgentsView-BMcCbple.js → AgentsView-DAMRTKzI.js} +3 -3
  7. package/dist/client/assets/ChatView-iE-2gf5P.js +13 -0
  8. package/dist/client/assets/{CommandCenter-D7mcD61V.js → CommandCenter-B6RnkLYm.js} +1 -1
  9. package/dist/client/assets/{DevServerView-DaqCn0p5.js → DevServerView-DcFL_LzK.js} +1 -1
  10. package/dist/client/assets/{DirectoryPicker-CLdqqqYN.js → DirectoryPicker-CtjqrYoO.js} +1 -1
  11. package/dist/client/assets/{DocumentsView-BOROVxPm.js → DocumentsView-BkAe2S4H.js} +1 -1
  12. package/dist/client/assets/{EvalsView-BQMXRUlQ.js → EvalsView-CbGA9dMn.js} +1 -1
  13. package/dist/client/assets/{ExperimentalAgentOnboardingModal-1GNeCIQT.js → ExperimentalAgentOnboardingModal-CMgO_S8T.js} +1 -1
  14. package/dist/client/assets/{GoalsView-Cr3c_2GC.js → GoalsView-_3P9J5sf.js} +1 -1
  15. package/dist/client/assets/{InsightsView-DgVBVQM4.js → InsightsView-DOhO7xH5.js} +1 -1
  16. package/dist/client/assets/{MemoryView-C0VzzMSw.js → MemoryView-DwJas8vi.js} +1 -1
  17. package/dist/client/assets/{PiExtensionsManager-D1kkkVtP.js → PiExtensionsManager-B_LiW_e9.js} +1 -1
  18. package/dist/client/assets/{PluginManager-BW-_Zyo5.js → PluginManager-BkB6WLQc.js} +1 -1
  19. package/dist/client/assets/{PullRequestView-Cmlo4nWA.js → PullRequestView-DcH5tmYc.js} +1 -1
  20. package/dist/client/assets/{ReportModal-BWuaroTF.js → ReportModal-BOEbqtqG.js} +1 -1
  21. package/dist/client/assets/{ResearchView-BmkF_vZU.js → ResearchView-Dp6V42pI.js} +1 -1
  22. package/dist/client/assets/{SecretsView-DVc8Hky0.js → SecretsView-BCqXHB2L.js} +1 -1
  23. package/dist/client/assets/{SessionTerminal-DCXrxA57.js → SessionTerminal-CkdoQv4y.js} +1 -1
  24. package/dist/client/assets/{SettingsModal-DZ32F1c-.js → SettingsModal-D4Fn4GlS.js} +3 -3
  25. package/dist/client/assets/{SettingsModal-DqwpLnDU.js → SettingsModal-Dc7YG6KB.js} +1 -1
  26. package/dist/client/assets/{SettingsTextareaRow-B5spAoOY.js → SettingsTextareaRow-WSkBoAOO.js} +1 -1
  27. package/dist/client/assets/{SetupWizardModal-VTBLyFzr.js → SetupWizardModal-VTrJAsKd.js} +2 -2
  28. package/dist/client/assets/{SkillsView-CR91ey9d.js → SkillsView-CXeXOxfF.js} +1 -1
  29. package/dist/client/assets/{WorkflowNodeEditor-BzGh_Fd9.js → WorkflowNodeEditor-DoxLGPRF.js} +1 -1
  30. package/dist/client/assets/{agent-import-generation-D27NKQsr.js → agent-import-generation-upc0yw-M.js} +1 -1
  31. package/dist/client/assets/{agentsOrgChartLayout-C2K_M3x3.js → agentsOrgChartLayout-C3iumMrW.js} +1 -1
  32. package/dist/client/assets/{architectureDiagram-3BPJPVTR-BQy8UcRx.js → architectureDiagram-3BPJPVTR-D6jqc3fJ.js} +1 -1
  33. package/dist/client/assets/{blockDiagram-GPEHLZMM-CZG1bqFQ.js → blockDiagram-GPEHLZMM-DY3AKuPD.js} +1 -1
  34. package/dist/client/assets/{c4Diagram-AAUBKEIU-CZmO_kg3.js → c4Diagram-AAUBKEIU-CpD52V4g.js} +1 -1
  35. package/dist/client/assets/channel-CaxOu15c.js +1 -0
  36. package/dist/client/assets/{chunk-2J33WTMH-jsad6DTE.js → chunk-2J33WTMH-CPeIHyAX.js} +1 -1
  37. package/dist/client/assets/{chunk-4BX2VUAB-DX7SuvwP.js → chunk-4BX2VUAB-ivAwI4xM.js} +1 -1
  38. package/dist/client/assets/{chunk-55IACEB6-De20xFgU.js → chunk-55IACEB6-BtVQ5XaZ.js} +1 -1
  39. package/dist/client/assets/{chunk-727SXJPM-CNiri9yW.js → chunk-727SXJPM-1eap1vDU.js} +1 -1
  40. package/dist/client/assets/{chunk-AQP2D5EJ-DvDqG-ax.js → chunk-AQP2D5EJ-B2NB3BW9.js} +1 -1
  41. package/dist/client/assets/{chunk-FMBD7UC4-DkMdKaUq.js → chunk-FMBD7UC4-Hk_smNYv.js} +1 -1
  42. package/dist/client/assets/{chunk-ND2GUHAM-Do5BwIrI.js → chunk-ND2GUHAM-BmGCAojk.js} +1 -1
  43. package/dist/client/assets/{chunk-QZHKN3VN-BnJgt9vl.js → chunk-QZHKN3VN-D0aXZ8CV.js} +1 -1
  44. package/dist/client/assets/classDiagram-4FO5ZUOK-DXIkGbsl.js +1 -0
  45. package/dist/client/assets/classDiagram-v2-Q7XG4LA2-DXIkGbsl.js +1 -0
  46. package/dist/client/assets/{cose-bilkent-S5V4N54A-D-ivAzzF.js → cose-bilkent-S5V4N54A-DAbu_gnF.js} +1 -1
  47. package/dist/client/assets/{dagre-BM42HDAG-Bpd9L0or.js → dagre-BM42HDAG-BdmLlrDJ.js} +1 -1
  48. package/dist/client/assets/{dashboard-view-DSvVO6Vr.js → dashboard-view-BoFBSXUn.js} +1 -1
  49. package/dist/client/assets/{dashboard-view-CgBo8Ctn.js → dashboard-view-CULL1yhL.js} +1 -1
  50. package/dist/client/assets/{dashboard-view-C-XU9CVv.js → dashboard-view-CxXMDfNY.js} +1 -1
  51. package/dist/client/assets/{dashboard-view-DbaRE8Ma.js → dashboard-view-PRCWCSLm.js} +1 -1
  52. package/dist/client/assets/{diagram-2AECGRRQ-B6TT1NWU.js → diagram-2AECGRRQ-PpqLbVUA.js} +1 -1
  53. package/dist/client/assets/{diagram-5GNKFQAL-DpRS2yRw.js → diagram-5GNKFQAL-9rkGmTwh.js} +1 -1
  54. package/dist/client/assets/{diagram-KO2AKTUF-BVbZr02C.js → diagram-KO2AKTUF-BT-efOMo.js} +1 -1
  55. package/dist/client/assets/{diagram-LMA3HP47-DzENbfal.js → diagram-LMA3HP47-w79OWFxg.js} +1 -1
  56. package/dist/client/assets/{diagram-OG6HWLK6-BIePG5SY.js → diagram-OG6HWLK6-Bye9I5IO.js} +1 -1
  57. package/dist/client/assets/{erDiagram-TEJ5UH35-CQo3WBwo.js → erDiagram-TEJ5UH35-aodREgDf.js} +1 -1
  58. package/dist/client/assets/{flowDiagram-I6XJVG4X-Ct2H4jYo.js → flowDiagram-I6XJVG4X-D0DKItY3.js} +1 -1
  59. package/dist/client/assets/{folder-open-DAh8mpTX.js → folder-open-CqvaMJvx.js} +1 -1
  60. package/dist/client/assets/{ganttDiagram-6RSMTGT7-DyOLCG4B.js → ganttDiagram-6RSMTGT7-CZVApkvw.js} +1 -1
  61. package/dist/client/assets/{gitGraphDiagram-PVQCEYII-sC28-su3.js → gitGraphDiagram-PVQCEYII-D_ynwJ4p.js} +1 -1
  62. package/dist/client/assets/index-DWRJyaa3.js +2818 -0
  63. package/dist/client/assets/{infoDiagram-5YYISTIA-Q81_5aBZ.js → infoDiagram-5YYISTIA-pJG6zxjk.js} +1 -1
  64. package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-Cwkjs0z5.js → ishikawaDiagram-YF4QCWOH-nFZ5laUo.js} +1 -1
  65. package/dist/client/assets/{journeyDiagram-JHISSGLW-BXcBV1Bc.js → journeyDiagram-JHISSGLW-CWpCaAIe.js} +1 -1
  66. package/dist/client/assets/{kanban-definition-UN3LZRKU-BI7hW892.js → kanban-definition-UN3LZRKU-ATkPspKa.js} +1 -1
  67. package/dist/client/assets/{mermaid.core-B8oDA6jj.js → mermaid.core-CDXPNs7a.js} +4 -4
  68. package/dist/client/assets/{mindmap-definition-RKZ34NQL-COG6_9eD.js → mindmap-definition-RKZ34NQL-BkqS9tpe.js} +1 -1
  69. package/dist/client/assets/{pieDiagram-4H26LBE5-D11brZ_N.js → pieDiagram-4H26LBE5-DEUyVLs-.js} +1 -1
  70. package/dist/client/assets/{puzzle-D3_Z_rlW.js → puzzle-DQ0y1-XK.js} +1 -1
  71. package/dist/client/assets/{quadrantDiagram-W4KKPZXB-jmhDVZcv.js → quadrantDiagram-W4KKPZXB-ESBJNK5c.js} +1 -1
  72. package/dist/client/assets/{requirementDiagram-4Y6WPE33-BKCUWI1E.js → requirementDiagram-4Y6WPE33-CqPs7zcv.js} +1 -1
  73. package/dist/client/assets/{sankeyDiagram-5OEKKPKP-HsZdEl2t.js → sankeyDiagram-5OEKKPKP-CkFN0m14.js} +1 -1
  74. package/dist/client/assets/{sequenceDiagram-3UESZ5HK-CsDf7Fup.js → sequenceDiagram-3UESZ5HK-Dx2nDuMO.js} +1 -1
  75. package/dist/client/assets/{shield-alert-C16k8wNu.js → shield-alert-BS05s4RM.js} +1 -1
  76. package/dist/client/assets/{standing-instructions-template-BqAyftqe.js → standing-instructions-template-xprxYNHm.js} +1 -1
  77. package/dist/client/assets/{stateDiagram-AJRCARHV-fvzWhltB.js → stateDiagram-AJRCARHV-EUPmRFGd.js} +1 -1
  78. package/dist/client/assets/{stateDiagram-v2-BHNVJYJU-cnt42Sr_.js → stateDiagram-v2-BHNVJYJU-DcQ2mhi5.js} +1 -1
  79. package/dist/client/assets/{timeline-definition-PNZ67QCA-DsZFCSMb.js → timeline-definition-PNZ67QCA-D4YO_3V-.js} +1 -1
  80. package/dist/client/assets/{upload-_s5sL5Pq.js → upload-BjyBtxo7.js} +1 -1
  81. package/dist/client/assets/{users-DH1U5ISc.js → users-D5ogZ7WQ.js} +1 -1
  82. package/dist/client/assets/{vennDiagram-CIIHVFJN-B3KDWS-e.js → vennDiagram-CIIHVFJN-BT5_XuQL.js} +1 -1
  83. package/dist/client/assets/{wardley-L42UT6IY-BKs5MtQS.js → wardley-L42UT6IY-X_ZMW457.js} +1 -1
  84. package/dist/client/assets/{wardleyDiagram-YWT4CUSO-CNsEoXVB.js → wardleyDiagram-YWT4CUSO-GK9nONHU.js} +1 -1
  85. package/dist/client/assets/{xychartDiagram-2RQKCTM6-kq_gW4QC.js → xychartDiagram-2RQKCTM6-Dw3zXHAq.js} +1 -1
  86. package/dist/client/index.html +1 -1
  87. package/dist/client/version.json +1 -1
  88. package/dist/droid-cli/package.json +1 -1
  89. package/dist/extension.js +647 -207
  90. package/dist/migrations/0057_fn_9004_project_ownership_default_reconciliation.sql +13 -0
  91. package/dist/migrations/0058_fn_9014_message_archive.sql +13 -0
  92. package/dist/pi-claude-cli/package.json +5 -5
  93. package/dist/plugin-sdk/index.js +69 -23
  94. package/dist/plugins/fusion-plugin-acp-runtime/bundled.js +69 -23
  95. package/dist/plugins/fusion-plugin-acp-runtime/package.json +1 -1
  96. package/dist/plugins/fusion-plugin-claude-runtime/bundled.js +69 -23
  97. package/dist/plugins/fusion-plugin-claude-runtime/package.json +1 -1
  98. package/dist/plugins/fusion-plugin-cli-printing-press/bundled.js +69 -23
  99. package/dist/plugins/fusion-plugin-cli-printing-press/package.json +1 -1
  100. package/dist/plugins/fusion-plugin-compound-engineering/bundled.js +69 -23
  101. package/dist/plugins/fusion-plugin-compound-engineering/package.json +1 -1
  102. package/dist/plugins/fusion-plugin-cursor-runtime/bundled.js +69 -23
  103. package/dist/plugins/fusion-plugin-cursor-runtime/package.json +1 -1
  104. package/dist/plugins/fusion-plugin-dependency-graph/bundled.js +69 -23
  105. package/dist/plugins/fusion-plugin-dependency-graph/package.json +1 -1
  106. package/dist/plugins/fusion-plugin-droid-runtime/bundled.js +71 -25
  107. package/dist/plugins/fusion-plugin-droid-runtime/package.json +1 -1
  108. package/dist/plugins/fusion-plugin-grok-runtime/bundled.js +69 -23
  109. package/dist/plugins/fusion-plugin-grok-runtime/package.json +1 -1
  110. package/dist/plugins/fusion-plugin-hermes-runtime/bundled.js +69 -23
  111. package/dist/plugins/fusion-plugin-hermes-runtime/package.json +1 -1
  112. package/dist/plugins/fusion-plugin-linear-import/bundled.js +69 -23
  113. package/dist/plugins/fusion-plugin-linear-import/package.json +1 -1
  114. package/dist/plugins/fusion-plugin-omp-runtime/bundled.js +69 -23
  115. package/dist/plugins/fusion-plugin-omp-runtime/package.json +1 -1
  116. package/dist/plugins/fusion-plugin-openclaw-runtime/bundled.js +69 -23
  117. package/dist/plugins/fusion-plugin-openclaw-runtime/package.json +1 -1
  118. package/dist/plugins/fusion-plugin-paperclip-runtime/bundled.js +69 -23
  119. package/dist/plugins/fusion-plugin-paperclip-runtime/package.json +1 -1
  120. package/dist/plugins/fusion-plugin-quality/bundled.js +69 -23
  121. package/dist/plugins/fusion-plugin-quality/package.json +1 -1
  122. package/dist/plugins/fusion-plugin-reports/bundled.js +69 -23
  123. package/dist/plugins/fusion-plugin-reports/package.json +1 -1
  124. package/dist/plugins/fusion-plugin-roadmap/bundled.js +69 -23
  125. package/dist/plugins/fusion-plugin-roadmap/package.json +1 -1
  126. package/dist/plugins/fusion-plugin-todos/bundled.js +69 -23
  127. package/dist/plugins/fusion-plugin-todos/package.json +1 -1
  128. package/dist/plugins/fusion-plugin-whatsapp-chat/bundled.js +69 -23
  129. package/dist/plugins/fusion-plugin-whatsapp-chat/package.json +1 -1
  130. package/package.json +3 -3
  131. package/skill/fusion/SKILL.md +1 -1
  132. package/skill/fusion/references/extension-tools.md +22 -0
  133. package/skill/fusion/references/fusion-capabilities.md +2 -0
  134. package/dist/client/assets/ChatView-DcM-ARpZ.js +0 -13
  135. package/dist/client/assets/channel-Cwl9FefC.js +0 -1
  136. package/dist/client/assets/classDiagram-4FO5ZUOK-BZtWCoHC.js +0 -1
  137. package/dist/client/assets/classDiagram-v2-Q7XG4LA2-BZtWCoHC.js +0 -1
  138. package/dist/client/assets/index-BlGpMJSZ.js +0 -2818
@@ -21717,9 +21717,14 @@ var init_project = __esm({
21717
21717
  // now keyed per-project on `project_id` (the effective PK). `id` is retained
21718
21718
  // for column-shape parity (always 1) but is no longer the PK and no longer
21719
21719
  // CHECK-constrained. Single-project / SQLite-parity callers leave project_id
21720
- // at its '' default (one row), preserving the pre-isolation behavior.
21720
+ // through the database ownership trigger, preserving the pre-isolation behavior.
21721
+ /*
21722
+ FNXC:MultiProjectIsolation 2026-08-12-15:43:
21723
+ Migration 0006 owns config's project_id default and leaves its catalog PK as (project_id).
21724
+ Drizzle emits DEFAULT while the database GUC/trigger selects the effective ownership partition.
21725
+ */
21721
21726
  id: integer("id").default(1),
21722
- projectId: text("project_id").notNull().default("").primaryKey(),
21727
+ projectId: text("project_id").notNull().default(sql`current_setting('fusion.project_id', true)`).primaryKey(),
21723
21728
  nextId: integer("next_id").default(1),
21724
21729
  nextWorkflowStepId: integer("next_workflow_step_id").default(1),
21725
21730
  // FNXC:SqliteFinalRemoval 2026-06-28:
@@ -22113,9 +22118,13 @@ var init_project = __esm({
22113
22118
  automations = projectSchema.table("automations", {
22114
22119
  /*
22115
22120
  * FNXC:AutomationIsolation 2026-07-13-22:37:
22116
- * Automations are partitioned by the AsyncDataLayer's project ID because embedded PostgreSQL consolidates the per-project SQLite files into one table. The composite key deliberately permits the same automation ID in two projects without allowing either project's CRUD or cron-claim path to address the other row. The empty default preserves an explicit partition for legacy and project-agnostic callers until startup stamps migrated rows.
22121
+ * Automations are partitioned by the AsyncDataLayer's project ID because embedded PostgreSQL consolidates the per-project SQLite files into one table. The composite key deliberately permits the same automation ID in two projects without allowing either project's CRUD or cron-claim path to address the other row.
22122
+ *
22123
+ * FNXC:MultiProjectIsolation 2026-08-12-15:43:
22124
+ * Migration 0006 owns the default through the database GUC/trigger; Drizzle emits DEFAULT
22125
+ * without replacing the physical legacy fallback or the fail-closed bound writer contract.
22117
22126
  */
22118
- projectId: text("project_id").notNull().default(""),
22127
+ projectId: text("project_id").notNull().default(sql`current_setting('fusion.project_id', true)`),
22119
22128
  id: text("id").notNull(),
22120
22129
  name: text("name").notNull(),
22121
22130
  description: text("description"),
@@ -22414,7 +22423,8 @@ var init_project = __esm({
22414
22423
  index("idxTaskDocumentsTaskId").on(t.taskId)
22415
22424
  ]);
22416
22425
  artifacts = projectSchema.table("artifacts", {
22417
- id: text("id").primaryKey(),
22426
+ projectId: text("project_id").notNull().default(sql`current_setting('fusion.project_id', true)`),
22427
+ id: text("id").notNull(),
22418
22428
  type: text("type").notNull(),
22419
22429
  title: text("title").notNull(),
22420
22430
  description: text("description"),
@@ -22429,7 +22439,8 @@ var init_project = __esm({
22429
22439
  createdAt: text("created_at").notNull(),
22430
22440
  updatedAt: text("updated_at").notNull()
22431
22441
  }, (t) => [
22432
- foreignKey({ columns: [t.taskId], foreignColumns: [tasks.id] }).onDelete("cascade"),
22442
+ primaryKey({ columns: [t.projectId, t.id] }),
22443
+ foreignKey({ name: "artifacts_task_id_fkey", columns: [t.projectId, t.taskId], foreignColumns: [tasks.projectId, tasks.id] }).onDelete("cascade"),
22433
22444
  index("idxArtifactsTaskId").on(t.taskId),
22434
22445
  index("idxArtifactsAuthorId").on(t.authorId),
22435
22446
  index("idxArtifactsType").on(t.type),
@@ -22619,7 +22630,8 @@ var init_project = __esm({
22619
22630
  index("idxEvalRunEventsRunIdSeq").on(t.runId, t.seq)
22620
22631
  ]);
22621
22632
  secrets = projectSchema.table("secrets", {
22622
- id: text("id").primaryKey(),
22633
+ projectId: text("project_id").notNull().default(sql`current_setting('fusion.project_id', true)`),
22634
+ id: text("id").notNull(),
22623
22635
  key: text("key").notNull(),
22624
22636
  valueCiphertext: bytea("value_ciphertext").notNull(),
22625
22637
  nonce: bytea("nonce").notNull(),
@@ -22632,7 +22644,8 @@ var init_project = __esm({
22632
22644
  lastReadAt: text("last_read_at"),
22633
22645
  lastReadBy: text("last_read_by")
22634
22646
  }, (t) => [
22635
- unique("secrets_key_unique").on(t.key),
22647
+ primaryKey({ columns: [t.projectId, t.id] }),
22648
+ unique("secrets_key_unique").on(t.projectId, t.key),
22636
22649
  check("secrets_access_policy_check", sql`${t.accessPolicy} IN ('auto', 'prompt', 'deny')`),
22637
22650
  check("secrets_env_exportable_check", sql`${t.envExportable} IN (0, 1)`)
22638
22651
  ]);
@@ -22674,10 +22687,11 @@ var init_project = __esm({
22674
22687
  updatedAt: text("updated_at").notNull()
22675
22688
  }, (t) => [primaryKey({ columns: [t.projectId, t.id] })]);
22676
22689
  branchGroups = projectSchema.table("branch_groups", {
22677
- id: text("id").primaryKey(),
22690
+ projectId: text("project_id").notNull().default(sql`current_setting('fusion.project_id', true)`),
22691
+ id: text("id").notNull(),
22678
22692
  sourceType: text("source_type").notNull(),
22679
22693
  sourceId: text("source_id").notNull(),
22680
- branchName: text("branch_name").notNull().unique(),
22694
+ branchName: text("branch_name").notNull(),
22681
22695
  worktreePath: text("worktree_path"),
22682
22696
  autoMerge: integer("auto_merge").notNull().default(0),
22683
22697
  prState: text("pr_state").notNull().default("none"),
@@ -22693,6 +22707,8 @@ var init_project = __esm({
22693
22707
  updatedAt: bigint("updated_at", { mode: "number" }).notNull(),
22694
22708
  closedAt: bigint("closed_at", { mode: "number" })
22695
22709
  }, (t) => [
22710
+ primaryKey({ columns: [t.projectId, t.id] }),
22711
+ unique("branch_groups_branch_name_key").on(t.projectId, t.branchName),
22696
22712
  check("branch_groups_source_type_check", sql`${t.sourceType} IN ('mission','planning','new-task')`),
22697
22713
  check("branch_groups_pr_state_check", sql`${t.prState} IN ('none','open','merged','closed')`),
22698
22714
  check("branch_groups_status_check", sql`${t.status} IN ('open','finalized','abandoned')`),
@@ -23094,12 +23110,14 @@ var init_project = __esm({
23094
23110
  index("idxUsageEventsKindTs").on(t.kind, t.ts)
23095
23111
  ]);
23096
23112
  pluginActivations = projectSchema.table("plugin_activations", {
23097
- id: integer("id").generatedAlwaysAsIdentity().primaryKey(),
23113
+ projectId: text("project_id").notNull().default(sql`current_setting('fusion.project_id', true)`),
23114
+ id: integer("id").generatedAlwaysAsIdentity().notNull(),
23098
23115
  pluginId: text("plugin_id").notNull(),
23099
23116
  source: text("source").notNull(),
23100
23117
  pluginVersion: text("plugin_version"),
23101
23118
  activatedAt: text("activated_at").notNull()
23102
23119
  }, (t) => [
23120
+ primaryKey({ columns: [t.projectId, t.id] }),
23103
23121
  index("idxPluginActivationsActivatedAt").on(t.activatedAt),
23104
23122
  index("idxPluginActivationsPluginId").on(t.pluginId)
23105
23123
  ]);
@@ -23124,8 +23142,13 @@ var init_project = __esm({
23124
23142
  index("idxKnowledgePagesUpdatedAt").on(t.updatedAt)
23125
23143
  ]);
23126
23144
  deployments = projectSchema.table("deployments", {
23127
- id: integer("id").generatedAlwaysAsIdentity().primaryKey(),
23128
- projectId: text("project_id").notNull().default(""),
23145
+ id: integer("id").generatedAlwaysAsIdentity().notNull(),
23146
+ /*
23147
+ FNXC:MultiProjectIsolation 2026-08-12-15:43:
23148
+ Migration 0006 rebuilt deployments_pkey as (project_id, id). Drizzle emits DEFAULT while the
23149
+ database GUC/trigger keeps ownership stamping and the physical legacy fallback authoritative.
23150
+ */
23151
+ projectId: text("project_id").notNull().default(sql`current_setting('fusion.project_id', true)`),
23129
23152
  deploymentId: text("deployment_id").notNull(),
23130
23153
  service: text("service"),
23131
23154
  environment: text("environment"),
@@ -23136,6 +23159,7 @@ var init_project = __esm({
23136
23159
  meta: jsonb("meta"),
23137
23160
  createdAt: text("created_at").notNull()
23138
23161
  }, (t) => [
23162
+ primaryKey({ columns: [t.projectId, t.id], name: "deployments_pkey" }),
23139
23163
  uniqueIndex("idxDeploymentsProjectDeploymentId").on(t.projectId, t.deploymentId),
23140
23164
  index("idxDeploymentsProjectDeployedAt").on(t.projectId, t.deployedAt),
23141
23165
  index("idxDeploymentsDeployedAt").on(t.deployedAt),
@@ -23143,7 +23167,12 @@ var init_project = __esm({
23143
23167
  ]);
23144
23168
  githubCheckStates = projectSchema.table("github_check_states", {
23145
23169
  id: integer("id").generatedAlwaysAsIdentity().notNull(),
23146
- projectId: text("project_id").notNull().default(""),
23170
+ /*
23171
+ FNXC:MultiProjectIsolation 2026-08-12-15:43:
23172
+ Migration 0048 post-dated 0006, so FN-9004 reconciles its physical default to the ownership
23173
+ expression. Drizzle emits DEFAULT while the database GUC/trigger remains the stamping authority.
23174
+ */
23175
+ projectId: text("project_id").notNull().default(sql`current_setting('fusion.project_id', true)`),
23147
23176
  repo: text("repo").notNull(),
23148
23177
  headSha: text("head_sha").notNull(),
23149
23178
  checkName: text("check_name").notNull(),
@@ -23163,9 +23192,14 @@ var init_project = __esm({
23163
23192
  index("idxGithubCheckStatesProjectReceived").on(t.projectId, t.receivedAt)
23164
23193
  ]);
23165
23194
  incidents = projectSchema.table("incidents", {
23166
- id: integer("id").generatedAlwaysAsIdentity().primaryKey(),
23167
- projectId: text("project_id").notNull().default(""),
23168
- incidentId: text("incident_id").notNull().unique(),
23195
+ id: integer("id").generatedAlwaysAsIdentity().notNull(),
23196
+ /*
23197
+ FNXC:MultiProjectIsolation 2026-08-12-15:43:
23198
+ Migration 0006 rebuilt incident keys with project_id first. Drizzle emits DEFAULT while the
23199
+ database GUC/trigger retains ownership stamping and its physical legacy fallback.
23200
+ */
23201
+ projectId: text("project_id").notNull().default(sql`current_setting('fusion.project_id', true)`),
23202
+ incidentId: text("incident_id").notNull(),
23169
23203
  groupingKey: text("grouping_key").notNull(),
23170
23204
  title: text("title").notNull(),
23171
23205
  severity: text("severity"),
@@ -23179,6 +23213,8 @@ var init_project = __esm({
23179
23213
  createdAt: text("created_at").notNull(),
23180
23214
  updatedAt: text("updated_at").notNull()
23181
23215
  }, (t) => [
23216
+ primaryKey({ columns: [t.projectId, t.id], name: "incidents_pkey" }),
23217
+ unique("incidents_incident_id_key").on(t.projectId, t.incidentId),
23182
23218
  index("idxIncidentsProjectOpenedAt").on(t.projectId, t.openedAt),
23183
23219
  index("idxIncidentsProjectStatus").on(t.projectId, t.status),
23184
23220
  index("idxIncidentsGroupingKey").on(t.groupingKey),
@@ -23233,12 +23269,14 @@ var init_project = __esm({
23233
23269
  content: text("content").notNull(),
23234
23270
  type: text("type").notNull(),
23235
23271
  read: integer("read").default(0),
23272
+ archived: integer("archived").default(0),
23236
23273
  metadata: jsonb("metadata"),
23237
23274
  createdAt: text("created_at").notNull(),
23238
23275
  updatedAt: text("updated_at").notNull()
23239
23276
  }, (t) => [
23240
23277
  primaryKey({ columns: [t.projectId, t.id] }),
23241
23278
  index("idxMessagesTo").on(t.toId, t.toType, t.read),
23279
+ index("idxMessagesToArchived").on(t.toId, t.toType, t.archived),
23242
23280
  index("idxMessagesFrom").on(t.fromId, t.fromType),
23243
23281
  index("idxMessagesCreatedAt").on(t.createdAt)
23244
23282
  ]);
@@ -23339,7 +23377,8 @@ var init_project = __esm({
23339
23377
  index("idx_cli_sessions_project_state").on(t.projectId, t.agentState)
23340
23378
  ]);
23341
23379
  chatMessages = projectSchema.table("chat_messages", {
23342
- id: text("id").primaryKey(),
23380
+ projectId: text("project_id").notNull().default(sql`current_setting('fusion.project_id', true)`),
23381
+ id: text("id").notNull(),
23343
23382
  sessionId: text("session_id").notNull(),
23344
23383
  role: text("role").notNull(),
23345
23384
  content: text("content").notNull(),
@@ -23348,6 +23387,7 @@ var init_project = __esm({
23348
23387
  createdAt: text("created_at").notNull(),
23349
23388
  attachments: jsonb("attachments")
23350
23389
  }, (t) => [
23390
+ primaryKey({ columns: [t.projectId, t.id] }),
23351
23391
  index("idxChatMessagesSessionId").on(t.sessionId),
23352
23392
  index("idxChatMessagesCreatedAt").on(t.createdAt)
23353
23393
  ]);
@@ -23373,7 +23413,8 @@ var init_project = __esm({
23373
23413
  index("idxChatTokenUsageCreatedAt").on(t.createdAt)
23374
23414
  ]);
23375
23415
  runAuditEvents = projectSchema.table("run_audit_events", {
23376
- id: text("id").primaryKey(),
23416
+ projectId: text("project_id").notNull().default(sql`current_setting('fusion.project_id', true)`),
23417
+ id: text("id").notNull(),
23377
23418
  timestamp: text("timestamp").notNull(),
23378
23419
  taskId: text("task_id"),
23379
23420
  agentId: text("agent_id").notNull(),
@@ -23383,6 +23424,7 @@ var init_project = __esm({
23383
23424
  target: text("target").notNull(),
23384
23425
  metadata: jsonb("metadata")
23385
23426
  }, (t) => [
23427
+ primaryKey({ columns: [t.projectId, t.id] }),
23386
23428
  index("idxRunAuditEventsRunIdTimestamp").on(t.runId, t.timestamp),
23387
23429
  index("idxRunAuditEventsTaskIdTimestamp").on(t.taskId, t.timestamp),
23388
23430
  index("idxRunAuditEventsTimestamp").on(t.timestamp)
@@ -23483,13 +23525,14 @@ var init_project = __esm({
23483
23525
  index("idxMissionLineageStopsMissionId").on(t.projectId, t.missionId)
23484
23526
  ]);
23485
23527
  verificationCache = projectSchema.table("verification_cache", {
23528
+ projectId: text("project_id").notNull().default(sql`current_setting('fusion.project_id', true)`),
23486
23529
  treeSha: text("tree_sha").notNull(),
23487
23530
  testCommand: text("test_command").notNull().default(""),
23488
23531
  buildCommand: text("build_command").notNull().default(""),
23489
23532
  recordedAt: text("recorded_at").notNull(),
23490
23533
  taskId: text("task_id")
23491
23534
  }, (t) => [
23492
- primaryKey({ columns: [t.treeSha, t.testCommand, t.buildCommand] }),
23535
+ primaryKey({ columns: [t.projectId, t.treeSha, t.testCommand, t.buildCommand] }),
23493
23536
  index("idxVerificationCacheRecordedAt").on(t.recordedAt)
23494
23537
  ]);
23495
23538
  importTranslationCache = projectSchema.table("import_translation_cache", {
@@ -23522,7 +23565,8 @@ var init_project = __esm({
23522
23565
  index("idxImportTranslationCacheRecordedAt").on(t.recordedAt)
23523
23566
  ]);
23524
23567
  approvalRequests = projectSchema.table("approval_requests", {
23525
- id: text("id").primaryKey(),
23568
+ projectId: text("project_id").notNull().default(sql`current_setting('fusion.project_id', true)`),
23569
+ id: text("id").notNull(),
23526
23570
  status: text("status").notNull(),
23527
23571
  requesterActorId: text("requester_actor_id").notNull(),
23528
23572
  requesterActorType: text("requester_actor_type").notNull(),
@@ -23541,13 +23585,14 @@ var init_project = __esm({
23541
23585
  createdAt: text("created_at").notNull(),
23542
23586
  updatedAt: text("updated_at").notNull()
23543
23587
  }, (t) => [
23588
+ primaryKey({ columns: [t.projectId, t.id] }),
23544
23589
  index("idxApprovalRequestsStatusCreatedAt").on(t.status, t.createdAt),
23545
23590
  index("idxApprovalRequestsRequesterCreatedAt").on(t.requesterActorId, t.createdAt),
23546
23591
  index("idxApprovalRequestsTaskCreatedAt").on(t.taskId, t.createdAt)
23547
23592
  ]);
23548
23593
  approvalRequestAuditEvents = projectSchema.table("approval_request_audit_events", {
23549
- projectId: text("project_id").notNull().default(""),
23550
- id: text("id").primaryKey(),
23594
+ projectId: text("project_id").notNull().default(sql`current_setting('fusion.project_id', true)`),
23595
+ id: text("id").notNull(),
23551
23596
  requestId: text("request_id").notNull(),
23552
23597
  eventType: text("event_type").notNull(),
23553
23598
  actorId: text("actor_id").notNull(),
@@ -23556,6 +23601,7 @@ var init_project = __esm({
23556
23601
  note: text("note"),
23557
23602
  createdAt: text("created_at").notNull()
23558
23603
  }, (t) => [
23604
+ primaryKey({ columns: [t.projectId, t.id] }),
23559
23605
  index("idxApprovalRequestAuditRequestCreatedAt").on(t.requestId, t.createdAt, t.id),
23560
23606
  index("idxApprovalRequestAuditProjectCreatedAt").on(t.projectId, t.createdAt)
23561
23607
  ]);
@@ -27045,6 +27091,27 @@ var init_grok_provider = __esm({
27045
27091
  apiKey: "$GROK_API_KEY",
27046
27092
  api: "openai-completions",
27047
27093
  models: [
27094
+ /*
27095
+ FNXC:ModelRegistry 2026-08-12-20:17:
27096
+ FN-9008 requires Grok 4.6 to be selectable in every model area. Keep it in this shared
27097
+ catalog because pi's registerProvider() replaces provider model lists wholesale, while every
27098
+ Fusion host seeds and re-merges this export. xAI's model docs verify grok-4.6, its 500k-token
27099
+ context window, and configurable reasoning; max output and per-model image input remain
27100
+ upstream-pending-verification, so retain the conservative text-only and 65536-token defaults.
27101
+ Source: https://docs.x.ai/developers/models
27102
+ */
27103
+ {
27104
+ id: "grok-4.6",
27105
+ name: "Grok 4.6",
27106
+ reasoning: true,
27107
+ input: ["text"],
27108
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
27109
+ contextWindow: 5e5,
27110
+ maxTokens: 65536,
27111
+ compat: {
27112
+ supportsDeveloperRole: false
27113
+ }
27114
+ },
27048
27115
  {
27049
27116
  id: "grok-4.5",
27050
27117
  name: "Grok 4.5",
@@ -35003,6 +35070,7 @@ function rowToMessage(row) {
35003
35070
  content: row.content,
35004
35071
  type: row.type,
35005
35072
  read: (row.read ?? 0) === 1,
35073
+ archived: (row.archived ?? 0) === 1,
35006
35074
  metadata: row.metadata ?? void 0,
35007
35075
  createdAt: row.createdAt,
35008
35076
  updatedAt: row.updatedAt
@@ -35014,6 +35082,11 @@ function participantIdsForLookup(ownerId, ownerType) {
35014
35082
  }
35015
35083
  return [ownerId];
35016
35084
  }
35085
+ function archivedCondition(archived) {
35086
+ if (archived === true) return eq(project_exports.messages.archived, 1);
35087
+ if (archived === false) return or(eq(project_exports.messages.archived, 0), sql`${project_exports.messages.archived} IS NULL`);
35088
+ return or(eq(project_exports.messages.archived, 0), sql`${project_exports.messages.archived} IS NULL`);
35089
+ }
35017
35090
  async function sendMessage(handle, message) {
35018
35091
  const sanitizedContent = sanitizeTextValue(message.content);
35019
35092
  const sanitizedMetadata = sanitizeJsonbValue(message.metadata);
@@ -35026,6 +35099,7 @@ async function sendMessage(handle, message) {
35026
35099
  content: sanitizedContent,
35027
35100
  type: message.type,
35028
35101
  read: message.read ? 1 : 0,
35102
+ archived: message.archived ? 1 : 0,
35029
35103
  metadata: sanitizedMetadata,
35030
35104
  createdAt: message.createdAt,
35031
35105
  updatedAt: message.updatedAt
@@ -35034,7 +35108,8 @@ async function sendMessage(handle, message) {
35034
35108
  ...message,
35035
35109
  content: sanitizedContent,
35036
35110
  metadata: sanitizedMetadata,
35037
- read: message.read ? 1 : 0
35111
+ read: message.read ? 1 : 0,
35112
+ archived: message.archived ? 1 : 0
35038
35113
  });
35039
35114
  }
35040
35115
  async function sendMessageOnce(handle, message) {
@@ -35047,6 +35122,7 @@ async function sendMessageOnce(handle, message) {
35047
35122
  content: message.content,
35048
35123
  type: message.type,
35049
35124
  read: message.read ? 1 : 0,
35125
+ archived: message.archived ? 1 : 0,
35050
35126
  metadata: message.metadata,
35051
35127
  createdAt: message.createdAt,
35052
35128
  updatedAt: message.updatedAt
@@ -35098,6 +35174,7 @@ async function queryMessagesByParticipant(handle, direction, ownerId, ownerType,
35098
35174
  if (filter?.read !== void 0) {
35099
35175
  conditions.push(eq(project_exports.messages.read, filter.read ? 1 : 0));
35100
35176
  }
35177
+ conditions.push(archivedCondition(filter?.archived));
35101
35178
  const limit = filter?.limit ?? 100;
35102
35179
  const offset = filter?.offset ?? 0;
35103
35180
  const rows = await handle.select(messageColumns).from(project_exports.messages).where(and(...conditions)).orderBy(desc(project_exports.messages.createdAt), desc(project_exports.messages.id)).limit(limit).offset(offset);
@@ -35111,6 +35188,13 @@ async function markMessageAsRead(handle, messageId) {
35111
35188
  await handle.update(project_exports.messages).set({ read: 1, updatedAt: now }).where(eq(project_exports.messages.id, messageId));
35112
35189
  return await getMessage(handle, messageId);
35113
35190
  }
35191
+ async function setMessageArchived(handle, id, archived) {
35192
+ const existing = await getMessage(handle, id);
35193
+ if (!existing) return null;
35194
+ if (existing.archived === archived) return existing;
35195
+ const rows = await handle.update(project_exports.messages).set({ archived: archived ? 1 : 0, updatedAt: (/* @__PURE__ */ new Date()).toISOString() }).where(eq(project_exports.messages.id, id)).returning(messageColumns);
35196
+ return rows[0] ? rowToMessage(rows[0]) : null;
35197
+ }
35114
35198
  async function markAllMessagesAsRead(handle, ownerId, ownerType) {
35115
35199
  const now = (/* @__PURE__ */ new Date()).toISOString();
35116
35200
  const participantIds = participantIdsForLookup(ownerId, ownerType);
@@ -35118,7 +35202,8 @@ async function markAllMessagesAsRead(handle, ownerId, ownerType) {
35118
35202
  and(
35119
35203
  inArray(project_exports.messages.toId, participantIds),
35120
35204
  eq(project_exports.messages.toType, ownerType),
35121
- eq(project_exports.messages.read, 0)
35205
+ eq(project_exports.messages.read, 0),
35206
+ archivedCondition()
35122
35207
  )
35123
35208
  );
35124
35209
  const count2 = countRows[0]?.count ?? 0;
@@ -35126,7 +35211,8 @@ async function markAllMessagesAsRead(handle, ownerId, ownerType) {
35126
35211
  and(
35127
35212
  inArray(project_exports.messages.toId, participantIds),
35128
35213
  eq(project_exports.messages.toType, ownerType),
35129
- eq(project_exports.messages.read, 0)
35214
+ eq(project_exports.messages.read, 0),
35215
+ archivedCondition()
35130
35216
  )
35131
35217
  );
35132
35218
  return count2;
@@ -35148,19 +35234,22 @@ async function getConversation(handle, participantA, participantB, options) {
35148
35234
  const aIds = participantIdsForLookup(participantA.id, participantA.type);
35149
35235
  const bIds = participantIdsForLookup(participantB.id, participantB.type);
35150
35236
  const rows = await handle.select(messageColumns).from(project_exports.messages).where(
35151
- or(
35152
- and(
35153
- inArray(project_exports.messages.fromId, aIds),
35154
- eq(project_exports.messages.fromType, participantA.type),
35155
- inArray(project_exports.messages.toId, bIds),
35156
- eq(project_exports.messages.toType, participantB.type)
35237
+ and(
35238
+ or(
35239
+ and(
35240
+ inArray(project_exports.messages.fromId, aIds),
35241
+ eq(project_exports.messages.fromType, participantA.type),
35242
+ inArray(project_exports.messages.toId, bIds),
35243
+ eq(project_exports.messages.toType, participantB.type)
35244
+ ),
35245
+ and(
35246
+ inArray(project_exports.messages.fromId, bIds),
35247
+ eq(project_exports.messages.fromType, participantB.type),
35248
+ inArray(project_exports.messages.toId, aIds),
35249
+ eq(project_exports.messages.toType, participantA.type)
35250
+ )
35157
35251
  ),
35158
- and(
35159
- inArray(project_exports.messages.fromId, bIds),
35160
- eq(project_exports.messages.fromType, participantB.type),
35161
- inArray(project_exports.messages.toId, aIds),
35162
- eq(project_exports.messages.toType, participantA.type)
35163
- )
35252
+ archivedCondition(options?.archived)
35164
35253
  )
35165
35254
  ).orderBy(desc(project_exports.messages.createdAt)).limit(limit);
35166
35255
  return rows.reverse().map((row) => rowToMessage(row));
@@ -35171,14 +35260,16 @@ async function getMailbox(handle, ownerId, ownerType) {
35171
35260
  and(
35172
35261
  inArray(project_exports.messages.toId, participantIds),
35173
35262
  eq(project_exports.messages.toType, ownerType),
35174
- eq(project_exports.messages.read, 0)
35263
+ eq(project_exports.messages.read, 0),
35264
+ archivedCondition()
35175
35265
  )
35176
35266
  );
35177
35267
  const unreadCount = unreadRows[0]?.count ?? 0;
35178
35268
  const lastRows = await handle.select(messageColumns).from(project_exports.messages).where(
35179
35269
  and(
35180
35270
  inArray(project_exports.messages.toId, participantIds),
35181
- eq(project_exports.messages.toType, ownerType)
35271
+ eq(project_exports.messages.toType, ownerType),
35272
+ archivedCondition()
35182
35273
  )
35183
35274
  ).orderBy(desc(project_exports.messages.createdAt), desc(project_exports.messages.id)).limit(1);
35184
35275
  return {
@@ -35188,15 +35279,16 @@ async function getMailbox(handle, ownerId, ownerType) {
35188
35279
  lastMessage: lastRows[0] ? rowToMessage(lastRows[0]) : void 0
35189
35280
  };
35190
35281
  }
35191
- async function getAllAgentToAgentMessages(handle) {
35192
- const rows = await handle.select(messageColumns).from(project_exports.messages).where(eq(project_exports.messages.type, "agent-to-agent")).orderBy(desc(project_exports.messages.createdAt), desc(project_exports.messages.id));
35282
+ async function getAllAgentToAgentMessages(handle, filter) {
35283
+ const rows = await handle.select(messageColumns).from(project_exports.messages).where(and(eq(project_exports.messages.type, "agent-to-agent"), archivedCondition(filter?.archived))).orderBy(desc(project_exports.messages.createdAt), desc(project_exports.messages.id));
35193
35284
  return rows.map((row) => rowToMessage(row));
35194
35285
  }
35195
35286
  async function getUnreadAgentToAgentCount(handle) {
35196
35287
  const rows = await handle.select({ count: sql`count(*)::int` }).from(project_exports.messages).where(
35197
35288
  and(
35198
35289
  eq(project_exports.messages.type, "agent-to-agent"),
35199
- eq(project_exports.messages.read, 0)
35290
+ eq(project_exports.messages.read, 0),
35291
+ archivedCondition()
35200
35292
  )
35201
35293
  );
35202
35294
  return rows[0]?.count ?? 0;
@@ -35218,6 +35310,7 @@ var init_async_message_store = __esm({
35218
35310
  content: project_exports.messages.content,
35219
35311
  type: project_exports.messages.type,
35220
35312
  read: project_exports.messages.read,
35313
+ archived: project_exports.messages.archived,
35221
35314
  metadata: project_exports.messages.metadata,
35222
35315
  createdAt: project_exports.messages.createdAt,
35223
35316
  updatedAt: project_exports.messages.updatedAt
@@ -35403,12 +35496,12 @@ var init_message_store = __esm({
35403
35496
  }
35404
35497
  const sqliteDb = this.db;
35405
35498
  this.stmtInsert = sqliteDb.prepare(`
35406
- INSERT INTO messages (id, fromId, fromType, toId, toType, content, type, read, metadata, createdAt, updatedAt)
35407
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
35499
+ INSERT INTO messages (id, fromId, fromType, toId, toType, content, type, read, archived, metadata, createdAt, updatedAt)
35500
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
35408
35501
  `);
35409
35502
  this.stmtInsertOnce = sqliteDb.prepare(`
35410
- INSERT OR IGNORE INTO messages (id, fromId, fromType, toId, toType, content, type, read, metadata, createdAt, updatedAt)
35411
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
35503
+ INSERT OR IGNORE INTO messages (id, fromId, fromType, toId, toType, content, type, read, archived, metadata, createdAt, updatedAt)
35504
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
35412
35505
  `);
35413
35506
  this.stmtGetById = sqliteDb.prepare(`
35414
35507
  SELECT * FROM messages WHERE id = ?
@@ -35446,6 +35539,7 @@ var init_message_store = __esm({
35446
35539
  content: row.content,
35447
35540
  type: row.type,
35448
35541
  read: row.read === 1,
35542
+ archived: (row.archived ?? 0) === 1,
35449
35543
  metadata: fromJson(row.metadata),
35450
35544
  createdAt: row.createdAt,
35451
35545
  updatedAt: row.updatedAt
@@ -35479,6 +35573,7 @@ var init_message_store = __esm({
35479
35573
  content: sanitizeTextValue(input.content),
35480
35574
  type: input.type,
35481
35575
  read: false,
35576
+ archived: false,
35482
35577
  metadata: sanitizeJsonbValue(input.metadata),
35483
35578
  createdAt: now,
35484
35579
  updatedAt: now
@@ -35494,6 +35589,7 @@ var init_message_store = __esm({
35494
35589
  content: message.content,
35495
35590
  type: message.type,
35496
35591
  read: message.read,
35592
+ archived: message.archived,
35497
35593
  metadata: message.metadata ?? null,
35498
35594
  createdAt: message.createdAt,
35499
35595
  updatedAt: message.updatedAt
@@ -35508,6 +35604,7 @@ var init_message_store = __esm({
35508
35604
  message.content,
35509
35605
  message.type,
35510
35606
  message.read ? 1 : 0,
35607
+ message.archived ? 1 : 0,
35511
35608
  toJsonNullable(message.metadata),
35512
35609
  message.createdAt,
35513
35610
  message.updatedAt
@@ -35566,6 +35663,7 @@ var init_message_store = __esm({
35566
35663
  content: sanitizeTextValue(input.content),
35567
35664
  type: input.type,
35568
35665
  read: false,
35666
+ archived: false,
35569
35667
  metadata: sanitizeJsonbValue(input.metadata),
35570
35668
  createdAt: now,
35571
35669
  updatedAt: now
@@ -35586,6 +35684,7 @@ var init_message_store = __esm({
35586
35684
  message.content,
35587
35685
  message.type,
35588
35686
  0,
35687
+ 0,
35589
35688
  toJsonNullable(message.metadata),
35590
35689
  message.createdAt,
35591
35690
  message.updatedAt
@@ -35717,6 +35816,7 @@ var init_message_store = __esm({
35717
35816
  whereClauses.push("read = ?");
35718
35817
  params.push(filter.read ? 1 : 0);
35719
35818
  }
35819
+ whereClauses.push(filter?.archived === true ? "archived = 1" : "(archived = 0 OR archived IS NULL)");
35720
35820
  const whereSql = whereClauses.join(" AND ");
35721
35821
  const limit = filter?.limit ?? 100;
35722
35822
  const offset = filter?.offset ?? 0;
@@ -35767,15 +35867,39 @@ var init_message_store = __esm({
35767
35867
  const participantIds = this.getParticipantIdsForLookup(ownerId, ownerType);
35768
35868
  const toIdPredicate = participantIds.length === 1 ? "toId = ?" : `toId IN (${participantIds.map(() => "?").join(", ")})`;
35769
35869
  const unreadRow = this.db.prepare(`
35770
- SELECT COUNT(*) as count FROM messages WHERE ${toIdPredicate} AND toType = ? AND read = 0
35870
+ SELECT COUNT(*) as count FROM messages WHERE ${toIdPredicate} AND toType = ? AND read = 0 AND (archived = 0 OR archived IS NULL)
35771
35871
  `).get(...participantIds, ownerType);
35772
35872
  const count2 = unreadRow?.count ?? 0;
35773
35873
  this.db.prepare(`
35774
- UPDATE messages SET read = 1, updatedAt = ? WHERE ${toIdPredicate} AND toType = ? AND read = 0
35874
+ UPDATE messages SET read = 1, updatedAt = ? WHERE ${toIdPredicate} AND toType = ? AND read = 0 AND (archived = 0 OR archived IS NULL)
35775
35875
  `).run(now, ...participantIds, ownerType);
35776
35876
  this.db.bumpLastModified();
35777
35877
  return count2;
35778
35878
  }
35879
+ /** Archive a message without destroying its correspondence history. */
35880
+ async archiveMessage(id) {
35881
+ return this.setMessageArchived(id, true);
35882
+ }
35883
+ /** Restore a previously archived message to default mailbox lists. */
35884
+ async unarchiveMessage(id) {
35885
+ return this.setMessageArchived(id, false);
35886
+ }
35887
+ async setMessageArchived(id, archived) {
35888
+ if (this.asyncLayer) {
35889
+ const updated2 = await setMessageArchived(this.asyncLayer.db, id, archived);
35890
+ if (!updated2) throw new Error(`Message ${id} not found`);
35891
+ this.emit(archived ? "message:archived" : "message:unarchived", updated2);
35892
+ return updated2;
35893
+ }
35894
+ const existing = await this.getMessage(id);
35895
+ if (!existing) throw new Error(`Message ${id} not found`);
35896
+ if (existing.archived === archived) return existing;
35897
+ this.db.prepare("UPDATE messages SET archived = ?, updatedAt = ? WHERE id = ?").run(archived ? 1 : 0, (/* @__PURE__ */ new Date()).toISOString(), id);
35898
+ this.db.bumpLastModified();
35899
+ const updated = await this.getMessage(id);
35900
+ this.emit(archived ? "message:archived" : "message:unarchived", updated);
35901
+ return updated;
35902
+ }
35779
35903
  /**
35780
35904
  * Delete a message by ID.
35781
35905
  * @param id - The message ID
@@ -35866,7 +35990,7 @@ var init_message_store = __esm({
35866
35990
  (${participantAFromPredicate} AND fromType = ? AND ${participantBToPredicate} AND toType = ?)
35867
35991
  OR
35868
35992
  (${participantBFromPredicate} AND fromType = ? AND ${participantAToPredicate} AND toType = ?)
35869
- )
35993
+ ) AND ${options?.archived === true ? "archived = 1" : "(archived = 0 OR archived IS NULL)"}
35870
35994
  ORDER BY createdAt DESC
35871
35995
  LIMIT ?
35872
35996
  `).all(
@@ -35901,11 +36025,11 @@ var init_message_store = __esm({
35901
36025
  const participantIds = this.getParticipantIdsForLookup(ownerId, ownerType);
35902
36026
  const toIdPredicate = participantIds.length === 1 ? "toId = ?" : `toId IN (${participantIds.map(() => "?").join(", ")})`;
35903
36027
  const unreadRow = this.db.prepare(`
35904
- SELECT COUNT(*) as count FROM messages WHERE ${toIdPredicate} AND toType = ? AND read = 0
36028
+ SELECT COUNT(*) as count FROM messages WHERE ${toIdPredicate} AND toType = ? AND read = 0 AND (archived = 0 OR archived IS NULL)
35905
36029
  `).get(...participantIds, ownerType);
35906
36030
  const unreadCount = unreadRow?.count ?? 0;
35907
36031
  const lastRow = this.db.prepare(`
35908
- SELECT * FROM messages WHERE ${toIdPredicate} AND toType = ? ORDER BY createdAt DESC, rowid DESC LIMIT 1
36032
+ SELECT * FROM messages WHERE ${toIdPredicate} AND toType = ? AND (archived = 0 OR archived IS NULL) ORDER BY createdAt DESC, rowid DESC LIMIT 1
35909
36033
  `).get(...participantIds, ownerType);
35910
36034
  const lastMessage = lastRow ? this.rowToMessage(lastRow) : void 0;
35911
36035
  return {
@@ -35919,13 +36043,13 @@ var init_message_store = __esm({
35919
36043
  * Get all agent-to-agent messages across all agents.
35920
36044
  * @returns Array of messages (newest first)
35921
36045
  */
35922
- async getAllAgentToAgentMessages() {
36046
+ async getAllAgentToAgentMessages(filter) {
35923
36047
  if (this.asyncLayer) {
35924
- return getAllAgentToAgentMessages(this.asyncLayer.db);
36048
+ return getAllAgentToAgentMessages(this.asyncLayer.db, filter);
35925
36049
  }
35926
36050
  const rows = this.db.prepare(`
35927
36051
  SELECT * FROM messages
35928
- WHERE type = ?
36052
+ WHERE type = ? AND ${filter?.archived === true ? "archived = 1" : "(archived = 0 OR archived IS NULL)"}
35929
36053
  ORDER BY createdAt DESC, rowid DESC
35930
36054
  `).all("agent-to-agent");
35931
36055
  return rows.map((row) => this.rowToMessage(row));
@@ -35939,7 +36063,7 @@ var init_message_store = __esm({
35939
36063
  }
35940
36064
  const row = this.db.prepare(`
35941
36065
  SELECT COUNT(*) as count FROM messages
35942
- WHERE type = ? AND read = 0
36066
+ WHERE type = ? AND read = 0 AND (archived = 0 OR archived IS NULL)
35943
36067
  `).get("agent-to-agent");
35944
36068
  return row?.count ?? 0;
35945
36069
  }
@@ -36038,6 +36162,7 @@ async function createApprovalRequest(layer, input) {
36038
36162
  };
36039
36163
  await layer.transactionImmediate(async (tx) => {
36040
36164
  await tx.insert(project_exports.approvalRequests).values({
36165
+ ...layer.projectId?.trim() ? { projectId: layer.projectId } : {},
36041
36166
  id: request.id,
36042
36167
  status: request.status,
36043
36168
  requesterActorId: request.requester.actorId,
@@ -36061,12 +36186,12 @@ async function createApprovalRequest(layer, input) {
36061
36186
  });
36062
36187
  return request;
36063
36188
  }
36064
- async function getApprovalRequest(handle, id) {
36065
- const rows = await handle.select().from(project_exports.approvalRequests).where(eq(project_exports.approvalRequests.id, id));
36189
+ async function getApprovalRequest(handle, id, projectId2) {
36190
+ const rows = await handle.select().from(project_exports.approvalRequests).where(and(eq(project_exports.approvalRequests.id, id), projectScopeFor(project_exports.approvalRequests.projectId, projectId2)));
36066
36191
  return rows[0] ? rowToRequest(rows[0]) : null;
36067
36192
  }
36068
- async function listApprovalRequests(handle, input = {}) {
36069
- const conditions = [];
36193
+ async function listApprovalRequests(handle, input = {}, projectId2) {
36194
+ const conditions = [projectScopeFor(project_exports.approvalRequests.projectId, projectId2)];
36070
36195
  if (input.status) conditions.push(eq(project_exports.approvalRequests.status, input.status));
36071
36196
  if (input.requesterActorId) conditions.push(eq(project_exports.approvalRequests.requesterActorId, input.requesterActorId));
36072
36197
  if (input.taskId) conditions.push(eq(project_exports.approvalRequests.taskId, input.taskId));
@@ -36080,7 +36205,7 @@ async function listApprovalRequests(handle, input = {}) {
36080
36205
  async function decideApprovalRequest(layer, requestId, status, input) {
36081
36206
  const now = (/* @__PURE__ */ new Date()).toISOString();
36082
36207
  return layer.transactionImmediate(async (tx) => {
36083
- const existing = await getApprovalRequest(tx, requestId);
36208
+ const existing = await getApprovalRequest(tx, requestId, layer.projectId);
36084
36209
  if (!existing) throw new Error(`Approval request ${requestId} not found`);
36085
36210
  if (!isValidApprovalRequestTransition(existing.status, status)) {
36086
36211
  throw new Error(`Invalid approval request transition: ${existing.status} -> ${status}`);
@@ -36091,23 +36216,24 @@ async function decideApprovalRequest(layer, requestId, status, input) {
36091
36216
  const updatedRows = await tx.update(project_exports.approvalRequests).set({ status, decidedAt: now, updatedAt: now }).where(
36092
36217
  and(
36093
36218
  eq(project_exports.approvalRequests.id, requestId),
36094
- eq(project_exports.approvalRequests.status, existing.status)
36219
+ eq(project_exports.approvalRequests.status, existing.status),
36220
+ projectScopeFor(project_exports.approvalRequests.projectId, layer.projectId)
36095
36221
  )
36096
36222
  ).returning({ id: project_exports.approvalRequests.id });
36097
36223
  if (updatedRows.length === 0) {
36098
- const raced = await getApprovalRequest(tx, requestId);
36224
+ const raced = await getApprovalRequest(tx, requestId, layer.projectId);
36099
36225
  throw new Error(
36100
36226
  `Invalid approval request transition: ${raced?.status ?? existing.status} -> ${status}`
36101
36227
  );
36102
36228
  }
36103
36229
  await appendAuditEvent(tx, layer.projectId ?? "", requestId, status, input.actor, now, input.note);
36104
- return await getApprovalRequest(tx, requestId);
36230
+ return await getApprovalRequest(tx, requestId, layer.projectId);
36105
36231
  });
36106
36232
  }
36107
36233
  async function markApprovalRequestCompleted(layer, requestId, input) {
36108
36234
  const now = (/* @__PURE__ */ new Date()).toISOString();
36109
36235
  return layer.transactionImmediate(async (tx) => {
36110
- const existing = await getApprovalRequest(tx, requestId);
36236
+ const existing = await getApprovalRequest(tx, requestId, layer.projectId);
36111
36237
  if (!existing) throw new Error(`Approval request ${requestId} not found`);
36112
36238
  if (!isValidApprovalRequestTransition(existing.status, "completed")) {
36113
36239
  throw new Error(`Invalid approval request transition: ${existing.status} -> completed`);
@@ -36121,21 +36247,22 @@ async function markApprovalRequestCompleted(layer, requestId, input) {
36121
36247
  const updatedRows = await tx.update(project_exports.approvalRequests).set({ status: "completed", completedAt: now, updatedAt: now }).where(
36122
36248
  and(
36123
36249
  eq(project_exports.approvalRequests.id, requestId),
36124
- eq(project_exports.approvalRequests.status, existing.status)
36250
+ eq(project_exports.approvalRequests.status, existing.status),
36251
+ projectScopeFor(project_exports.approvalRequests.projectId, layer.projectId)
36125
36252
  )
36126
36253
  ).returning({ id: project_exports.approvalRequests.id });
36127
36254
  if (updatedRows.length === 0) {
36128
- const raced = await getApprovalRequest(tx, requestId);
36255
+ const raced = await getApprovalRequest(tx, requestId, layer.projectId);
36129
36256
  throw new Error(
36130
36257
  `Invalid approval request transition: ${raced?.status ?? existing.status} -> completed`
36131
36258
  );
36132
36259
  }
36133
36260
  await appendAuditEvent(tx, layer.projectId ?? "", requestId, "completed", input.actor, now, input.note);
36134
- return await getApprovalRequest(tx, requestId);
36261
+ return await getApprovalRequest(tx, requestId, layer.projectId);
36135
36262
  });
36136
36263
  }
36137
- async function getApprovalAuditHistory(handle, requestId) {
36138
- const rows = await handle.select().from(project_exports.approvalRequestAuditEvents).where(eq(project_exports.approvalRequestAuditEvents.requestId, requestId)).orderBy(
36264
+ async function getApprovalAuditHistory(handle, requestId, projectId2) {
36265
+ const rows = await handle.select().from(project_exports.approvalRequestAuditEvents).where(and(eq(project_exports.approvalRequestAuditEvents.requestId, requestId), projectScopeFor(project_exports.approvalRequestAuditEvents.projectId, projectId2))).orderBy(
36139
36266
  sql`${project_exports.approvalRequestAuditEvents.createdAt} ASC, ${project_exports.approvalRequestAuditEvents.id} ASC`
36140
36267
  );
36141
36268
  return rows.map((row) => rowToAuditEvent(row));
@@ -36145,6 +36272,7 @@ var init_async_approval_request_store = __esm({
36145
36272
  "use strict";
36146
36273
  init_drizzle_orm();
36147
36274
  init_schema2();
36275
+ init_data_layer();
36148
36276
  init_agents();
36149
36277
  init_types();
36150
36278
  }
@@ -36158,6 +36286,7 @@ var init_approval_request_store = __esm({
36158
36286
  "use strict";
36159
36287
  init_drizzle_orm();
36160
36288
  init_db2();
36289
+ init_data_layer();
36161
36290
  init_async_approval_request_store();
36162
36291
  init_schema2();
36163
36292
  init_async_agent_activity();
@@ -36286,23 +36415,26 @@ var init_approval_request_store = __esm({
36286
36415
  return created;
36287
36416
  }
36288
36417
  async get(id) {
36289
- return getApprovalRequest(this.asyncLayer.db, id);
36418
+ return getApprovalRequest(this.asyncLayer.db, id, this.asyncLayer.projectId);
36290
36419
  }
36291
36420
  async list(input = {}) {
36292
- return listApprovalRequests(this.asyncLayer.db, input);
36421
+ return listApprovalRequests(this.asyncLayer.db, input, this.asyncLayer.projectId);
36293
36422
  }
36294
36423
  async getPendingCountsByActor() {
36295
36424
  const table = project_exports.approvalRequests;
36296
36425
  const rows = await this.asyncLayer.db.select({
36297
36426
  actorId: table.requesterActorId,
36298
36427
  requestCount: count()
36299
- }).from(table).where(eq(table.status, "pending")).groupBy(table.requesterActorId);
36428
+ }).from(table).where(and(eq(table.status, "pending"), projectScopeFor(table.projectId, this.asyncLayer.projectId))).groupBy(table.requesterActorId);
36300
36429
  return new Map(rows.map((row) => [row.actorId, Number(row.requestCount)]));
36301
36430
  }
36302
36431
  async findLatestByDedupeKey(input) {
36303
36432
  if (this.backendMode) {
36304
36433
  const table = project_exports.approvalRequests;
36305
- const conditions = [eq(table.requesterActorId, input.requesterActorId)];
36434
+ const conditions = [
36435
+ eq(table.requesterActorId, input.requesterActorId),
36436
+ projectScopeFor(table.projectId, this.asyncLayer.projectId)
36437
+ ];
36306
36438
  if (input.taskId !== void 0) {
36307
36439
  conditions.push(eq(table.taskId, input.taskId));
36308
36440
  }
@@ -36341,7 +36473,7 @@ var init_approval_request_store = __esm({
36341
36473
  return markApprovalRequestCompleted(this.asyncLayer, requestId, input);
36342
36474
  }
36343
36475
  async getAuditHistory(requestId) {
36344
- return getApprovalAuditHistory(this.asyncLayer.db, requestId);
36476
+ return getApprovalAuditHistory(this.asyncLayer.db, requestId, this.asyncLayer.projectId);
36345
36477
  }
36346
36478
  };
36347
36479
  }
@@ -40527,6 +40659,8 @@ async function applySchemaBaseline(db, options = {}) {
40527
40659
  const agentRatingProjectIsolationAlreadyApplied = applied.includes(AGENT_RATING_PROJECT_ISOLATION_VERSION);
40528
40660
  const agentRatingsProjectPartitionAlreadyApplied = applied.includes(AGENT_RATINGS_PROJECT_PARTITION_VERSION);
40529
40661
  const projectOwnershipDeclarationDriftAlreadyApplied = applied.includes(PROJECT_OWNERSHIP_DECLARATION_DRIFT_VERSION);
40662
+ const projectOwnershipDefaultReconciliationAlreadyApplied = applied.includes(PROJECT_OWNERSHIP_DEFAULT_RECONCILIATION_VERSION);
40663
+ const messageArchiveSchemaAlreadyApplied = applied.includes(MESSAGE_ARCHIVE_SCHEMA_VERSION);
40530
40664
  assertBinaryNotOlderThanDatabase(applied);
40531
40665
  let schemaChanged = false;
40532
40666
  if (!baselineAlreadyApplied) {
@@ -41010,17 +41144,29 @@ async function applySchemaBaseline(db, options = {}) {
41010
41144
  await tx.execute(sql`INSERT INTO public.${sql.identifier(MIGRATION_BOOKKEEPING_TABLE)} (version) VALUES (${PROJECT_OWNERSHIP_DECLARATION_DRIFT_VERSION}) ON CONFLICT (version) DO NOTHING`);
41011
41145
  schemaChanged = true;
41012
41146
  }
41147
+ if (!projectOwnershipDefaultReconciliationAlreadyApplied) {
41148
+ const migrationSql = await readFile4(PROJECT_OWNERSHIP_DEFAULT_RECONCILIATION_MIGRATION_PATH, "utf8");
41149
+ await tx.execute(sql.raw(migrationSql));
41150
+ await tx.execute(sql`INSERT INTO public.${sql.identifier(MIGRATION_BOOKKEEPING_TABLE)} (version) VALUES (${PROJECT_OWNERSHIP_DEFAULT_RECONCILIATION_VERSION}) ON CONFLICT (version) DO NOTHING`);
41151
+ schemaChanged = true;
41152
+ }
41153
+ if (!messageArchiveSchemaAlreadyApplied) {
41154
+ const migrationSql = await readFile4(MESSAGE_ARCHIVE_SCHEMA_MIGRATION_PATH, "utf8");
41155
+ await tx.execute(sql.raw(migrationSql));
41156
+ await tx.execute(sql`INSERT INTO public.${sql.identifier(MIGRATION_BOOKKEEPING_TABLE)} (version) VALUES (${MESSAGE_ARCHIVE_SCHEMA_VERSION}) ON CONFLICT (version) DO NOTHING`);
41157
+ schemaChanged = true;
41158
+ }
41013
41159
  return { applied: schemaChanged, pluginHooksRun: pluginHooks.length };
41014
41160
  });
41015
41161
  }
41016
- var SCHEMA_BASELINE_VERSION, TASK_DECLARED_SYMBOLS_VERSION, INITIAL_SCHEMA_VERSION, AUTOMATION_ISOLATION_SCHEMA_VERSION, ANALYTICS_ISOLATION_SCHEMA_VERSION, MONITOR_APPROVAL_ISOLATION_SCHEMA_VERSION, LEGACY_CUTOVER_PRESERVATION_SCHEMA_VERSION, MULTI_PROJECT_CUTOVER_SCHEMA_VERSION, PROJECT_OWNERSHIP_SCHEMA_VERSION, SQLITE_SCHEMA_PARITY_VERSION, SESSION_ADVISOR_ENABLED_SCHEMA_VERSION, MISSION_FIX_IDEMPOTENCY_VERSION, IMPORT_TRANSLATION_CACHE_VERSION, IMPORT_TRANSLATION_CACHE_SCOPE_FIX_VERSION, IMPORT_TRANSLATION_CACHE_LEGACY_PARTITION_BACKFILL_VERSION, OWNER_PROJECT_ID_SPLIT_VERSION, CHAT_SESSION_PINS_VERSION, EXECUTOR_TOOL_FAILURE_RETRY_VERSION, EXECUTOR_ESCALATION_ATTEMPT_VERSION, GLOBAL_ROUTINES_SCHEMA_VERSION, TASK_MERGER_MODEL_LANE_VERSION, BULK_COMPLETION_REFUSAL_AT_VERSION, TASK_PROPOSAL_CLAIM_VERSION, CONFIGURATION_REVISIONS_VERSION, IDEATION_SCHEMA_VERSION, RESEARCH_FEATURE_PROVENANCE_VERSION, TASK_VERIFICATION_REQUEST_VERSION, SYMBOL_LOCKS_SCHEMA_VERSION, BIGINT_COUNTERS_VERSION, PLANNING_ACTIVE_TIMING_VERSION, SQLITE_MIGRATION_RUNTIME_READ_VERSION, WORKFLOW_TASK_CONTINUATIONS_VERSION, LEGACY_ADOPTION_DRAINED_MARKER_RUNTIME_GRANTS_VERSION, TASK_WEDGE_NOTIFICATION_VERSION, MILESTONE_ASSERTION_PROVENANCE_VERSION, MISSION_LINEAGE_STOP_VERSION, CHAT_SESSION_TAGS_VERSION, DROP_GLOBAL_CONCURRENCY_VERSION, MISSION_TASK_PREFIX_VERSION, CREDENTIAL_INSTANCE_SELECTION_VERSION, TASK_LIFECYCLE_OUTBOX_VERSION, TASK_LIFECYCLE_CONSUMERS_VERSION, VALIDATOR_INPUT_FINGERPRINT_VERSION, UNPLANNED_EXECUTION_BLOCK_DEDUPE_VERSION, QUEUED_EPISODE_SIGNATURE_VERSION, MULTI_ROLE_WORKFLOW_AGENTS_VERSION, WORKFLOW_PRINCIPAL_FENCE_VERSION, TASK_RECOMMENDATIONS_VERSION, GITHUB_CHECK_STATES_VERSION, AGENT_ACTIVITY_EVENTS_VERSION, SPEC_LOCK_DRIFT_REPORT_VERSION, SPEC_LOCK_SOURCE_REVISION_BIGINT_VERSION, MEMORY_RECALL_RECORDS_VERSION, MISSION_FEATURE_SPEC_ALIGNMENT_VERSION, AGENT_RATING_PROJECT_ISOLATION_VERSION, AGENT_RATINGS_PROJECT_PARTITION_VERSION, PROJECT_OWNERSHIP_DECLARATION_DRIFT_VERSION, LEGACY_ADOPTION_DRAINED_MARKER_FUNCTION, StaleBinarySchemaError, MIGRATION_BOOKKEEPING_TABLE, LEGACY_ADOPTION_DRAINED_MARKER, __dirname, MIGRATIONS_DIR, BASELINE_MIGRATION_PATH, AUTOMATION_ISOLATION_MIGRATION_PATH, ANALYTICS_ISOLATION_MIGRATION_PATH, MONITOR_APPROVAL_ISOLATION_MIGRATION_PATH, LEGACY_CUTOVER_PRESERVATION_MIGRATION_PATH, MULTI_PROJECT_CUTOVER_MIGRATION_PATH, PROJECT_OWNERSHIP_MIGRATION_PATH, SQLITE_SCHEMA_PARITY_MIGRATION_PATH, SESSION_ADVISOR_ENABLED_MIGRATION_PATH, MISSION_FIX_IDEMPOTENCY_MIGRATION_PATH, IMPORT_TRANSLATION_CACHE_MIGRATION_PATH, IMPORT_TRANSLATION_CACHE_SCOPE_FIX_MIGRATION_PATH, IMPORT_TRANSLATION_CACHE_LEGACY_PARTITION_BACKFILL_MIGRATION_PATH, OWNER_PROJECT_ID_SPLIT_MIGRATION_PATH, CHAT_SESSION_PINS_MIGRATION_PATH, EXECUTOR_TOOL_FAILURE_RETRY_MIGRATION_PATH, EXECUTOR_ESCALATION_ATTEMPT_MIGRATION_PATH, GLOBAL_ROUTINES_MIGRATION_PATH, TASK_MERGER_MODEL_LANE_MIGRATION_PATH, BULK_COMPLETION_REFUSAL_AT_MIGRATION_PATH, TASK_PROPOSAL_CLAIM_MIGRATION_PATH, CONFIGURATION_REVISIONS_MIGRATION_PATH, IDEATION_MIGRATION_PATH, RESEARCH_FEATURE_PROVENANCE_MIGRATION_PATH, TASK_VERIFICATION_REQUEST_MIGRATION_PATH, SYMBOL_LOCKS_MIGRATION_PATH, BIGINT_COUNTERS_MIGRATION_PATH, WORKFLOW_IR_PIN_AND_LEGACY_ADOPTION_VERSION, WORKFLOW_IR_PIN_AND_LEGACY_ADOPTION_MIGRATION_PATH, PLANNING_ACTIVE_TIMING_MIGRATION_PATH, TASK_DECLARED_SYMBOLS_MIGRATION_PATH, SQLITE_MIGRATION_RUNTIME_READ_PATH, WORKFLOW_TASK_CONTINUATIONS_PATH, LEGACY_ADOPTION_DRAINED_MARKER_RUNTIME_GRANTS_PATH, TASK_WEDGE_NOTIFICATION_MIGRATION_PATH, MILESTONE_ASSERTION_PROVENANCE_MIGRATION_PATH, MISSION_LINEAGE_STOP_MIGRATION_PATH, CHAT_SESSION_TAGS_MIGRATION_PATH, DROP_GLOBAL_CONCURRENCY_MIGRATION_PATH, MISSION_TASK_PREFIX_MIGRATION_PATH, CREDENTIAL_INSTANCE_SELECTION_MIGRATION_PATH, TASK_LIFECYCLE_OUTBOX_MIGRATION_PATH, TASK_LIFECYCLE_CONSUMERS_MIGRATION_PATH, VALIDATOR_INPUT_FINGERPRINT_MIGRATION_PATH, UNPLANNED_EXECUTION_BLOCK_DEDUPE_MIGRATION_PATH, QUEUED_EPISODE_SIGNATURE_MIGRATION_PATH, MULTI_ROLE_WORKFLOW_AGENTS_MIGRATION_PATH, WORKFLOW_PRINCIPAL_FENCE_MIGRATION_PATH, TASK_RECOMMENDATIONS_MIGRATION_PATH, GITHUB_CHECK_STATES_MIGRATION_PATH, AGENT_ACTIVITY_EVENTS_MIGRATION_PATH, SPEC_LOCK_DRIFT_REPORT_MIGRATION_PATH, SPEC_LOCK_SOURCE_REVISION_BIGINT_MIGRATION_PATH, MEMORY_RECALL_RECORDS_MIGRATION_PATH, MISSION_FEATURE_SPEC_ALIGNMENT_MIGRATION_PATH, AGENT_RATING_PROJECT_ISOLATION_MIGRATION_PATH, AGENT_RATINGS_PROJECT_PARTITION_MIGRATION_PATH, PROJECT_OWNERSHIP_DECLARATION_DRIFT_MIGRATION_PATH;
41162
+ var SCHEMA_BASELINE_VERSION, TASK_DECLARED_SYMBOLS_VERSION, INITIAL_SCHEMA_VERSION, AUTOMATION_ISOLATION_SCHEMA_VERSION, ANALYTICS_ISOLATION_SCHEMA_VERSION, MONITOR_APPROVAL_ISOLATION_SCHEMA_VERSION, LEGACY_CUTOVER_PRESERVATION_SCHEMA_VERSION, MULTI_PROJECT_CUTOVER_SCHEMA_VERSION, PROJECT_OWNERSHIP_SCHEMA_VERSION, SQLITE_SCHEMA_PARITY_VERSION, SESSION_ADVISOR_ENABLED_SCHEMA_VERSION, MISSION_FIX_IDEMPOTENCY_VERSION, IMPORT_TRANSLATION_CACHE_VERSION, IMPORT_TRANSLATION_CACHE_SCOPE_FIX_VERSION, IMPORT_TRANSLATION_CACHE_LEGACY_PARTITION_BACKFILL_VERSION, OWNER_PROJECT_ID_SPLIT_VERSION, CHAT_SESSION_PINS_VERSION, EXECUTOR_TOOL_FAILURE_RETRY_VERSION, EXECUTOR_ESCALATION_ATTEMPT_VERSION, GLOBAL_ROUTINES_SCHEMA_VERSION, TASK_MERGER_MODEL_LANE_VERSION, BULK_COMPLETION_REFUSAL_AT_VERSION, TASK_PROPOSAL_CLAIM_VERSION, CONFIGURATION_REVISIONS_VERSION, IDEATION_SCHEMA_VERSION, RESEARCH_FEATURE_PROVENANCE_VERSION, TASK_VERIFICATION_REQUEST_VERSION, SYMBOL_LOCKS_SCHEMA_VERSION, BIGINT_COUNTERS_VERSION, PLANNING_ACTIVE_TIMING_VERSION, SQLITE_MIGRATION_RUNTIME_READ_VERSION, WORKFLOW_TASK_CONTINUATIONS_VERSION, LEGACY_ADOPTION_DRAINED_MARKER_RUNTIME_GRANTS_VERSION, TASK_WEDGE_NOTIFICATION_VERSION, MILESTONE_ASSERTION_PROVENANCE_VERSION, MISSION_LINEAGE_STOP_VERSION, CHAT_SESSION_TAGS_VERSION, DROP_GLOBAL_CONCURRENCY_VERSION, MISSION_TASK_PREFIX_VERSION, CREDENTIAL_INSTANCE_SELECTION_VERSION, TASK_LIFECYCLE_OUTBOX_VERSION, TASK_LIFECYCLE_CONSUMERS_VERSION, VALIDATOR_INPUT_FINGERPRINT_VERSION, UNPLANNED_EXECUTION_BLOCK_DEDUPE_VERSION, QUEUED_EPISODE_SIGNATURE_VERSION, MULTI_ROLE_WORKFLOW_AGENTS_VERSION, WORKFLOW_PRINCIPAL_FENCE_VERSION, TASK_RECOMMENDATIONS_VERSION, GITHUB_CHECK_STATES_VERSION, AGENT_ACTIVITY_EVENTS_VERSION, SPEC_LOCK_DRIFT_REPORT_VERSION, SPEC_LOCK_SOURCE_REVISION_BIGINT_VERSION, MEMORY_RECALL_RECORDS_VERSION, MISSION_FEATURE_SPEC_ALIGNMENT_VERSION, AGENT_RATING_PROJECT_ISOLATION_VERSION, AGENT_RATINGS_PROJECT_PARTITION_VERSION, PROJECT_OWNERSHIP_DECLARATION_DRIFT_VERSION, PROJECT_OWNERSHIP_DEFAULT_RECONCILIATION_VERSION, MESSAGE_ARCHIVE_SCHEMA_VERSION, LEGACY_ADOPTION_DRAINED_MARKER_FUNCTION, StaleBinarySchemaError, MIGRATION_BOOKKEEPING_TABLE, LEGACY_ADOPTION_DRAINED_MARKER, __dirname, MIGRATIONS_DIR, BASELINE_MIGRATION_PATH, AUTOMATION_ISOLATION_MIGRATION_PATH, ANALYTICS_ISOLATION_MIGRATION_PATH, MONITOR_APPROVAL_ISOLATION_MIGRATION_PATH, LEGACY_CUTOVER_PRESERVATION_MIGRATION_PATH, MULTI_PROJECT_CUTOVER_MIGRATION_PATH, PROJECT_OWNERSHIP_MIGRATION_PATH, SQLITE_SCHEMA_PARITY_MIGRATION_PATH, SESSION_ADVISOR_ENABLED_MIGRATION_PATH, MISSION_FIX_IDEMPOTENCY_MIGRATION_PATH, IMPORT_TRANSLATION_CACHE_MIGRATION_PATH, IMPORT_TRANSLATION_CACHE_SCOPE_FIX_MIGRATION_PATH, IMPORT_TRANSLATION_CACHE_LEGACY_PARTITION_BACKFILL_MIGRATION_PATH, OWNER_PROJECT_ID_SPLIT_MIGRATION_PATH, CHAT_SESSION_PINS_MIGRATION_PATH, EXECUTOR_TOOL_FAILURE_RETRY_MIGRATION_PATH, EXECUTOR_ESCALATION_ATTEMPT_MIGRATION_PATH, GLOBAL_ROUTINES_MIGRATION_PATH, TASK_MERGER_MODEL_LANE_MIGRATION_PATH, BULK_COMPLETION_REFUSAL_AT_MIGRATION_PATH, TASK_PROPOSAL_CLAIM_MIGRATION_PATH, CONFIGURATION_REVISIONS_MIGRATION_PATH, IDEATION_MIGRATION_PATH, RESEARCH_FEATURE_PROVENANCE_MIGRATION_PATH, TASK_VERIFICATION_REQUEST_MIGRATION_PATH, SYMBOL_LOCKS_MIGRATION_PATH, BIGINT_COUNTERS_MIGRATION_PATH, WORKFLOW_IR_PIN_AND_LEGACY_ADOPTION_VERSION, WORKFLOW_IR_PIN_AND_LEGACY_ADOPTION_MIGRATION_PATH, PLANNING_ACTIVE_TIMING_MIGRATION_PATH, TASK_DECLARED_SYMBOLS_MIGRATION_PATH, SQLITE_MIGRATION_RUNTIME_READ_PATH, WORKFLOW_TASK_CONTINUATIONS_PATH, LEGACY_ADOPTION_DRAINED_MARKER_RUNTIME_GRANTS_PATH, TASK_WEDGE_NOTIFICATION_MIGRATION_PATH, MILESTONE_ASSERTION_PROVENANCE_MIGRATION_PATH, MISSION_LINEAGE_STOP_MIGRATION_PATH, CHAT_SESSION_TAGS_MIGRATION_PATH, DROP_GLOBAL_CONCURRENCY_MIGRATION_PATH, MISSION_TASK_PREFIX_MIGRATION_PATH, CREDENTIAL_INSTANCE_SELECTION_MIGRATION_PATH, TASK_LIFECYCLE_OUTBOX_MIGRATION_PATH, TASK_LIFECYCLE_CONSUMERS_MIGRATION_PATH, VALIDATOR_INPUT_FINGERPRINT_MIGRATION_PATH, UNPLANNED_EXECUTION_BLOCK_DEDUPE_MIGRATION_PATH, QUEUED_EPISODE_SIGNATURE_MIGRATION_PATH, MULTI_ROLE_WORKFLOW_AGENTS_MIGRATION_PATH, WORKFLOW_PRINCIPAL_FENCE_MIGRATION_PATH, TASK_RECOMMENDATIONS_MIGRATION_PATH, GITHUB_CHECK_STATES_MIGRATION_PATH, AGENT_ACTIVITY_EVENTS_MIGRATION_PATH, SPEC_LOCK_DRIFT_REPORT_MIGRATION_PATH, SPEC_LOCK_SOURCE_REVISION_BIGINT_MIGRATION_PATH, MEMORY_RECALL_RECORDS_MIGRATION_PATH, MISSION_FEATURE_SPEC_ALIGNMENT_MIGRATION_PATH, AGENT_RATING_PROJECT_ISOLATION_MIGRATION_PATH, AGENT_RATINGS_PROJECT_PARTITION_MIGRATION_PATH, PROJECT_OWNERSHIP_DECLARATION_DRIFT_MIGRATION_PATH, PROJECT_OWNERSHIP_DEFAULT_RECONCILIATION_MIGRATION_PATH, MESSAGE_ARCHIVE_SCHEMA_MIGRATION_PATH;
41017
41163
  var init_schema_applier = __esm({
41018
41164
  "../core/src/postgres/schema-applier.ts"() {
41019
41165
  "use strict";
41020
41166
  init_drizzle_orm();
41021
41167
  init_plugin_schema_hook();
41022
41168
  init_advisory_locks();
41023
- SCHEMA_BASELINE_VERSION = "0056";
41169
+ SCHEMA_BASELINE_VERSION = "0058";
41024
41170
  TASK_DECLARED_SYMBOLS_VERSION = "0028";
41025
41171
  INITIAL_SCHEMA_VERSION = "0000";
41026
41172
  AUTOMATION_ISOLATION_SCHEMA_VERSION = "0001";
@@ -41077,6 +41223,8 @@ var init_schema_applier = __esm({
41077
41223
  AGENT_RATING_PROJECT_ISOLATION_VERSION = "0054";
41078
41224
  AGENT_RATINGS_PROJECT_PARTITION_VERSION = "0055";
41079
41225
  PROJECT_OWNERSHIP_DECLARATION_DRIFT_VERSION = "0056";
41226
+ PROJECT_OWNERSHIP_DEFAULT_RECONCILIATION_VERSION = "0057";
41227
+ MESSAGE_ARCHIVE_SCHEMA_VERSION = "0058";
41080
41228
  LEGACY_ADOPTION_DRAINED_MARKER_FUNCTION = "fusion_mark_legacy_adoption_drained";
41081
41229
  StaleBinarySchemaError = class extends Error {
41082
41230
  constructor(databaseVersion, binaryVersion) {
@@ -41213,6 +41361,8 @@ var init_schema_applier = __esm({
41213
41361
  AGENT_RATING_PROJECT_ISOLATION_MIGRATION_PATH = join8(MIGRATIONS_DIR, "0054_fn_8957_agent_rating_project_isolation.sql");
41214
41362
  AGENT_RATINGS_PROJECT_PARTITION_MIGRATION_PATH = join8(MIGRATIONS_DIR, "0055_fn_8988_agent_ratings_project_partition.sql");
41215
41363
  PROJECT_OWNERSHIP_DECLARATION_DRIFT_MIGRATION_PATH = join8(MIGRATIONS_DIR, "0056_fn_8997_project_ownership_declaration_drift.sql");
41364
+ PROJECT_OWNERSHIP_DEFAULT_RECONCILIATION_MIGRATION_PATH = join8(MIGRATIONS_DIR, "0057_fn_9004_project_ownership_default_reconciliation.sql");
41365
+ MESSAGE_ARCHIVE_SCHEMA_MIGRATION_PATH = join8(MIGRATIONS_DIR, "0058_fn_9014_message_archive.sql");
41216
41366
  }
41217
41367
  });
41218
41368
 
@@ -68745,8 +68895,10 @@ function safeJsonParse(value) {
68745
68895
  return null;
68746
68896
  }
68747
68897
  }
68748
- async function queryRunAuditEvents(db, filter = {}) {
68749
- const conditions = [];
68898
+ async function queryRunAuditEvents(db, filter = {}, projectId2) {
68899
+ const conditions = [projectScopeFor(project_exports.runAuditEvents.projectId, projectId2)].filter(
68900
+ (condition) => condition !== void 0
68901
+ );
68750
68902
  if (filter.runId) {
68751
68903
  conditions.push(eq(project_exports.runAuditEvents.runId, filter.runId));
68752
68904
  }
@@ -68892,6 +69044,7 @@ var init_async_audit = __esm({
68892
69044
  init_drizzle_orm();
68893
69045
  init_schema2();
68894
69046
  init_data_layer();
69047
+ init_data_layer();
68895
69048
  LEGACY_REVIEW_LANES3 = ["in-review"];
68896
69049
  LEGACY_COMPLETE_LANES = ["done"];
68897
69050
  }
@@ -69281,7 +69434,10 @@ async function insertArtifactRow(layer, input, stored, archivedColumns) {
69281
69434
  createdAt: now,
69282
69435
  updatedAt: now
69283
69436
  });
69284
- const rows = await tx.select().from(project_exports.artifacts).where(eq(project_exports.artifacts.id, id)).limit(1);
69437
+ const rows = await tx.select().from(project_exports.artifacts).where(and(
69438
+ eq(project_exports.artifacts.id, id),
69439
+ projectScopeFor(project_exports.artifacts.projectId, layer.projectId)
69440
+ )).limit(1);
69285
69441
  const row = rows[0];
69286
69442
  if (!row) throw new Error(`Failed to register artifact ${id}`);
69287
69443
  return rowToArtifact2(row);
@@ -69289,7 +69445,7 @@ async function insertArtifactRow(layer, input, stored, archivedColumns) {
69289
69445
  }
69290
69446
  async function updateArtifactRow(layer, id, updates, archivedColumns) {
69291
69447
  return layer.transactionImmediate(async (tx) => {
69292
- const existing = await getArtifact(tx, id);
69448
+ const existing = await getArtifact(tx, id, layer.projectId);
69293
69449
  if (!existing) {
69294
69450
  throw new Error(`Artifact ${id} not found`);
69295
69451
  }
@@ -69309,29 +69465,38 @@ async function updateArtifactRow(layer, id, updates, archivedColumns) {
69309
69465
  description: updates.description !== void 0 ? updates.description : existing.description ?? null,
69310
69466
  content: updates.content !== void 0 ? updates.content : existing.content ?? null,
69311
69467
  updatedAt: now
69312
- }).where(eq(project_exports.artifacts.id, id));
69313
- const updated = await getArtifact(tx, id);
69468
+ }).where(and(
69469
+ eq(project_exports.artifacts.id, id),
69470
+ projectScopeFor(project_exports.artifacts.projectId, layer.projectId)
69471
+ ));
69472
+ const updated = await getArtifact(tx, id, layer.projectId);
69314
69473
  if (!updated) {
69315
69474
  throw new Error(`Failed to update artifact ${id}`);
69316
69475
  }
69317
69476
  return updated;
69318
69477
  });
69319
69478
  }
69320
- async function getArtifact(db, id) {
69321
- const rows = await db.select().from(project_exports.artifacts).where(eq(project_exports.artifacts.id, id)).limit(1);
69479
+ async function getArtifact(db, id, projectId2) {
69480
+ const rows = await db.select().from(project_exports.artifacts).where(and(
69481
+ eq(project_exports.artifacts.id, id),
69482
+ projectScopeFor(project_exports.artifacts.projectId, projectId2)
69483
+ )).limit(1);
69322
69484
  const row = rows[0];
69323
69485
  return row ? rowToArtifact2(row) : null;
69324
69486
  }
69325
69487
  async function getArtifacts(db, taskId, projectId2, archivedColumns) {
69326
69488
  const column = await getLiveTaskColumn(db, taskId, projectId2, archivedColumns);
69327
69489
  if (column === null || column === "archived") return [];
69328
- const rows = await db.select().from(project_exports.artifacts).where(eq(project_exports.artifacts.taskId, taskId)).orderBy(desc(project_exports.artifacts.createdAt));
69490
+ const rows = await db.select().from(project_exports.artifacts).where(and(
69491
+ eq(project_exports.artifacts.taskId, taskId),
69492
+ projectScopeFor(project_exports.artifacts.projectId, projectId2)
69493
+ )).orderBy(desc(project_exports.artifacts.createdAt));
69329
69494
  return rows.map((row) => rowToArtifact2(row));
69330
69495
  }
69331
- async function listArtifacts(db, options) {
69496
+ async function listArtifacts(db, options, projectId2) {
69332
69497
  const limit = Math.min(Math.max(1, options?.limit ?? 200), 1e3);
69333
69498
  const offset = Math.max(0, options?.offset ?? 0);
69334
- const conditions = [];
69499
+ const conditions = [projectScopeFor(project_exports.artifacts.projectId, projectId2)];
69335
69500
  if (options?.type) {
69336
69501
  conditions.push(eq(project_exports.artifacts.type, options.type));
69337
69502
  }
@@ -69370,7 +69535,10 @@ async function listArtifacts(db, options) {
69370
69535
  taskColumn: project_exports.tasks.column
69371
69536
  }).from(project_exports.artifacts).leftJoin(
69372
69537
  project_exports.tasks,
69373
- eq(project_exports.artifacts.taskId, project_exports.tasks.id)
69538
+ and(
69539
+ eq(project_exports.artifacts.taskId, project_exports.tasks.id),
69540
+ eq(project_exports.artifacts.projectId, project_exports.tasks.projectId)
69541
+ )
69374
69542
  ).where(and(...conditions)).orderBy(desc(project_exports.artifacts.createdAt)).limit(limit).offset(offset);
69375
69543
  return rows.map((row) => {
69376
69544
  const artifact = rowToArtifact2(row);
@@ -70535,7 +70703,7 @@ function rowToBranchGroup2(row) {
70535
70703
  closedAt: row.closedAt ?? void 0
70536
70704
  };
70537
70705
  }
70538
- async function createBranchGroup(db, input) {
70706
+ async function createBranchGroup(db, input, projectId2) {
70539
70707
  validateBranchGroupBranchName(input.branchName);
70540
70708
  const now = Date.now();
70541
70709
  const id = generateBranchGroupId2();
@@ -70554,44 +70722,52 @@ async function createBranchGroup(db, input) {
70554
70722
  updatedAt: now,
70555
70723
  closedAt: input.closedAt ?? null
70556
70724
  });
70557
- const created = await getBranchGroup(db, id);
70725
+ const created = await getBranchGroup(db, id, projectId2);
70558
70726
  if (!created) throw new Error(`Failed to read branch group ${id} after create`);
70559
70727
  return created;
70560
70728
  }
70561
- async function getBranchGroup(db, id) {
70562
- const rows = await db.select().from(project_exports.branchGroups).where(eq(project_exports.branchGroups.id, id)).limit(1);
70729
+ async function getBranchGroup(db, id, projectId2) {
70730
+ const rows = await db.select().from(project_exports.branchGroups).where(and(
70731
+ eq(project_exports.branchGroups.id, id),
70732
+ projectScopeFor(project_exports.branchGroups.projectId, projectId2)
70733
+ )).limit(1);
70563
70734
  const row = rows[0];
70564
70735
  return row ? rowToBranchGroup2(row) : null;
70565
70736
  }
70566
- async function getBranchGroupBySource(db, sourceType, sourceId) {
70737
+ async function getBranchGroupBySource(db, sourceType, sourceId, projectId2) {
70567
70738
  const rows = await db.select().from(project_exports.branchGroups).where(
70568
70739
  and(
70569
70740
  eq(project_exports.branchGroups.sourceType, sourceType),
70570
- eq(project_exports.branchGroups.sourceId, sourceId)
70741
+ eq(project_exports.branchGroups.sourceId, sourceId),
70742
+ projectScopeFor(project_exports.branchGroups.projectId, projectId2)
70571
70743
  )
70572
70744
  ).limit(1);
70573
70745
  const row = rows[0];
70574
70746
  return row ? rowToBranchGroup2(row) : null;
70575
70747
  }
70576
- async function getBranchGroupByBranchName(db, branchName) {
70577
- const rows = await db.select().from(project_exports.branchGroups).where(eq(project_exports.branchGroups.branchName, branchName)).orderBy(sql`${project_exports.branchGroups.createdAt} DESC`).limit(1);
70748
+ async function getBranchGroupByBranchName(db, branchName, projectId2) {
70749
+ const rows = await db.select().from(project_exports.branchGroups).where(and(
70750
+ eq(project_exports.branchGroups.branchName, branchName),
70751
+ projectScopeFor(project_exports.branchGroups.projectId, projectId2)
70752
+ )).orderBy(sql`${project_exports.branchGroups.createdAt} DESC`).limit(1);
70578
70753
  const row = rows[0];
70579
70754
  return row ? rowToBranchGroup2(row) : null;
70580
70755
  }
70581
- async function ensureBranchGroupForSource(db, sourceType, sourceId, init) {
70582
- const existing = await getBranchGroupBySource(db, sourceType, sourceId);
70756
+ async function ensureBranchGroupForSource(db, sourceType, sourceId, init, projectId2) {
70757
+ const existing = await getBranchGroupBySource(db, sourceType, sourceId, projectId2);
70583
70758
  if (existing) return existing;
70584
- const existingByBranch = await getBranchGroupByBranchName(db, init.branchName);
70759
+ const existingByBranch = await getBranchGroupByBranchName(db, init.branchName, projectId2);
70585
70760
  if (existingByBranch) return existingByBranch;
70586
- return createBranchGroup(db, { sourceType, sourceId, ...init });
70761
+ return createBranchGroup(db, { sourceType, sourceId, ...init }, projectId2);
70587
70762
  }
70588
- async function listBranchGroups(db, options) {
70589
- const query = db.select().from(project_exports.branchGroups).orderBy(asc(project_exports.branchGroups.createdAt));
70590
- const rows = options?.status ? await query.where(eq(project_exports.branchGroups.status, options.status)) : await query;
70763
+ async function listBranchGroups(db, options, projectId2) {
70764
+ const conditions = [projectScopeFor(project_exports.branchGroups.projectId, projectId2)];
70765
+ if (options?.status) conditions.push(eq(project_exports.branchGroups.status, options.status));
70766
+ const rows = await db.select().from(project_exports.branchGroups).where(and(...conditions)).orderBy(asc(project_exports.branchGroups.createdAt));
70591
70767
  return rows.map((row) => rowToBranchGroup2(row));
70592
70768
  }
70593
- async function updateBranchGroup(db, id, patch) {
70594
- const current = await getBranchGroup(db, id);
70769
+ async function updateBranchGroup(db, id, patch, projectId2) {
70770
+ const current = await getBranchGroup(db, id, projectId2);
70595
70771
  if (!current) throw new Error(`Branch group ${id} not found`);
70596
70772
  if (patch.branchName !== void 0) {
70597
70773
  validateBranchGroupBranchName(patch.branchName);
@@ -70610,8 +70786,11 @@ async function updateBranchGroup(db, id, patch) {
70610
70786
  status: nextStatus,
70611
70787
  updatedAt: now,
70612
70788
  closedAt: nextClosedAt
70613
- }).where(eq(project_exports.branchGroups.id, id));
70614
- const updated = await getBranchGroup(db, id);
70789
+ }).where(and(
70790
+ eq(project_exports.branchGroups.id, id),
70791
+ projectScopeFor(project_exports.branchGroups.projectId, projectId2)
70792
+ ));
70793
+ const updated = await getBranchGroup(db, id, projectId2);
70615
70794
  if (!updated) throw new Error(`Branch group ${id} disappeared after update`);
70616
70795
  return updated;
70617
70796
  }
@@ -70768,6 +70947,7 @@ var init_async_branch_groups = __esm({
70768
70947
  "use strict";
70769
70948
  init_drizzle_orm();
70770
70949
  init_schema2();
70950
+ init_data_layer();
70771
70951
  init_branch_assignment();
70772
70952
  }
70773
70953
  });
@@ -80581,6 +80761,9 @@ import { randomUUID as randomUUID21 } from "node:crypto";
80581
80761
  function tableForScope(scope) {
80582
80762
  return scope === "project" ? project_exports.secrets : central_exports.secretsGlobal;
80583
80763
  }
80764
+ function scopeForSecretTable(scope, table, projectId2) {
80765
+ return scope === "project" ? projectScopeFor(table.projectId, projectId2) : void 0;
80766
+ }
80584
80767
  function isAccessPolicy(value) {
80585
80768
  return value === "auto" || value === "prompt" || value === "deny";
80586
80769
  }
@@ -80603,23 +80786,23 @@ function rowToRecord2(row, scope) {
80603
80786
  lastReadBy: row.lastReadBy
80604
80787
  };
80605
80788
  }
80606
- async function getSecretMetadata(handle, id, scope) {
80789
+ async function getSecretMetadata(handle, id, scope, projectId2) {
80607
80790
  const table = tableForScope(scope);
80608
- const rows = await handle.select(metadataColumns(table)).from(table).where(eq(table.id, id)).limit(1);
80791
+ const rows = await handle.select(metadataColumns(table)).from(table).where(and(eq(table.id, id), scopeForSecretTable(scope, table, projectId2))).limit(1);
80609
80792
  const row = rows[0];
80610
80793
  return row ? rowToRecord2(row, scope) : null;
80611
80794
  }
80612
- async function listSecrets(handle, scope) {
80795
+ async function listSecrets(handle, scope, projectId2) {
80613
80796
  if (scope) {
80614
80797
  const table = tableForScope(scope);
80615
- const rows = await handle.select(metadataColumns(table)).from(table).orderBy(asc(sql`lower(${table.key})`));
80798
+ const rows = await handle.select(metadataColumns(table)).from(table).where(scopeForSecretTable(scope, table, projectId2)).orderBy(asc(sql`lower(${table.key})`));
80616
80799
  return rows.map((row) => rowToRecord2(row, scope));
80617
80800
  }
80618
- const project = await listSecrets(handle, "project");
80619
- const global2 = await listSecrets(handle, "global");
80801
+ const project = await listSecrets(handle, "project", projectId2);
80802
+ const global2 = await listSecrets(handle, "global", projectId2);
80620
80803
  return [...project, ...global2];
80621
80804
  }
80622
- async function createSecret(handle, cipher, input) {
80805
+ async function createSecret(handle, cipher, input, projectId2) {
80623
80806
  const key = input.key.trim();
80624
80807
  if (!key) {
80625
80808
  throw new SecretsStoreError({ code: "invalid-key", message: "Secret key is required" });
@@ -80633,6 +80816,7 @@ async function createSecret(handle, cipher, input) {
80633
80816
  const table = tableForScope(input.scope);
80634
80817
  try {
80635
80818
  await handle.insert(table).values({
80819
+ ...input.scope === "project" && projectId2?.trim() ? { projectId: projectId2 } : {},
80636
80820
  id,
80637
80821
  key,
80638
80822
  valueCiphertext: encrypted.ciphertext,
@@ -80652,14 +80836,14 @@ async function createSecret(handle, cipher, input) {
80652
80836
  }
80653
80837
  throw error2;
80654
80838
  }
80655
- const created = await getSecretMetadata(handle, id, input.scope);
80839
+ const created = await getSecretMetadata(handle, id, input.scope, projectId2);
80656
80840
  if (!created) {
80657
80841
  throw new SecretsStoreError({ code: "not-found", message: "Secret insert succeeded but row could not be read back" });
80658
80842
  }
80659
80843
  return created;
80660
80844
  }
80661
- async function updateSecret(handle, cipher, id, scope, patch) {
80662
- const existing = await getSecretMetadata(handle, id, scope);
80845
+ async function updateSecret(handle, cipher, id, scope, patch, projectId2) {
80846
+ const existing = await getSecretMetadata(handle, id, scope, projectId2);
80663
80847
  if (!existing) {
80664
80848
  throw new SecretsStoreError({ code: "not-found", message: "Secret not found" });
80665
80849
  }
@@ -80693,34 +80877,34 @@ async function updateSecret(handle, cipher, id, scope, patch) {
80693
80877
  updates.nonce = encrypted.nonce;
80694
80878
  }
80695
80879
  try {
80696
- await handle.update(table).set(updates).where(eq(table.id, id));
80880
+ await handle.update(table).set(updates).where(and(eq(table.id, id), scopeForSecretTable(scope, table, projectId2)));
80697
80881
  } catch (error2) {
80698
80882
  if (isPostgresUniqueError(error2)) {
80699
80883
  throw new SecretsStoreError({ code: "duplicate-key", message: "Secret key already exists" });
80700
80884
  }
80701
80885
  throw error2;
80702
80886
  }
80703
- const updated = await getSecretMetadata(handle, id, scope);
80887
+ const updated = await getSecretMetadata(handle, id, scope, projectId2);
80704
80888
  if (!updated) {
80705
80889
  throw new SecretsStoreError({ code: "not-found", message: "Secret update succeeded but row could not be read back" });
80706
80890
  }
80707
80891
  return updated;
80708
80892
  }
80709
- async function deleteSecret(handle, id, scope) {
80710
- const existing = await getSecretMetadata(handle, id, scope);
80893
+ async function deleteSecret(handle, id, scope, projectId2) {
80894
+ const existing = await getSecretMetadata(handle, id, scope, projectId2);
80711
80895
  if (!existing) {
80712
80896
  throw new SecretsStoreError({ code: "not-found", message: "Secret not found" });
80713
80897
  }
80714
80898
  const table = tableForScope(scope);
80715
- await handle.delete(table).where(eq(table.id, id));
80899
+ await handle.delete(table).where(and(eq(table.id, id), scopeForSecretTable(scope, table, projectId2)));
80716
80900
  }
80717
- async function revealSecret(handle, cipher, id, scope, reader) {
80901
+ async function revealSecret(handle, cipher, id, scope, reader, projectId2) {
80718
80902
  const table = tableForScope(scope);
80719
80903
  const rows = await handle.select({
80720
80904
  ...metadataColumns(table),
80721
80905
  valueCiphertext: table.valueCiphertext,
80722
80906
  nonce: table.nonce
80723
- }).from(table).where(eq(table.id, id)).limit(1);
80907
+ }).from(table).where(and(eq(table.id, id), scopeForSecretTable(scope, table, projectId2))).limit(1);
80724
80908
  const row = rows[0];
80725
80909
  if (!row) {
80726
80910
  throw new SecretsStoreError({ code: "not-found", message: "Secret not found" });
@@ -80739,7 +80923,7 @@ async function revealSecret(handle, cipher, id, scope, reader) {
80739
80923
  }
80740
80924
  const now = (/* @__PURE__ */ new Date()).toISOString();
80741
80925
  const lastReadBy = reader.userId ?? reader.agentId ?? null;
80742
- await handle.update(table).set({ lastReadAt: now, lastReadBy, updatedAt: now }).where(eq(table.id, id));
80926
+ await handle.update(table).set({ lastReadAt: now, lastReadBy, updatedAt: now }).where(and(eq(table.id, id), scopeForSecretTable(scope, table, projectId2)));
80743
80927
  return { key: row.key, plaintextValue };
80744
80928
  }
80745
80929
  var severityAuditLog10, SecretsStoreError, metadataColumns;
@@ -80750,6 +80934,7 @@ var init_async_secrets_store = __esm({
80750
80934
  init_drizzle_orm();
80751
80935
  init_postgres_errors();
80752
80936
  init_schema2();
80937
+ init_data_layer();
80753
80938
  init_secrets_crypto();
80754
80939
  severityAuditLog10 = createLogger2("core-async-secrets-store");
80755
80940
  SecretsStoreError = class extends Error {
@@ -80845,7 +81030,7 @@ var init_secrets_store = __esm({
80845
81030
  };
80846
81031
  }
80847
81032
  async listSecrets(scope) {
80848
- return listSecrets(this.asyncLayer.db, scope);
81033
+ return listSecrets(this.asyncLayer.db, scope, this.asyncLayer.projectId);
80849
81034
  }
80850
81035
  async listEnvExportable(opts) {
80851
81036
  const keyPrefix = opts?.keyPrefix;
@@ -80888,7 +81073,7 @@ var init_secrets_store = __esm({
80888
81073
  return [...exported.values()];
80889
81074
  }
80890
81075
  async getSecretMetadata(id, scope) {
80891
- return getSecretMetadata(this.asyncLayer.db, id, scope);
81076
+ return getSecretMetadata(this.asyncLayer.db, id, scope, this.asyncLayer.projectId);
80892
81077
  }
80893
81078
  async createSecret(input) {
80894
81079
  const key = input.key.trim();
@@ -80898,12 +81083,12 @@ var init_secrets_store = __esm({
80898
81083
  if (input.accessPolicy && !isAccessPolicy2(input.accessPolicy)) {
80899
81084
  throw new SecretsStoreError2({ code: "invalid-policy", message: "Invalid access policy" });
80900
81085
  }
80901
- const created = await createSecret(this.asyncLayer.db, this.cipher, input);
81086
+ const created = await createSecret(this.asyncLayer.db, this.cipher, input, this.asyncLayer.projectId);
80902
81087
  this.emitAudit({ mutationType: "secret:create", scope: input.scope, secretId: created.id, key: created.key });
80903
81088
  return created;
80904
81089
  }
80905
81090
  async updateSecret(id, scope, patch) {
80906
- const updated = await updateSecret(this.asyncLayer.db, this.cipher, id, scope, patch);
81091
+ const updated = await updateSecret(this.asyncLayer.db, this.cipher, id, scope, patch, this.asyncLayer.projectId);
80907
81092
  this.emitAudit({ mutationType: "secret:update", scope, secretId: updated.id, key: updated.key });
80908
81093
  return updated;
80909
81094
  }
@@ -80912,12 +81097,12 @@ var init_secrets_store = __esm({
80912
81097
  if (!existing) {
80913
81098
  throw new SecretsStoreError2({ code: "not-found", message: "Secret not found" });
80914
81099
  }
80915
- await deleteSecret(this.asyncLayer.db, id, scope);
81100
+ await deleteSecret(this.asyncLayer.db, id, scope, this.asyncLayer.projectId);
80916
81101
  this.emitAudit({ mutationType: "secret:delete", scope, secretId: id, key: existing.key });
80917
81102
  return;
80918
81103
  }
80919
81104
  async revealSecret(id, scope, reader) {
80920
- const revealed = await revealSecret(this.asyncLayer.db, this.cipher, id, scope, reader);
81105
+ const revealed = await revealSecret(this.asyncLayer.db, this.cipher, id, scope, reader, this.asyncLayer.projectId);
80921
81106
  this.emitAudit({ mutationType: "secret:read", scope, secretId: id, key: revealed.key, actor: reader });
80922
81107
  return revealed;
80923
81108
  }
@@ -82018,6 +82203,7 @@ async function getVerificationCacheHitImpl(store, treeSha, testCommand, buildCom
82018
82203
  const normalizedBuild = buildCommand2 ?? "";
82019
82204
  const table = project_exports.verificationCache;
82020
82205
  const rows = await store.asyncLayer.db.select({ recordedAt: table.recordedAt, taskId: table.taskId }).from(table).where(and(
82206
+ projectScopeFor(table.projectId, store.asyncLayer.projectId),
82021
82207
  eq(table.treeSha, treeSha),
82022
82208
  eq(table.testCommand, normalizedTest),
82023
82209
  eq(table.buildCommand, normalizedBuild)
@@ -82760,7 +82946,7 @@ async function invokeTaskCreatedHookImpl(store, task) {
82760
82946
  }
82761
82947
  async function createBranchGroupImpl(store, input) {
82762
82948
  const layer = store.asyncLayer;
82763
- return createBranchGroup(layer.db, input);
82949
+ return createBranchGroup(layer.db, input, layer.projectId);
82764
82950
  }
82765
82951
  var init_task_id_integrity2 = __esm({
82766
82952
  "../core/src/task-store/task-id-integrity.ts"() {
@@ -82845,22 +83031,23 @@ import { readFile as readFile7, writeFile as writeFile5 } from "node:fs/promises
82845
83031
  import { join as join23 } from "node:path";
82846
83032
  async function getBranchGroupImpl(store, id) {
82847
83033
  const layer = store.asyncLayer;
82848
- return getBranchGroup(layer.db, id);
83034
+ return getBranchGroup(layer.db, id, layer.projectId);
82849
83035
  }
82850
83036
  async function getBranchGroupBySourceImpl(store, sourceType, sourceId) {
82851
83037
  const layer = store.asyncLayer;
82852
- return getBranchGroupBySource(layer.db, sourceType, sourceId);
83038
+ return getBranchGroupBySource(layer.db, sourceType, sourceId, layer.projectId);
82853
83039
  }
82854
83040
  async function getBranchGroupByBranchNameImpl(store, branchName) {
82855
83041
  const layer = store.asyncLayer;
82856
- return getBranchGroupByBranchName(layer.db, branchName);
83042
+ return getBranchGroupByBranchName(layer.db, branchName, layer.projectId);
82857
83043
  }
82858
83044
  async function ensureBranchGroupForSourceImpl(store, sourceType, sourceId, init) {
82859
- return ensureBranchGroupForSource(store.asyncLayer.db, sourceType, sourceId, init);
83045
+ const layer = store.asyncLayer;
83046
+ return ensureBranchGroupForSource(layer.db, sourceType, sourceId, init, layer.projectId);
82860
83047
  }
82861
83048
  async function listBranchGroupsImpl(store, options) {
82862
83049
  const layer = store.asyncLayer;
82863
- return listBranchGroups(layer.db, options);
83050
+ return listBranchGroups(layer.db, options, layer.projectId);
82864
83051
  }
82865
83052
  async function listTasksByBranchGroupImpl(store, groupId) {
82866
83053
  const tasks2 = await store.listTasks({ includeArchived: true, slim: false });
@@ -84402,7 +84589,7 @@ function insertArtifactRowImpl(store, input, id, now, stored) {
84402
84589
  }
84403
84590
  async function getArtifactImpl(store, id) {
84404
84591
  const layer = store.asyncLayer;
84405
- return getArtifact(layer.db, id);
84592
+ return getArtifact(layer.db, id, layer.projectId);
84406
84593
  }
84407
84594
  async function updateArtifactImpl(store, id, updates) {
84408
84595
  const layer = store.asyncLayer;
@@ -89271,6 +89458,7 @@ var init_async_archive_lineage = __esm({
89271
89458
  "use strict";
89272
89459
  init_drizzle_orm();
89273
89460
  init_schema2();
89461
+ init_data_layer();
89274
89462
  init_async_persistence();
89275
89463
  init_async_lifecycle();
89276
89464
  init_lineage_approval_invalidation();
@@ -92738,7 +92926,7 @@ async function _maybeAutoArchiveSameAgentDuplicateBackendImpl(store, task, input
92738
92926
  }
92739
92927
  async function updateBranchGroupImpl(store, id, patch) {
92740
92928
  const layer = store.asyncLayer;
92741
- return updateBranchGroup(layer.db, id, patch);
92929
+ return updateBranchGroup(layer.db, id, patch, layer.projectId);
92742
92930
  }
92743
92931
  async function updatePrEntityImpl(store, id, patch) {
92744
92932
  const layer = store.asyncLayer;
@@ -93248,13 +93436,19 @@ async function deleteAttachmentArtifactRows(store, taskId, filename) {
93248
93436
  const linkedArtifactIds = artifacts2.filter((artifact) => artifact.metadata?.source === "attachment" && artifact.metadata.attachmentFilename === filename).map((artifact) => artifact.id);
93249
93437
  if (linkedArtifactIds.length === 0) return;
93250
93438
  for (const artifactId of linkedArtifactIds) {
93251
- await layer.db.delete(project_exports.artifacts).where(eq(project_exports.artifacts.id, artifactId));
93439
+ await layer.db.delete(project_exports.artifacts).where(and(
93440
+ eq(project_exports.artifacts.id, artifactId),
93441
+ projectScopeFor(project_exports.artifacts.projectId, layer.projectId)
93442
+ ));
93252
93443
  }
93253
93444
  return;
93254
93445
  }
93255
93446
  async function getArtifactsForAttachmentCleanup(store, taskId) {
93256
93447
  const layer = store.asyncLayer;
93257
- const rows = await layer.db.select().from(project_exports.artifacts).where(eq(project_exports.artifacts.taskId, taskId));
93448
+ const rows = await layer.db.select().from(project_exports.artifacts).where(and(
93449
+ eq(project_exports.artifacts.taskId, taskId),
93450
+ projectScopeFor(project_exports.artifacts.projectId, layer.projectId)
93451
+ ));
93258
93452
  return rows;
93259
93453
  }
93260
93454
  async function deleteAttachmentImpl(store, id, filename) {
@@ -95670,7 +95864,7 @@ function clearLinkedAgentTaskIdsImpl(store, taskId, updatedAt = (/* @__PURE__ */
95670
95864
  `).run(updatedAt, updatedAt, taskId);
95671
95865
  }
95672
95866
  async function listArtifactsImpl(store, options) {
95673
- return listArtifacts(store.asyncLayer.db, options);
95867
+ return listArtifacts(store.asyncLayer.db, options, store.asyncLayer.projectId);
95674
95868
  }
95675
95869
  async function rehomeOccupantImpl(store, taskId, targetColumn, reason, metadata) {
95676
95870
  let current;
@@ -103997,7 +104191,11 @@ var init_store = __esm({
103997
104191
  /** PostgreSQL-authoritative audit reader; sync fallback remains for test doubles. */
103998
104192
  async getRunAuditEventsAsync(options = {}) {
103999
104193
  if (this.asyncLayer) {
104000
- const events = await queryRunAuditEvents(this.asyncLayer.db, options);
104194
+ const events = await queryRunAuditEvents(
104195
+ this.asyncLayer.db,
104196
+ options,
104197
+ this.asyncLayer.projectId
104198
+ );
104001
104199
  return events.map((event) => ({
104002
104200
  ...event,
104003
104201
  taskId: event.taskId ?? void 0,
@@ -107575,7 +107773,9 @@ function rangeWhere(query) {
107575
107773
  async function aggregatePluginActivations(dbOrLayer, query = {}) {
107576
107774
  if ("ping" in dbOrLayer) {
107577
107775
  const layer = dbOrLayer;
107578
- const conditions = [];
107776
+ const conditions = [projectScopeFor(project_exports.pluginActivations.projectId, layer.projectId)].filter(
107777
+ (condition) => condition !== void 0
107778
+ );
107579
107779
  if (query.from !== void 0) conditions.push(gte(project_exports.pluginActivations.activatedAt, query.from));
107580
107780
  if (query.to !== void 0) conditions.push(lte(project_exports.pluginActivations.activatedAt, query.to));
107581
107781
  const where2 = conditions.length > 0 ? and(...conditions) : void 0;
@@ -107614,6 +107814,7 @@ async function aggregatePluginActivations(dbOrLayer, query = {}) {
107614
107814
  var init_plugin_activation_analytics = __esm({
107615
107815
  "../core/src/plugins/plugin-activation-analytics.ts"() {
107616
107816
  "use strict";
107817
+ init_data_layer();
107617
107818
  init_drizzle_orm();
107618
107819
  init_schema2();
107619
107820
  }
@@ -130611,6 +130812,18 @@ function rowToMessage2(row) {
130611
130812
  createdAt: row.createdAt
130612
130813
  };
130613
130814
  }
130815
+ function chatMessageProjectConditions(handle, projectId2) {
130816
+ const messageScope = projectScopeFor(project_exports.chatMessages.projectId, projectId2);
130817
+ const sessionScope = projectScopeFor(project_exports.chatSessions.projectId, projectId2);
130818
+ if (!messageScope || !sessionScope) return [];
130819
+ return [
130820
+ messageScope,
130821
+ exists(handle.select({ id: project_exports.chatSessions.id }).from(project_exports.chatSessions).where(and(
130822
+ eq(project_exports.chatSessions.id, project_exports.chatMessages.sessionId),
130823
+ sessionScope
130824
+ )))
130825
+ ];
130826
+ }
130614
130827
  function rowToRoom(row) {
130615
130828
  return {
130616
130829
  id: row.id,
@@ -130782,7 +130995,7 @@ async function replaceChatSessionTags(layer, sessionId, projectId2, tagIds) {
130782
130995
  return attachTags(tx, session);
130783
130996
  });
130784
130997
  }
130785
- async function addChatMessage(handle, message) {
130998
+ async function addChatMessage(handle, message, projectId2) {
130786
130999
  const sanitizedAttachments = message.attachments === void 0 ? void 0 : sanitizeJsonbValue(message.attachments);
130787
131000
  const sanitized = {
130788
131001
  ...message,
@@ -130801,15 +131014,24 @@ async function addChatMessage(handle, message) {
130801
131014
  attachments: sanitizedAttachments ?? null,
130802
131015
  createdAt: sanitized.createdAt
130803
131016
  });
130804
- await handle.update(project_exports.chatSessions).set({ updatedAt: sanitized.createdAt }).where(eq(project_exports.chatSessions.id, sanitized.sessionId));
131017
+ await handle.update(project_exports.chatSessions).set({ updatedAt: sanitized.createdAt }).where(and(
131018
+ eq(project_exports.chatSessions.id, sanitized.sessionId),
131019
+ projectScopeFor(project_exports.chatSessions.projectId, projectId2)
131020
+ ));
130805
131021
  return sanitized;
130806
131022
  }
130807
- async function getChatMessage(handle, id) {
130808
- const rows = await handle.select().from(project_exports.chatMessages).where(eq(project_exports.chatMessages.id, id));
131023
+ async function getChatMessage(handle, id, projectId2) {
131024
+ const rows = await handle.select().from(project_exports.chatMessages).where(and(
131025
+ eq(project_exports.chatMessages.id, id),
131026
+ ...chatMessageProjectConditions(handle, projectId2)
131027
+ ));
130809
131028
  return rows[0] ? rowToMessage2(rows[0]) : void 0;
130810
131029
  }
130811
- async function getChatMessages(handle, sessionId, filter) {
130812
- const conditions = [eq(project_exports.chatMessages.sessionId, sessionId)];
131030
+ async function getChatMessages(handle, sessionId, filter, projectId2) {
131031
+ const conditions = [
131032
+ eq(project_exports.chatMessages.sessionId, sessionId),
131033
+ ...chatMessageProjectConditions(handle, projectId2)
131034
+ ];
130813
131035
  if (filter?.before) {
130814
131036
  conditions.push(lte(project_exports.chatMessages.createdAt, filter.before));
130815
131037
  }
@@ -130819,9 +131041,12 @@ async function getChatMessages(handle, sessionId, filter) {
130819
131041
  const rows = await handle.select().from(project_exports.chatMessages).where(and(...conditions)).orderBy(filter?.order === "desc" ? desc(orderCol) : asc(orderCol)).limit(limit).offset(offset);
130820
131042
  return rows.map(rowToMessage2);
130821
131043
  }
130822
- async function getLastMessageForSessions(handle, sessionIds) {
131044
+ async function getLastMessageForSessions(handle, sessionIds, projectId2) {
130823
131045
  if (sessionIds.length === 0) return /* @__PURE__ */ new Map();
130824
- const rows = await handle.select().from(project_exports.chatMessages).where(inArray(project_exports.chatMessages.sessionId, sessionIds)).orderBy(
131046
+ const rows = await handle.select().from(project_exports.chatMessages).where(and(
131047
+ inArray(project_exports.chatMessages.sessionId, sessionIds),
131048
+ ...chatMessageProjectConditions(handle, projectId2)
131049
+ )).orderBy(
130825
131050
  desc(project_exports.chatMessages.createdAt),
130826
131051
  desc(project_exports.chatMessages.id)
130827
131052
  );
@@ -130987,8 +131212,8 @@ async function setInFlightGeneration(handle, id, inFlightGeneration) {
130987
131212
  await handle.update(project_exports.chatSessions).set({ inFlightGeneration: sanitizedInFlightGeneration }).where(eq(project_exports.chatSessions.id, id));
130988
131213
  return getChatSession(handle, id);
130989
131214
  }
130990
- async function addChatMessageAttachment(handle, sessionId, messageId, attachment) {
130991
- const message = await getChatMessage(handle, messageId);
131215
+ async function addChatMessageAttachment(handle, sessionId, messageId, attachment, projectId2) {
131216
+ const message = await getChatMessage(handle, messageId, projectId2);
130992
131217
  if (!message || message.sessionId !== sessionId) {
130993
131218
  throw new Error(`Message ${messageId} not found in session ${sessionId}`);
130994
131219
  }
@@ -130996,25 +131221,35 @@ async function addChatMessageAttachment(handle, sessionId, messageId, attachment
130996
131221
  ...message.attachments ?? [],
130997
131222
  attachment
130998
131223
  ]);
130999
- await handle.update(project_exports.chatMessages).set({ attachments: updatedAttachments }).where(eq(project_exports.chatMessages.id, messageId));
131000
- const updated = await getChatMessage(handle, messageId);
131224
+ await handle.update(project_exports.chatMessages).set({ attachments: updatedAttachments }).where(and(
131225
+ eq(project_exports.chatMessages.id, messageId),
131226
+ ...chatMessageProjectConditions(handle, projectId2)
131227
+ ));
131228
+ const updated = await getChatMessage(handle, messageId, projectId2);
131001
131229
  if (!updated) throw new Error(`Failed to update message ${messageId}`);
131002
131230
  return updated;
131003
131231
  }
131004
- async function deleteChatMessage(handle, id) {
131005
- const existing = await getChatMessage(handle, id);
131232
+ async function deleteChatMessage(handle, id, projectId2) {
131233
+ const existing = await getChatMessage(handle, id, projectId2);
131006
131234
  if (!existing) return false;
131007
- await handle.delete(project_exports.chatMessages).where(eq(project_exports.chatMessages.id, id));
131008
- await handle.update(project_exports.chatSessions).set({ updatedAt: (/* @__PURE__ */ new Date()).toISOString() }).where(eq(project_exports.chatSessions.id, existing.sessionId));
131235
+ await handle.delete(project_exports.chatMessages).where(and(
131236
+ eq(project_exports.chatMessages.id, id),
131237
+ ...chatMessageProjectConditions(handle, projectId2)
131238
+ ));
131239
+ await handle.update(project_exports.chatSessions).set({ updatedAt: (/* @__PURE__ */ new Date()).toISOString() }).where(and(
131240
+ eq(project_exports.chatSessions.id, existing.sessionId),
131241
+ projectScopeFor(project_exports.chatSessions.projectId, projectId2)
131242
+ ));
131009
131243
  return true;
131010
131244
  }
131011
- async function searchChatSessionsByMessageContent(handle, query, sessionIds) {
131245
+ async function searchChatSessionsByMessageContent(handle, query, sessionIds, projectId2) {
131012
131246
  const trimmed = query.trim();
131013
131247
  if (!trimmed || sessionIds.length === 0) return /* @__PURE__ */ new Map();
131014
131248
  const escaped = trimmed.replace(/\\/g, "\\\\").replace(/%/g, "\\%").replace(/_/g, "\\_");
131015
131249
  const rows = await handle.select().from(project_exports.chatMessages).where(and(
131016
131250
  inArray(project_exports.chatMessages.sessionId, sessionIds),
131017
- ilike(project_exports.chatMessages.content, `%${escaped}%`)
131251
+ ilike(project_exports.chatMessages.content, `%${escaped}%`),
131252
+ ...chatMessageProjectConditions(handle, projectId2)
131018
131253
  )).orderBy(
131019
131254
  desc(project_exports.chatMessages.createdAt),
131020
131255
  desc(project_exports.chatMessages.id)
@@ -131028,13 +131263,16 @@ async function searchChatSessionsByMessageContent(handle, query, sessionIds) {
131028
131263
  }
131029
131264
  return result;
131030
131265
  }
131031
- async function deleteChatMessagesFrom(handle, sessionId, fromMessageId) {
131032
- const orderedRows = await handle.select().from(project_exports.chatMessages).where(eq(project_exports.chatMessages.sessionId, sessionId)).orderBy(
131266
+ async function deleteChatMessagesFrom(handle, sessionId, fromMessageId, projectId2) {
131267
+ const orderedRows = await handle.select().from(project_exports.chatMessages).where(and(
131268
+ eq(project_exports.chatMessages.sessionId, sessionId),
131269
+ ...chatMessageProjectConditions(handle, projectId2)
131270
+ )).orderBy(
131033
131271
  asc(project_exports.chatMessages.createdAt),
131034
131272
  asc(project_exports.chatMessages.id)
131035
131273
  );
131036
131274
  const ordered2 = orderedRows.map(rowToMessage2);
131037
- const target = await getChatMessage(handle, fromMessageId);
131275
+ const target = await getChatMessage(handle, fromMessageId, projectId2);
131038
131276
  if (!target || target.sessionId !== sessionId) {
131039
131277
  return { deletedIds: [], retained: ordered2 };
131040
131278
  }
@@ -131047,19 +131285,28 @@ async function deleteChatMessagesFrom(handle, sessionId, fromMessageId) {
131047
131285
  if (deletedIds.length === 0) {
131048
131286
  return { deletedIds: [], retained };
131049
131287
  }
131050
- await handle.delete(project_exports.chatMessages).where(inArray(project_exports.chatMessages.id, deletedIds));
131051
- await handle.update(project_exports.chatSessions).set({ updatedAt: (/* @__PURE__ */ new Date()).toISOString() }).where(eq(project_exports.chatSessions.id, sessionId));
131288
+ await handle.delete(project_exports.chatMessages).where(and(
131289
+ inArray(project_exports.chatMessages.id, deletedIds),
131290
+ ...chatMessageProjectConditions(handle, projectId2)
131291
+ ));
131292
+ await handle.update(project_exports.chatSessions).set({ updatedAt: (/* @__PURE__ */ new Date()).toISOString() }).where(and(
131293
+ eq(project_exports.chatSessions.id, sessionId),
131294
+ projectScopeFor(project_exports.chatSessions.projectId, projectId2)
131295
+ ));
131052
131296
  return { deletedIds, retained };
131053
131297
  }
131054
- async function updateChatMessageMetadata(handle, messageId, metadata, options) {
131055
- const existing = await getChatMessage(handle, messageId);
131298
+ async function updateChatMessageMetadata(handle, messageId, metadata, options, projectId2) {
131299
+ const existing = await getChatMessage(handle, messageId, projectId2);
131056
131300
  if (!existing) {
131057
131301
  throw new Error(`Message ${messageId} not found`);
131058
131302
  }
131059
131303
  const merge2 = options?.merge !== false;
131060
131304
  const nextMetadata = metadata === null ? merge2 ? existing.metadata : null : merge2 ? { ...existing.metadata ?? {}, ...metadata } : metadata;
131061
- await handle.update(project_exports.chatMessages).set({ metadata: sanitizeJsonbValue(nextMetadata) ?? null }).where(eq(project_exports.chatMessages.id, messageId));
131062
- const updated = await getChatMessage(handle, messageId);
131305
+ await handle.update(project_exports.chatMessages).set({ metadata: sanitizeJsonbValue(nextMetadata) ?? null }).where(and(
131306
+ eq(project_exports.chatMessages.id, messageId),
131307
+ ...chatMessageProjectConditions(handle, projectId2)
131308
+ ));
131309
+ const updated = await getChatMessage(handle, messageId, projectId2);
131063
131310
  if (!updated) {
131064
131311
  throw new Error(`Failed to update message ${messageId}`);
131065
131312
  }
@@ -131441,7 +131688,7 @@ var init_chat_store = __esm({
131441
131688
  attachments: input.attachments,
131442
131689
  createdAt: now
131443
131690
  };
131444
- const created = await addChatMessage(this.asyncLayer.db, message);
131691
+ const created = await addChatMessage(this.asyncLayer.db, message, this.asyncLayer.projectId);
131445
131692
  this.emit("chat:message:added", created);
131446
131693
  return created;
131447
131694
  }
@@ -131449,7 +131696,7 @@ var init_chat_store = __esm({
131449
131696
  * Append a file attachment metadata record to an existing message.
131450
131697
  */
131451
131698
  async addMessageAttachment(sessionId, messageId, attachment) {
131452
- const updated = await addChatMessageAttachment(this.asyncLayer.db, sessionId, messageId, attachment);
131699
+ const updated = await addChatMessageAttachment(this.asyncLayer.db, sessionId, messageId, attachment, this.asyncLayer.projectId);
131453
131700
  this.emit("chat:message:updated", updated);
131454
131701
  return updated;
131455
131702
  }
@@ -131461,7 +131708,7 @@ var init_chat_store = __esm({
131461
131708
  * @returns Array of messages ordered by createdAt ASC (default) or DESC
131462
131709
  */
131463
131710
  async getMessages(sessionId, filter) {
131464
- return getChatMessages(this.asyncLayer.db, sessionId, filter);
131711
+ return getChatMessages(this.asyncLayer.db, sessionId, filter, this.asyncLayer.projectId);
131465
131712
  }
131466
131713
  /**
131467
131714
  * Get a message by ID.
@@ -131470,7 +131717,7 @@ var init_chat_store = __esm({
131470
131717
  * @returns The message, or undefined if not found
131471
131718
  */
131472
131719
  async getMessage(id) {
131473
- return getChatMessage(this.asyncLayer.db, id);
131720
+ return getChatMessage(this.asyncLayer.db, id, this.asyncLayer.projectId);
131474
131721
  }
131475
131722
  /**
131476
131723
  * Get the latest message for each session in the provided list.
@@ -131480,10 +131727,10 @@ var init_chat_store = __esm({
131480
131727
  * @returns Map of sessionId -> latest ChatMessage for that session
131481
131728
  */
131482
131729
  async getLastMessageForSessions(sessionIds) {
131483
- return getLastMessageForSessions(this.asyncLayer.db, sessionIds);
131730
+ return getLastMessageForSessions(this.asyncLayer.db, sessionIds, this.asyncLayer.projectId);
131484
131731
  }
131485
131732
  async hasMessages(sessionId) {
131486
- return (await getChatMessages(this.asyncLayer.db, sessionId, { limit: 1 })).length > 0;
131733
+ return (await getChatMessages(this.asyncLayer.db, sessionId, { limit: 1 }, this.asyncLayer.projectId)).length > 0;
131487
131734
  }
131488
131735
  /**
131489
131736
  * Search sessions by message content (not just title/agentId).
@@ -131511,7 +131758,7 @@ var init_chat_store = __esm({
131511
131758
  if (!trimmed || !sessionIds || sessionIds.length === 0) {
131512
131759
  return /* @__PURE__ */ new Map();
131513
131760
  }
131514
- return searchChatSessionsByMessageContent(this.asyncLayer.db, trimmed, sessionIds);
131761
+ return searchChatSessionsByMessageContent(this.asyncLayer.db, trimmed, sessionIds, this.asyncLayer.projectId);
131515
131762
  }
131516
131763
  /**
131517
131764
  * Delete a message by ID.
@@ -131520,9 +131767,9 @@ var init_chat_store = __esm({
131520
131767
  * @returns true if deleted, false if not found
131521
131768
  */
131522
131769
  async deleteMessage(id) {
131523
- const existing = await getChatMessage(this.asyncLayer.db, id);
131770
+ const existing = await getChatMessage(this.asyncLayer.db, id, this.asyncLayer.projectId);
131524
131771
  if (!existing) return false;
131525
- const deleted = await deleteChatMessage(this.asyncLayer.db, id);
131772
+ const deleted = await deleteChatMessage(this.asyncLayer.db, id, this.asyncLayer.projectId);
131526
131773
  if (deleted) {
131527
131774
  this.emit("chat:message:deleted", id);
131528
131775
  const updatedSession = await this.getSession(existing.sessionId);
@@ -131545,7 +131792,7 @@ var init_chat_store = __esm({
131545
131792
  * @returns deletedIds (in ASC order) and retained messages (pre-edit history, ASC order)
131546
131793
  */
131547
131794
  async deleteMessagesFrom(sessionId, fromMessageId) {
131548
- const result = await deleteChatMessagesFrom(this.asyncLayer.db, sessionId, fromMessageId);
131795
+ const result = await deleteChatMessagesFrom(this.asyncLayer.db, sessionId, fromMessageId, this.asyncLayer.projectId);
131549
131796
  if (result.deletedIds.length > 0) {
131550
131797
  for (const id of result.deletedIds) {
131551
131798
  this.emit("chat:message:deleted", id);
@@ -131563,7 +131810,7 @@ var init_chat_store = __esm({
131563
131810
  * is what lets a later edit rewind losslessly via SessionManager.branch()/resetLeaf().
131564
131811
  */
131565
131812
  async updateMessageMetadata(messageId, metadata, options) {
131566
- const updated = await updateChatMessageMetadata(this.asyncLayer.db, messageId, metadata, options);
131813
+ const updated = await updateChatMessageMetadata(this.asyncLayer.db, messageId, metadata, options, this.asyncLayer.projectId);
131567
131814
  this.emit("chat:message:updated", updated);
131568
131815
  return updated;
131569
131816
  }
@@ -144276,32 +144523,36 @@ var init_scheduler = __esm({
144276
144523
  const hierarchy = await missionStore.getMissionWithHierarchy(mission.id);
144277
144524
  if (!hierarchy) continue;
144278
144525
  for (const slice of hierarchy.milestones.flatMap((milestone) => milestone.slices).filter((slice2) => slice2.status === "active")) {
144279
- const superseded = await missionStore.reconcileSupersededGeneratedFixFeatures(slice.id);
144280
- fixed += superseded.supersededCount;
144281
- if (superseded.supersededCount > 0) {
144282
- const refreshed = await missionStore.getSlice(slice.id);
144283
- if (refreshed?.status === "complete") {
144284
- await this.onSliceComplete(refreshed);
144285
- continue;
144526
+ try {
144527
+ const superseded = await missionStore.reconcileSupersededGeneratedFixFeatures(slice.id);
144528
+ fixed += superseded.supersededCount;
144529
+ if (superseded.supersededCount > 0) {
144530
+ const refreshed = await missionStore.getSlice(slice.id);
144531
+ if (refreshed?.status === "complete") {
144532
+ await this.onSliceComplete(refreshed);
144533
+ continue;
144534
+ }
144286
144535
  }
144287
- }
144288
- const listFeatures2 = missionStore.listFeatures;
144289
- const features = listFeatures2 ? await listFeatures2(slice.id) : slice.features;
144290
- const supersededFeatureIds = new Set(superseded.featureIds ?? []);
144291
- const autoTriage = mission.autopilotEnabled === true || mission.autoAdvance === true;
144292
- for (const feature of features) {
144293
- if (supersededFeatureIds.has(feature.id) || feature.taskId || !autoTriage || feature.status === "blocked") continue;
144294
- if (feature.status !== "defined" && this.isGeneratedFixFeature(feature)) {
144295
- await missionStore.updateFeature(feature.id, { status: "blocked", loopState: "blocked", taskId: void 0 });
144536
+ const listFeatures2 = missionStore.listFeatures;
144537
+ const features = listFeatures2 ? await listFeatures2.call(missionStore, slice.id) : slice.features;
144538
+ const supersededFeatureIds = new Set(superseded.featureIds ?? []);
144539
+ const autoTriage = mission.autopilotEnabled === true || mission.autoAdvance === true;
144540
+ for (const feature of features) {
144541
+ if (supersededFeatureIds.has(feature.id) || feature.taskId || !autoTriage || feature.status === "blocked") continue;
144542
+ if (feature.status !== "defined" && this.isGeneratedFixFeature(feature)) {
144543
+ await missionStore.updateFeature(feature.id, { status: "blocked", loopState: "blocked", taskId: void 0 });
144544
+ fixed++;
144545
+ continue;
144546
+ }
144547
+ if (feature.status !== "defined" && feature.status !== "triaged" && feature.status !== "in-progress") continue;
144548
+ const ready = feature.status === "defined" ? feature : await missionStore.updateFeature(feature.id, { status: "defined", loopState: "idle", taskId: void 0 });
144549
+ if (ready !== feature) fixed++;
144550
+ const triaged = await missionStore.triageFeature(ready.id);
144296
144551
  fixed++;
144297
- continue;
144552
+ if (triaged.taskId) await this.emitStrandedFeatureTriageAudit(mission.id, slice.id, triaged.id, triaged.taskId);
144298
144553
  }
144299
- if (feature.status !== "defined" && feature.status !== "triaged" && feature.status !== "in-progress") continue;
144300
- const ready = feature.status === "defined" ? feature : await missionStore.updateFeature(feature.id, { status: "defined", loopState: "idle", taskId: void 0 });
144301
- if (ready !== feature) fixed++;
144302
- const triaged = await missionStore.triageFeature(ready.id);
144303
- fixed++;
144304
- if (triaged.taskId) await this.emitStrandedFeatureTriageAudit(mission.id, slice.id, triaged.id, triaged.taskId);
144554
+ } catch (error2) {
144555
+ schedulerLog.error(`Error during active mission recovery reconciliation for slice ${slice.id}:`, error2);
144305
144556
  }
144306
144557
  }
144307
144558
  }
@@ -148783,7 +149034,13 @@ var init_gating_classifications = __esm({
148783
149034
  "fn_post_room_message",
148784
149035
  "fn_update_identity",
148785
149036
  "fn_reflect_on_performance",
148786
- "fn_read_evaluations"
149037
+ /*
149038
+ FNXC:ToolGovernance 2026-08-12-22:11:
149039
+ fn_agent_read_evaluations is a subtree-scoped read. Authorization is enforced by
149040
+ the extension tool's getChainOfCommand boundary, not by this action classifier.
149041
+ */
149042
+ "fn_read_evaluations",
149043
+ "fn_agent_read_evaluations"
148787
149044
  ]);
148788
149045
  COORDINATION_EXEMPT_TOOLS = [
148789
149046
  "read",
@@ -148843,6 +149100,8 @@ var init_gating_classifications = __esm({
148843
149100
  "fn_post_room_message",
148844
149101
  "fn_memory_append",
148845
149102
  "fn_read_evaluations",
149103
+ // FNXC:ToolGovernance 2026-08-12-22:11: The manager read is subtree-authorized in extension.ts; follow-up remains absent so it falls back to task_agent_mutation policy.
149104
+ "fn_agent_read_evaluations",
148846
149105
  "fn_update_identity",
148847
149106
  "fn_reflect_on_performance"
148848
149107
  ];