@objectstack/console 17.3.0 → 17.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (188) hide show
  1. package/CHANGELOG.md +87 -0
  2. package/dist/.objectui-sha +1 -1
  3. package/dist/assets/{ActionResultDialog-CQwenjVA.js → ActionResultDialog-Bsr2GS71.js} +1 -1
  4. package/dist/assets/{AiPendingActionsPage-7gZ8zlOy.js → AiPendingActionsPage-DB-UVcdM.js} +1 -1
  5. package/dist/assets/{ApiConsolePage-DUF0ysH7.js → ApiConsolePage-Bzqo2owc.js} +1 -1
  6. package/dist/assets/{AppDocsIndex-CP_AVG4X.js → AppDocsIndex-KhVqdZ-P.js} +1 -1
  7. package/dist/assets/{AppManagementPage-BJktnoa5.js → AppManagementPage-CsZ0LMQn.js} +1 -1
  8. package/dist/assets/{ApprovalsInboxPage-DlnxY-uy.js → ApprovalsInboxPage-D_LOnhJ7.js} +1 -1
  9. package/dist/assets/{AuditLogPage-DIJPRjji.js → AuditLogPage-B9eqwuzl.js} +1 -1
  10. package/dist/assets/{ComponentNavView-C84QByT7.js → ComponentNavView-DeokLfkW.js} +1 -1
  11. package/dist/assets/{CreateViewDialog-Zbd9Cagm.js → CreateViewDialog-BMdQ4ZYy.js} +1 -1
  12. package/dist/assets/{DashboardView-UyKHklBx.js → DashboardView-DHZboRi8.js} +1 -1
  13. package/dist/assets/{DeveloperHubPage-BRyNdrCJ.js → DeveloperHubPage-C_VYirN0.js} +1 -1
  14. package/dist/assets/{DocPage-Bx8ZXCYt.js → DocPage-_9x-3Dbi.js} +1 -1
  15. package/dist/assets/{DocShell-Ipy_IDvh.js → DocShell-D4dSPfBz.js} +1 -1
  16. package/dist/assets/{DocsIndex-CmY-7OQR.js → DocsIndex-CJVRa_hE.js} +1 -1
  17. package/dist/assets/{DocsLayout-BNsSvaz2.js → DocsLayout-C-tYgUZv.js} +1 -1
  18. package/dist/assets/{DocsSlug-Cb_NMM1k.js → DocsSlug-DmyGpfEy.js} +1 -1
  19. package/dist/assets/{ExpressionProvider-DqGWVuxV.js → ExpressionProvider-B6z09kM6.js} +1 -1
  20. package/dist/assets/{FlowRunsPage-B6ustUgi.js → FlowRunsPage-OjGJi-JU.js} +1 -1
  21. package/dist/assets/{IntegrationsPage-chOxmiyU.js → IntegrationsPage-CrDMDe62.js} +1 -1
  22. package/dist/assets/{InterfaceListPage-DVETnQm5.js → InterfaceListPage-P3y6hqTX.js} +1 -1
  23. package/dist/assets/{MarketplaceInstalledPage-DA5pjhAz.js → MarketplaceInstalledPage-CQek7WnV.js} +1 -1
  24. package/dist/assets/{MarketplacePackagePage-dCIVHBFi.js → MarketplacePackagePage-DL2ivKSc.js} +1 -1
  25. package/dist/assets/{MarketplacePage-wJb6g1p7.js → MarketplacePage-B-6EokyB.js} +1 -1
  26. package/dist/assets/{MetadataInspector-Cu-n1FYz.js → MetadataInspector-IQGUoLyp.js} +1 -1
  27. package/dist/assets/{ObjectDataPage-CP-YSZYQ.js → ObjectDataPage-Bmc3RQhM.js} +1 -1
  28. package/dist/assets/{PageView-B1_ibRuM.js → PageView-DzUZqB_h.js} +1 -1
  29. package/dist/assets/{ProfilePage-DEr5iZVB.js → ProfilePage-NklCqPxc.js} +1 -1
  30. package/dist/assets/{PublicFormsPage-CBcKQbNl.js → PublicFormsPage-CItIvcLQ.js} +1 -1
  31. package/dist/assets/RecordDetailView-XWxuegfV.js +3 -0
  32. package/dist/assets/{RecordFormPage-CGQlYWDk.js → RecordFormPage-B-yrhs7J.js} +1 -1
  33. package/dist/assets/{ReportDefaultInspector-R_p6YStL.js → ReportDefaultInspector-D5Kro5_t.js} +1 -1
  34. package/dist/assets/{ReportView-BTMrtcGH.js → ReportView-COpZ8PQT.js} +1 -1
  35. package/dist/assets/{RuntimeDraftBar-agGU39FL.js → RuntimeDraftBar-CSVtuByp.js} +1 -1
  36. package/dist/assets/{SchemaForm-DJbupOno.js → SchemaForm-DIsxxOZF.js} +1 -1
  37. package/dist/assets/{SearchResultsPage-CHhZUc6L.js → SearchResultsPage-B2r6kgni.js} +1 -1
  38. package/dist/assets/{SettingsHub-BGLR_gS7.js → SettingsHub-DQz2HDtZ.js} +1 -1
  39. package/dist/assets/{SettingsView-Bq-7Zkzs.js → SettingsView-BfOEalDW.js} +1 -1
  40. package/dist/assets/{SkeletonDetail-B4-UKxai.js → SkeletonDetail-DMOa5zcl.js} +1 -1
  41. package/dist/assets/{SystemHubPage-CVZVag1e.js → SystemHubPage-DM2VRSIP.js} +1 -1
  42. package/dist/assets/{abnfDiagram-VCTEODGH-DUS5D5dU.js → abnfDiagram-VCTEODGH-DaPlU6Hz.js} +1 -1
  43. package/dist/assets/{app-shell-eager-leaves-BB0oaPx6.js → app-shell-eager-leaves-wjbiJgVZ.js} +1 -1
  44. package/dist/assets/architectureDiagram-5GKGNRK7-Cq014PwG.js +36 -0
  45. package/dist/assets/{blockDiagram-OSKFZWR5-Bz2hnVmp.js → blockDiagram-OSKFZWR5-vtlcoeZc.js} +1 -1
  46. package/dist/assets/{c4Diagram-7LVT6UL2-DU3u1Y6c.js → c4Diagram-7LVT6UL2-BrdwRG2M.js} +1 -1
  47. package/dist/assets/channel-D2IgUFnY.js +1 -0
  48. package/dist/assets/{chunk-3NF5O7KM-B8Q7HUio.js → chunk-3NF5O7KM-CjWAf_Jo.js} +1 -1
  49. package/dist/assets/{chunk-4HAMMTFA-BPKwX4iB.js → chunk-4HAMMTFA-BtV_msXT.js} +1 -1
  50. package/dist/assets/chunk-75Z2AOVW-DdRL9yNr.js +2 -0
  51. package/dist/assets/chunk-CLGD4ZFX-De9kMAXh.js +1 -0
  52. package/dist/assets/{chunk-DU6HZSFF-BkY4hAzc.js → chunk-DU6HZSFF-DqjylQO-.js} +1 -1
  53. package/dist/assets/chunk-F27PBJKO-tEB_K-iD.js +1 -0
  54. package/dist/assets/{chunk-GMAD6QVW-DZo_NykZ.js → chunk-GMAD6QVW-BMzd_HHM.js} +1 -1
  55. package/dist/assets/{chunk-GVQU2GXP-9ELY9S6X.js → chunk-GVQU2GXP-B1p1nHC0.js} +1 -1
  56. package/dist/assets/{chunk-H2I77ZZE-vCr_buP7.js → chunk-H2I77ZZE-ioXC4dHO.js} +1 -1
  57. package/dist/assets/{chunk-HLEWEB6X-iPkY2ESt.js → chunk-HLEWEB6X-zZ3ZMup3.js} +1 -1
  58. package/dist/assets/chunk-L3NEJ4N5-DePXufTQ.js +1 -0
  59. package/dist/assets/{chunk-LQGUR6SS-iVI0GACK.js → chunk-LQGUR6SS-BUWUp_dz.js} +1 -1
  60. package/dist/assets/{chunk-OSK3NFVY-DcRwXCQD.js → chunk-OSK3NFVY-L7nTUJKT.js} +2 -2
  61. package/dist/assets/{chunk-P2QGCYS3-nx2-dM5t.js → chunk-P2QGCYS3-BG-i3rdI.js} +1 -1
  62. package/dist/assets/{chunk-POPQ4Y6H-BxLOacOG.js → chunk-POPQ4Y6H-DLEB8EqK.js} +1 -1
  63. package/dist/assets/{chunk-PWAF6VOD-2mst9kZu.js → chunk-PWAF6VOD-Be_prJjm.js} +1 -1
  64. package/dist/assets/{chunk-SVP7TREG-C3BMpr4x.js → chunk-SVP7TREG-BdJpxJji.js} +1 -1
  65. package/dist/assets/chunk-XXDRQBXY-CEXsCcSu.js +1 -0
  66. package/dist/assets/{chunk-ZLD2IHE6-ZFqtFJbj.js → chunk-ZLD2IHE6-BLIPZykR.js} +1 -1
  67. package/dist/assets/classDiagram-CYGNFDIV-BielDdJQ.js +1 -0
  68. package/dist/assets/classDiagram-v2-TLXNO2FR-BielDdJQ.js +1 -0
  69. package/dist/assets/cose-bilkent-JH36ORCC-CnLWv9XE.js +1 -0
  70. package/dist/assets/{createDerive-Best2JCj.js → createDerive-DtfnFzGm.js} +1 -1
  71. package/dist/assets/{cynefinDiagram-5FMLGOSQ-Lnly8IJd.js → cynefinDiagram-5FMLGOSQ-Do1SZz4I.js} +1 -1
  72. package/dist/assets/{dagre-OS7QT2EB-CdXLxmTK.js → dagre-OS7QT2EB-CqmZ9Y9O.js} +1 -1
  73. package/dist/assets/data-adapter-1YRpH3h_.js +5 -0
  74. package/dist/assets/{default-inspector-registry-DeEG98bO.js → default-inspector-registry-CmSpNwTr.js} +1 -1
  75. package/dist/assets/{diagram-S7CK7UJ4-DE8I3gxQ.js → diagram-S7CK7UJ4-CMpcDWop.js} +1 -1
  76. package/dist/assets/{diagram-UQ7AKVKN-D2xQpbEq.js → diagram-UQ7AKVKN-DLK_4yej.js} +1 -1
  77. package/dist/assets/{diagram-VSXAHHWV-DnttDSlO.js → diagram-VSXAHHWV-MAILxw0S.js} +1 -1
  78. package/dist/assets/diagram-VX7I27RA-DGiXGVX7.js +24 -0
  79. package/dist/assets/{diagram-Z3DM3KII-BgB9f0Nv.js → diagram-Z3DM3KII-BywboeGI.js} +1 -1
  80. package/dist/assets/dist-B88JFSFg.js +5 -0
  81. package/dist/assets/{ebnfDiagram-PWID7BFC-32WvKbS2.js → ebnfDiagram-PWID7BFC-DdMLbnuP.js} +1 -1
  82. package/dist/assets/{erDiagram-2YWLMYGG-Dwf8uAdl.js → erDiagram-2YWLMYGG-O6raGx2P.js} +1 -1
  83. package/dist/assets/flowDiagram-T62WH6J4-CkAxOnqU.js +1 -0
  84. package/dist/assets/framework-DFE_Mws9.js +36 -0
  85. package/dist/assets/{ganttDiagram-EL5Y4UJY-DqYIE0Cu.js → ganttDiagram-EL5Y4UJY-Dijdjc50.js} +2 -2
  86. package/dist/assets/{getIcon-CgyYxSEC.js → getIcon-B4Pp7Q-0.js} +1 -1
  87. package/dist/assets/gitGraphDiagram-WWUBYQGX-Cfl4OIGG.js +106 -0
  88. package/dist/assets/{highlighted-body-OFNGDK62-BxO9mjPI.js → highlighted-body-OFNGDK62-BlqGRgbU.js} +1 -1
  89. package/dist/assets/{i18n-Cfqor-xb.js → i18n-DGcOKnTh.js} +1 -1
  90. package/dist/assets/{i18n-locales-Bz4c8KXc.js → i18n-locales-BBA090ve.js} +10 -10
  91. package/dist/assets/index-C5Fu9Kda.css +2 -0
  92. package/dist/assets/index-ClPLLRzK.js +20 -0
  93. package/dist/assets/{infoDiagram-FKFFQAWI-Cr1-5_Am.js → infoDiagram-FKFFQAWI-oOVNWlVA.js} +1 -1
  94. package/dist/assets/{infrastructure-CIpDEFyQ.js → infrastructure-B4zG1jNa.js} +2 -2
  95. package/dist/assets/{ishikawaDiagram-5VMMS53U-Bsjx7BsE.js → ishikawaDiagram-5VMMS53U-BUfTfup1.js} +1 -1
  96. package/dist/assets/{journeyDiagram-EYS64GPL-1scn5Z5c.js → journeyDiagram-EYS64GPL-4fyU8Ui9.js} +2 -2
  97. package/dist/assets/{kanban-definition-UXKFOSKX-DjLQAv5U.js → kanban-definition-UXKFOSKX-qwquHo2y.js} +1 -1
  98. package/dist/assets/mermaid-GHXKKRXX-_UhQGe8N.js +1 -0
  99. package/dist/assets/{mermaid.core-pW40dd4u.js → mermaid.core-RfBGJVq5.js} +2 -2
  100. package/dist/assets/{metadata-admin-pawEBYI9.js → metadata-admin-Bo-vWW2Z.js} +3 -3
  101. package/dist/assets/{mindmap-definition-THT77NOG-CUcYMB9H.js → mindmap-definition-THT77NOG-cOVHgGB_.js} +1 -1
  102. package/dist/assets/{pegDiagram-XKGWAZYB-CT1r3sRa.js → pegDiagram-XKGWAZYB-DQikOuPL.js} +1 -1
  103. package/dist/assets/{pieDiagram-E7YTZNPT-CSi-V1LQ.js → pieDiagram-E7YTZNPT-Cu9wPXiv.js} +2 -2
  104. package/dist/assets/plugin-calendar-DqlnPeWE.js +1 -0
  105. package/dist/assets/plugin-charts-hJ5C1pY-.js +7 -0
  106. package/dist/assets/{plugin-chatbot-BGnkLzFS.js → plugin-chatbot-BeSLDg4N.js} +5 -5
  107. package/dist/assets/plugin-dashboard-d1o52lHr.js +6 -0
  108. package/dist/assets/{plugin-form-_fjHxKTV.js → plugin-form-D8x_rH5w.js} +1 -1
  109. package/dist/assets/plugin-gantt-B2GTMGPH.js +63 -0
  110. package/dist/assets/plugin-grid-DGXy_yQF.js +9 -0
  111. package/dist/assets/{plugin-kanban-DA0eW6yj.js → plugin-kanban-CVf6Nj3e.js} +1 -1
  112. package/dist/assets/plugin-map-hkbw1bGS.js +1 -0
  113. package/dist/assets/{plugin-markdown-B7zwZHmn.js → plugin-markdown-Bdb2UThR.js} +4 -4
  114. package/dist/assets/plugin-report-CelulaB7.js +59 -0
  115. package/dist/assets/{plugin-timeline-B6rsNNAK.js → plugin-timeline-DTcJ-hts.js} +1 -1
  116. package/dist/assets/plugin-tree-Bk5vG9la.js +1 -0
  117. package/dist/assets/{plugin-view-5qxxRyZZ.js → plugin-view-CKs41t7o.js} +1 -1
  118. package/dist/assets/plugins-views-DZmsFOak.js +4 -0
  119. package/dist/assets/{quadrantDiagram-AXDQQJYC-DUJ_94hm.js → quadrantDiagram-AXDQQJYC-DqTU6p89.js} +3 -3
  120. package/dist/assets/{railroadDiagram-O6MQD6OU-CEyfAhzM.js → railroadDiagram-O6MQD6OU-CHGgIBKb.js} +1 -1
  121. package/dist/assets/{requirementDiagram-IS5BZ75X-CAK7hvBg.js → requirementDiagram-IS5BZ75X-B20mHS5h.js} +1 -1
  122. package/dist/assets/{runtime-metadata-persistence-DYPxFzHI.js → runtime-metadata-persistence-DzS2YaNb.js} +1 -1
  123. package/dist/assets/{sankeyDiagram-P5KCCOFB-DgYJh7uz.js → sankeyDiagram-P5KCCOFB-oqGY91Cw.js} +3 -3
  124. package/dist/assets/{sequenceDiagram-WJ2MYXX4-DsQerPtC.js → sequenceDiagram-WJ2MYXX4-CVMm7Aid.js} +1 -1
  125. package/dist/assets/{src-CVJP2nIc.js → src-D7tZqf12.js} +1 -1
  126. package/dist/assets/{src-_DxAIBqo.js → src-DCXZnd2l.js} +1 -1
  127. package/dist/assets/{src-S6pzKItc.js → src-DEMdKbQy.js} +1 -1
  128. package/dist/assets/src-hcMLuWxG.js +17 -0
  129. package/dist/assets/stateDiagram-XQSTLZYL-3oM7IdVe.js +1 -0
  130. package/dist/assets/stateDiagram-v2-IH3M54BS-BznjPAgb.js +1 -0
  131. package/dist/assets/studioEntry-BUFsLXCL.js +1 -0
  132. package/dist/assets/{submitRedirect-UXd9NsjL.js → submitRedirect-7ExeC4kw.js} +1 -1
  133. package/dist/assets/{swimlanes-V6O3JKXN-BiKyiEJr.js → swimlanes-V6O3JKXN-Djgbrkmh.js} +1 -1
  134. package/dist/assets/swimlanesDiagram-JKAHXJPX-DHJJ3qZq.js +8 -0
  135. package/dist/assets/{timeline-definition-24CTP7MA-CW5rY3PX.js → timeline-definition-24CTP7MA-k2lbfDvL.js} +2 -2
  136. package/dist/assets/ui-components-CMHDBJEm.js +37 -0
  137. package/dist/assets/{ui-layout-UUTFXV6S.js → ui-layout-Jk_qY9Ni.js} +1 -1
  138. package/dist/assets/{use-book-data-qUZAxIs0.js → use-book-data-CM73PGvc.js} +1 -1
  139. package/dist/assets/{useActionModal-CkM-zGdy.js → useActionModal-D_iilsul.js} +1 -1
  140. package/dist/assets/{usePackageL10n-F9isJ9pn.js → usePackageL10n-BfPqgsRL.js} +1 -1
  141. package/dist/assets/{useSettingsLabel-CSZBfUiw.js → useSettingsLabel-CW2sBbmj.js} +1 -1
  142. package/dist/assets/vendor-charts-BBlPrtHS.js +67 -0
  143. package/dist/assets/{vendor-i18n-C1AQDWux.js → vendor-i18n-CzBLXLJU.js} +1 -1
  144. package/dist/assets/vendor-objectstack-BU0HrnMy.js +270 -0
  145. package/dist/assets/{vendor-zod-r9lyeyrU.js → vendor-zod-Bwe8XZZa.js} +3 -3
  146. package/dist/assets/{vennDiagram-4TSXK5OY-C79cMc25.js → vennDiagram-4TSXK5OY-zweM554s.js} +1 -1
  147. package/dist/assets/{wardleyDiagram-VM6X3IG4-BAO0_jUk.js → wardleyDiagram-VM6X3IG4-Dg9r6Ajz.js} +1 -1
  148. package/dist/assets/{xychartDiagram-S5SC5T6Z-BIRd7YRo.js → xychartDiagram-S5SC5T6Z-CraplxeN.js} +2 -2
  149. package/dist/eager-closure.json +87 -87
  150. package/dist/index.html +4 -4
  151. package/package.json +1 -1
  152. package/dist/assets/RecordDetailView-A8bbPnkK.js +0 -3
  153. package/dist/assets/architectureDiagram-5GKGNRK7-mGW8P1lC.js +0 -36
  154. package/dist/assets/channel-FD4s9EIH.js +0 -1
  155. package/dist/assets/chunk-75Z2AOVW-CkSdnmiC.js +0 -2
  156. package/dist/assets/chunk-CLGD4ZFX-BTkDISwp.js +0 -1
  157. package/dist/assets/chunk-F27PBJKO-DUKg0YWV.js +0 -1
  158. package/dist/assets/chunk-L3NEJ4N5-Bzz35TZJ.js +0 -1
  159. package/dist/assets/chunk-XXDRQBXY-iNC8aYmk.js +0 -1
  160. package/dist/assets/classDiagram-CYGNFDIV-D5Pd2TCl.js +0 -1
  161. package/dist/assets/classDiagram-v2-TLXNO2FR-D5Pd2TCl.js +0 -1
  162. package/dist/assets/cose-bilkent-JH36ORCC-CPQv9aQH.js +0 -1
  163. package/dist/assets/data-adapter-DL25qpAe.js +0 -5
  164. package/dist/assets/diagram-VX7I27RA-BSEwkn7K.js +0 -24
  165. package/dist/assets/dist-BpPy7hlB.js +0 -5
  166. package/dist/assets/flowDiagram-T62WH6J4-CqVSNJ8T.js +0 -1
  167. package/dist/assets/framework-BfSv4Kb0.js +0 -36
  168. package/dist/assets/gitGraphDiagram-WWUBYQGX-D1dYmoGu.js +0 -106
  169. package/dist/assets/index-BU-FzlQ6.js +0 -20
  170. package/dist/assets/index-_VyGO4ms.css +0 -2
  171. package/dist/assets/mermaid-GHXKKRXX-NzEcDxBh.js +0 -1
  172. package/dist/assets/plugin-calendar-BwiiCIjv.js +0 -1
  173. package/dist/assets/plugin-charts-CDGkx7z5.js +0 -7
  174. package/dist/assets/plugin-dashboard-Bj4ldCX6.js +0 -6
  175. package/dist/assets/plugin-gantt-zR8DkpEg.js +0 -63
  176. package/dist/assets/plugin-grid-kkbz4uec.js +0 -9
  177. package/dist/assets/plugin-map-DukneTNg.js +0 -1
  178. package/dist/assets/plugin-report-DaPtlsJr.js +0 -59
  179. package/dist/assets/plugin-tree-DauauLFc.js +0 -1
  180. package/dist/assets/plugins-views-iYcMmImr.js +0 -4
  181. package/dist/assets/src-JX1BkhmR.js +0 -17
  182. package/dist/assets/stateDiagram-XQSTLZYL-BJndPKik.js +0 -1
  183. package/dist/assets/stateDiagram-v2-IH3M54BS-Bi94bTLl.js +0 -1
  184. package/dist/assets/studioEntry-C6G8U-LG.js +0 -1
  185. package/dist/assets/swimlanesDiagram-JKAHXJPX-DKIR852g.js +0 -8
  186. package/dist/assets/ui-components-D2lrjG-t.js +0 -43
  187. package/dist/assets/vendor-charts-CY9WhhzX.js +0 -67
  188. package/dist/assets/vendor-objectstack-BeKUVjuj.js +0 -270
@@ -1,5 +0,0 @@
1
- import{$ as e,An as t,At as n,B as r,Bt as i,C as a,D as o,Dt as s,E as c,En as l,F as u,G as d,Gn as f,Hn as p,Ht as m,I as h,It as g,J as _,Jn as v,K as y,Kn as b,Ln as x,Lt as ee,M as te,Nt as ne,O as re,Ot as ie,P as ae,Q as oe,Qt as se,R as ce,Rt as le,S as ue,Un as de,Ut as fe,V as pe,W as me,Wn as he,Wt as ge,X as _e,Xt as ve,Y as ye,Yt as be,Z as xe,Zt as Se,_ as Ce,_t as we,b as Te,bt as Ee,c as De,d as Oe,et as ke,f as Ae,fn as je,ft as Me,g as Ne,gt as Pe,h as Fe,i as Ie,it as Le,j as Re,jn as ze,k as Be,l as Ve,mn as He,mt as Ue,ot as We,pn as Ge,pt as Ke,qn as qe,r as Je,s as Ye,u as Xe,vt as Ze,w as Qe,x as $e,xt as et,y as tt,yt as nt,zt as rt}from"./vendor-objectstack-BeKUVjuj.js";ie();var S=v(),it=new Set([...We,...Object.values(Xe)]);function at(e){return m(e).names}function ot(e){return new Set(ge(e))}function st(e){if(!e||typeof e!=`object`)return[];let t=e.objects;return Array.isArray(t)?t.filter(e=>!!e&&typeof e==`object`):t&&typeof t==`object`?Object.entries(t).filter(([,e])=>!!e&&typeof e==`object`).map(([e,t])=>({name:e,...t})):[]}function ct(e){let t=new Map;for(let n of st(e)){let e=typeof n.name==`string`&&n.name.length>0?n.name:void 0;if(!e)continue;let r=ot(n);r.size>0&&t.set(e,r)}return t}function C(e,t){return`'${t}' is an injected system column with NO storage behind it: '${e}' is an external object (ADR-0015), so the remote database owns its schema and the platform registers this anchor without provisioning a column`}function w(e,t){return`If the remote table really carries '${t}', declare it in ${e}'s own fields (mapped through the external binding's columnMap) so the reference resolves to a column you vouch for; otherwise drop the reference, or opt the object out of the injection (\`ownership: 'none'\` for the ownership anchors, \`systemFields: { audit: false }\` for the audit family).`}var lt=`widget-dataset-unknown`,ut=`widget-dimension-unknown`,dt=`widget-measure-unknown`,ft=`chart-field-unknown`,pt=`chart-config-missing`,mt=`table-count-only`,ht=`measure-aggregate-incoherent`,gt=`widget-legacy-analytics-shape`,_t=`widget-legacy-analytics-unrenderable`,vt=`dashboard-filter-field-unknown`,yt=`dashboard-filter-field-unprovisioned`,bt=[`categoryField`,`valueField`,`xAxisField`,`yAxisFields`,`aggregate`,`aggregation`,`rowField`,`columnField`];function xt(e){return Array.isArray(e)?e:e&&typeof e==`object`?Object.entries(e).map(([e,t])=>({name:e,...t})):[]}function St(e){return Array.isArray(e)?e.filter(e=>typeof e==`string`):[]}var Ct=new Set([`gauge`,`solid-gauge`,`metric`,`kpi`,`bullet`,`table`,`pivot`]),wt=new Set(Se.options.filter(e=>!Ct.has(e)));function Tt(e,t){let n=e.length,r=t.length,i=Array.from({length:r+1},(e,t)=>t);for(let a=1;a<=n;a++){let n=[a];for(let o=1;o<=r;o++)n[o]=Math.min(i[o]+1,n[o-1]+1,i[o-1]+(e[a-1]===t[o-1]?0:1));i=n}return i[r]}function Et(e,t){let n,r=1/0;for(let i of t){let t;if(e.length>=3&&(i.includes(e)||e.includes(i)))t=Math.abs(i.length-e.length);else{let n=Tt(e,i);if(n>Math.max(2,Math.floor(e.length/3)))continue;t=100+n}t<r&&(r=t,n=i)}return n}function Dt(e,t){let n=Et(e,t);return n?` Did you mean "${n}"?`:``}function T(e){let t=[...e];return t.length>0?t.join(`, `):`(none)`}var Ot=`dateRange`,kt=`created_at`;function At(e){let t=new Map,n=e.dateRange;if(n&&typeof n==`object`){let e=n.field,r=typeof e==`string`&&e?e:kt;t.set(Ot,{name:Ot,field:r})}for(let n of xt(e.globalFilters)){if(typeof n.field!=`string`||!n.field)continue;let e=typeof n.name==`string`&&n.name?n.name:n.field,r=Array.isArray(n.targetWidgets)?n.targetWidgets.filter(e=>typeof e==`string`):void 0;t.set(e,{name:e,field:n.field,targetWidgets:r})}return[...t.values()]}function jt(e,t){let n=e.filterBindings,r=n&&typeof n==`object`?n[t.name]:void 0;if(r!==!1){if(typeof r==`string`&&r)return{field:r,explicit:!0};if(t.targetWidgets&&t.targetWidgets.length>0){let n=typeof e.id==`string`?e.id:void 0;if(!n||!t.targetWidgets.includes(n))return}return{field:t.field,explicit:!1}}}function Mt(e){let t=[],n=new Map;for(let t of xt(e.datasets))typeof t.name==`string`&&n.set(t.name,t);let r=new Map;for(let t of xt(e.objects)){if(typeof t.name!=`string`)continue;let e=new Map;for(let n of xt(t.fields))typeof n.name==`string`&&typeof n.type==`string`&&e.set(n.name,n.type);r.set(t.name,e)}let i=ct(e),a=xt(e.datasets);for(let e=0;e<a.length;e++){let n=a[e],i=typeof n.object==`string`?r.get(n.object):void 0;if(!i)continue;let o=xt(n.measures);for(let r=0;r<o.length;r++){let a=o[r],s=typeof a.field==`string`?a.field:void 0,c=typeof a.aggregate==`string`?a.aggregate:void 0;if(!s||!c)continue;let l=i.get(s);l&&ne(c,l)&&t.push({severity:`warning`,rule:ht,where:`dataset "${typeof n.name==`string`?n.name:`(dataset ${e})`}" \u203A measure "${typeof a.name==`string`?a.name:`(measure ${r})`}"`,path:`datasets[${e}].measures[${r}]`,message:`measure "${a.name}" applies ${c} to ${l} field "${s}" \u2014 summed percentages are meaningless (they can exceed 100%).`,hint:`Use aggregate "avg" for percentage/rate fields (or "count" of records). If a running total is genuinely intended, suppress with: suppressWarnings: ['${ht}'] on the measure.`})}}let o=xt(e.dashboards);for(let e=0;e<o.length;e++){let a=o[e],s=typeof a.name==`string`?a.name:`(dashboard ${e})`,c=Array.isArray(a.widgets)?a.widgets:[],l=At(a);for(let a=0;a<c.length;a++){let o=c[a],u=`dashboard "${s}" \u203A widget "${typeof o.id==`string`?o.id:`(widget ${a})`}"`,d=`dashboards[${e}].widgets[${a}]`,f=e=>Array.isArray(o.suppressWarnings)&&o.suppressWarnings.includes(e),p=e=>{e.severity===`warning`&&f(e.rule)||t.push({...e,where:u,path:d})},m=bt.filter(e=>o[e]!==void 0);if(m.length>0){let e=typeof o.options==`object`&&o.options!==null&&o.options.data!==void 0,t=o.dataset!==void 0||o.object!==void 0||o.data!==void 0||e,n=m.map(e=>`\`${e}\``).join(`, `),r=m.length>1,i="Bind a semantic dataset and select fields BY NAME: `dataset: '<name>', dimensions: [...], values: [...]`. Dataset-bound widgets render through DatasetWidget (pivot rows/cols come from `dimensions`, cell values from `values`).";p(t?{severity:`warning`,rule:gt,message:`sets legacy analytics key${r?`s`:``} ${n} that the ADR-0021 single-form cutover removed \u2014 the dashboard renderer ignores ${r?`them`:`it`}.`,hint:`${i} These inline keys are a no-op. Suppress with suppressWarnings: ['${gt}'] if intentional.`}:{severity:`error`,rule:_t,message:`sets legacy analytics key${r?`s`:``} ${n} (removed by the ADR-0021 single-form cutover) and binds no data source (no \`dataset\`, \`object\`, or inline \`data\`) \u2014 it renders nothing.`,hint:`${i} The renderer ignores the legacy keys, so without a data source this widget has no data at all.`})}let h=typeof o.dataset==`string`?o.dataset:void 0,g=h?n.get(h):void 0;if(h&&!g&&p({severity:`error`,rule:lt,message:`dataset "${h}" does not resolve to a declared dataset.`,hint:`Declared datasets: ${T(n.keys())}.${Dt(h,n.keys())} Define the dataset with defineDataset() or fix the reference (ADR-0021).`}),!h){p({severity:`error`,rule:lt,message:"binds no `dataset` — the ADR-0021 widget shape requires one, so this widget resolves no data and renders empty.",hint:`Set \`dataset: '<name>'\` (plus \`values\`, and \`dimensions\` where the chart family needs them). Declared datasets: ${T(n.keys())}.`});continue}if(!g)continue;if(l.length>0){let e=typeof g.object==`string`?g.object:void 0,t=e?r.get(e):void 0,n=e?i.get(e):void 0;if(t&&e)for(let r of l){let i=jt(o,r);if(!i)continue;let a=i.field;if(!a.includes(`.`)){if(t.has(a)||it.has(a)){n?.has(a)&&p({severity:`warning`,rule:yt,message:(i.explicit?`binds dashboard filter \`${r.name}\` to field \`${a}\` (via filterBindings), but `:`inherits dashboard filter \`${r.name}(${a})\`, but `)+`${C(e,a)}. The filter is ANDed into this widget's analytics query (#2501), so it can never match a real value \u2014 on SQLite it silently degrades to constant-false and the widget renders empty (HTTP 200, zero rows, no error).`,hint:`${w(e,a)} A widget can also opt out with filterBindings: { ${r.name}: false }. Suppress with suppressWarnings: ['${yt}'] if the remote schema resolves it some other way.`});continue}p({severity:`error`,rule:vt,message:i.explicit?`binds dashboard filter \`${r.name}\` to field \`${a}\` (via filterBindings), but object \`${e}\` (dataset "${h}") has no field \`${a}\`.`:`inherits dashboard filter \`${r.name}(${a})\`, but object \`${e}\` (dataset "${h}") has no field \`${a}\`.`,hint:i.explicit?`Point filterBindings: { ${r.name}: '<field>' } at a field that exists on \`${e}\`, or opt out with filterBindings: { ${r.name}: false }.${Dt(a,t.keys())} Object fields: ${T(t.keys())}.`:`Set filterBindings: { ${r.name}: false } on this widget to opt out, or re-target to an existing field with filterBindings: { ${r.name}: '<field>' }.${Dt(a,t.keys())} Object fields: ${T(t.keys())}.`})}}}let _=new Set;for(let e of xt(g.dimensions))typeof e.name==`string`&&_.add(e.name);let v=new Map;for(let e of xt(g.measures))typeof e.name==`string`&&v.set(e.name,e);let y=St(o.dimensions);for(let e=0;e<y.length;e++)_.has(y[e])||p({severity:`error`,rule:ut,message:`dimensions[${e}] "${y[e]}" is not a dimension of dataset "${h}" (declared dimensions: ${T(_)}).`,hint:`Widgets select dataset dimensions BY NAME.${Dt(y[e],_)} Add the dimension to the dataset or fix the reference.`});let b=St(o.values);for(let e=0;e<b.length;e++)v.has(b[e])||p({severity:`error`,rule:dt,message:`values[${e}] "${b[e]}" is not a measure of dataset "${h}" (declared measures: ${T(v.keys())}).`,hint:`Widgets select dataset measures BY NAME, not by base column.${Dt(b[e],v.keys())} Add the measure to the dataset or fix the reference.`});let x=o.chartConfig&&typeof o.chartConfig==`object`?o.chartConfig:void 0,ee=typeof o.type==`string`&&wt.has(o.type);if(x){let e=new Set(b.filter(e=>v.has(e))),t=x.xAxis&&typeof x.xAxis==`object`?x.xAxis:void 0;t&&typeof t.field==`string`&&!_.has(t.field)&&!y.includes(t.field)&&p({severity:`error`,rule:ft,message:`chartConfig.xAxis.field "${t.field}" does not resolve to a dimension of dataset "${h}" (declared dimensions: ${T(_)}).`,hint:`Point xAxis.field at a dataset dimension name.${Dt(t.field,_)}`});let n=(t,n)=>{if(b.includes(n))return;let r=v.has(n);p({severity:`error`,rule:ft,message:r?`chartConfig.${t} "${n}" is a measure of dataset "${h}" but is not selected in the widget's values (${T(b)}), so the query result will not contain it.`:`chartConfig.${t} "${n}" does not resolve to a measure of dataset "${h}" (declared measures: ${T(v.keys())}).`,hint:r?`Add "${n}" to the widget's values, or bind the chart to a selected measure.`:`Post-cutover data is keyed by the dataset's measure NAME, not the base column.${Dt(n,e.size>0?e:v.keys())}`})},r=Array.isArray(x.yAxis)?x.yAxis:[];for(let e=0;e<r.length;e++){let t=r[e]?.field;typeof t==`string`&&n(`yAxis[${e}].field`,t)}let i=Array.isArray(x.series)?x.series:[];for(let e=0;e<i.length;e++){let t=i[e]?.name;typeof t==`string`&&n(`series[${e}].name`,t)}}else ee&&p({severity:`warning`,rule:pt,message:`chart-type widget ('${o.type}') has no chartConfig \u2014 the renderer cannot determine which measure to plot, so the series renders empty.`,hint:`Add chartConfig with xAxis.field set to a dimension (${T(y)}) and yAxis[].field set to a measure name (${T(b)}). If the default rendering is intentional, suppress with: suppressWarnings: ['${pt}']`});if(o.type!==`table`&&o.type!==`pivot`||y.length>0||b.length===0)continue;let te=b.map(e=>v.get(e));te.some(e=>!e)||te.every(e=>e.aggregate===`count`&&!e.derived)&&p({severity:`warning`,rule:mt,message:`a '${o.type}' widget bound to dataset "${h}" selects only count measure(s) (${b.join(`, `)}) and no dimensions, so it renders a single summary row \u2014 not a per-record list.`,hint:`A flat record listing is not an analytics dataset. Model it as an object-bound ListView (ADR-0017) surfaced through app navigation, and use a 'metric' widget here if you only need the count. If a single-row table is intentional, add an explicit dimension or suppress with: suppressWarnings: ['${mt}']`})}}return t}var Nt=`Guard it with '!= null' — 'has(x)' does NOT do that: a declared field holding null is still PRESENT, so has(x) is true.`,Pt=new Set([`<`,`<=`,`>`,`>=`,`+`,`-`,`*`,`/`,`%`]),Ft=[`record`,`previous`];function E(e){return!!e&&typeof e==`object`&&typeof e.op==`string`}function It(e){return E(e)&&e.op===`value`&&e.args===null}function Lt(e,t){if(!E(e)||e.op!==`.`&&e.op!==`.?`)return null;let n=e.args;if(!Array.isArray(n)||n.length<2)return null;let[r,i]=n;if(typeof i!=`string`||!E(r)||r.op!==`id`)return null;let a=r.args;return typeof a!=`string`||!t.includes(a)?null:{operand:`${a}.${i}`,field:i}}function Rt(e){let t=e.args;if(E(t))return[t];if(!Array.isArray(t))return[];let n=[];for(let e of t)if(E(e))n.push(e);else if(Array.isArray(e))for(let t of e)E(t)&&n.push(t);return n}function zt(e){if(e.op!==`call`)return null;let t=e.args;return!Array.isArray(t)||typeof t[0]!=`string`?null:t[0]}function Bt(e){let t=e.args;return!Array.isArray(t)||!Array.isArray(t[1])?[]:t[1]}function Vt(e,t){return new Set([...e,...t])}function Ht(e,t){let n=new Set;for(let r of e)t.has(r)&&n.add(r);return n}function Ut(e,t){if(!E(e))return new Set;switch(e.op){case`!=`:{let[n,r]=e.args??[];if(It(r)){let e=Lt(n,t);return e?new Set([e.operand]):new Set}if(It(n)){let e=Lt(r,t);return e?new Set([e.operand]):new Set}return new Set}case`&&`:{let[n,r]=e.args;return Vt(Ut(n,t),Ut(r,t))}case`||`:{let[n,r]=e.args;return Ht(Ut(n,t),Ut(r,t))}case`!_`:return Wt(e.args,t);case`?:`:{let[,n,r]=e.args;return Ht(Ut(n,t),Ut(r,t))}default:return new Set}}function Wt(e,t){if(!E(e))return new Set;switch(e.op){case`==`:{let[n,r]=e.args??[];if(It(r)){let e=Lt(n,t);return e?new Set([e.operand]):new Set}if(It(n)){let e=Lt(r,t);return e?new Set([e.operand]):new Set}return new Set}case`||`:{let[n,r]=e.args;return Vt(Wt(n,t),Wt(r,t))}case`&&`:{let[n,r]=e.args;return Ht(Wt(n,t),Wt(r,t))}case`!_`:return Ut(e.args,t);case`call`:{if(zt(e)!==`isBlank`)return new Set;let[n]=Bt(e),r=Lt(n,t);return r?new Set([r.operand]):new Set}default:return new Set}}function Gt(e,t,n){if(E(e)){if(zt(e)===`has`)for(let r of Bt(e)){let e=Lt(r,t);e&&n.add(e.operand)}for(let r of Rt(e))Gt(r,t,n)}}function Kt(e,t){if(typeof e!=`string`||!e.trim()||t.nullableFields.size===0)return[];let n=t.roots??Ft,r=xe(e);if(!r)return[];let i=new Set;Gt(r,n,i);let a=[],o=new Set,s=(e,r,s)=>{let c=Lt(e,n);if(!c||!t.nullableFields.has(c.field)||s.has(c.operand))return;let l=`${c.operand}\0${r}`;o.has(l)||(o.add(l),a.push({operand:c.operand,field:c.field,operator:r,hasOnlyGuard:i.has(c.operand)}))},c=(e,t)=>{if(!E(e))return;let r=e.op;if(r===`&&`){let[r,i]=e.args;c(r,t),c(i,Vt(t,Ut(r,n)));return}if(r===`||`){let[r,i]=e.args;c(r,t),c(i,Vt(t,Wt(r,n)));return}if(r===`?:`){let[r,i,a]=e.args;c(r,t),c(i,Vt(t,Ut(r,n))),c(a,Vt(t,Wt(r,n)));return}if(r!==`call`||zt(e)!==`has`){if(Pt.has(r)){let[n,i]=e.args;s(n,r,t),s(i,r,t),c(n,t),c(i,t);return}if(r===`-_`){s(e.args,`-`,t),c(e.args,t);return}for(let n of Rt(e))c(n,t)}};return c(r,new Set),a}var qt={"fail-closed":`so the rule enforces nothing and the write is rejected fail-closed (#4649/#4763)`,"fail-open":"so the predicate is SKIPPED fail-open — the field is never actually required, the write proceeds unchecked, and the only trace is a `requiredWhen … failed to evaluate — skipped` log line (#4649/#4811)"};function Jt(e,t,n,r=`fail-closed`){let i=t?`'${t}'`:`this object`,a=n.hasOnlyGuard?` \`has(${n.operand})\` does not guard it.`:``;return`${e} applies \`${n.operator}\` to \`${n.operand}\`, which ${i} declares as nullable (no \`required: true\`, no \`defaultValue\`).${a} At runtime the operand is null, CEL has no \`${n.operator}\` overload for null, and the whole predicate aborts \u2014 ${qt[r]}. The predicate compares a value that is null. ${Nt}`}function Yt(e){return Array.isArray(e)?e:e&&typeof e==`object`?Object.entries(e).map(([e,t])=>({name:e,...t})):[]}function Xt(e){let t=new Map;for(let n of e){let e=typeof n.name==`string`?n.name:void 0;if(!e)continue;let r=n.fields,i=[];Array.isArray(r)?i=r.map(e=>e.name).filter(e=>typeof e==`string`):r&&typeof r==`object`&&(i=Object.keys(r)),t.set(e,[...new Set([...i,...at(n)])])}return t}var Zt=[`record`,`previous`];function Qt(e){return!!e&&typeof e==`object`&&typeof e.op==`string`}function $t(e){let t=new Map,n=xe(e);if(!n)return t;let r=[n];for(;r.length>0;){let e=r.pop();if(!Qt(e))continue;if((e.op===`.`||e.op===`.?`)&&Array.isArray(e.args)&&e.args.length>=2){let[n,r]=e.args;typeof r==`string`&&Qt(n)&&n.op===`id`&&typeof n.args==`string`&&Zt.includes(n.args)&&(t.has(r)||t.set(r,`${n.args}.${r}`))}let n=e.args;if(Qt(n))r.push(n);else if(Array.isArray(n)){for(let e of n)if(Qt(e))r.push(e);else if(Array.isArray(e))for(let t of e)Qt(t)&&r.push(t)}}return t}function en(e){let t=new Map;for(let n of e){let e=typeof n.name==`string`?n.name:void 0;if(!e)continue;let r=n.fields,i={};if(Array.isArray(r))for(let e of r){let t=e?.name,n=e?.type;typeof t==`string`&&typeof n==`string`&&(i[t]=n)}else if(r&&typeof r==`object`)for(let[e,t]of Object.entries(r)){let n=t?.type;typeof n==`string`&&(i[e]=n)}t.set(e,i)}return t}function tn(e){let t=e.fields;return Array.isArray(t)?t.filter(e=>e&&typeof e==`object`&&typeof e.name==`string`).map(e=>[e.name,e]):t&&typeof t==`object`?Object.entries(t).filter(([,e])=>!!e&&typeof e==`object`).map(([e,t])=>[e,t]):[]}function nn(e){if(e.required===!0||e.defaultValue!==void 0&&e.defaultValue!==null||e.type===`autonumber`)return!1;let t=e.options;return!(Array.isArray(t)&&t.some(e=>!!e&&typeof e==`object`&&e.default===!0))}function rn(e){let t=new Map;for(let n of e){let e=typeof n.name==`string`?n.name:void 0;if(!e)continue;let r=new Set;for(let[e,t]of tn(n))nn(t)&&r.add(e);t.set(e,r)}return t}function an(e){let t=d(e);return t.ok&&t.roots.includes(`parent`)}function on(e){let t=0;for(let[,n]of tn(e)){if(n.type!==`master_detail`)continue;let e=n.reference;typeof e==`string`&&e.trim()!==``&&(t+=1)}return t}function sn(e){if(typeof e==`string`)return e;if(e&&typeof e==`object`){let t=e;if(typeof t.dialect==`string`&&t.dialect!==`cel`)return;if(typeof t.source==`string`)return t.source}}function cn(e,t){let n=[],r=typeof e.name==`string`?e.name:`?`,i=t?`${t} \u2192 '${r}'`:`'${r}'`,a=e.condition;a!=null&&n.push({label:`validation rule ${i}`,raw:a}),e.when!=null&&n.push({label:`validation rule ${i} when-predicate`,raw:e.when});for(let t of[`then`,`otherwise`]){let r=e[t];r&&typeof r==`object`&&!Array.isArray(r)&&n.push(...cn(r,`${i} ${t}`))}return n}function ln(e){let t=[],n=Yt(e.objects),r=Xt(n),i=en(n),a=rn(n),s=new Map;for(let e of n){let t=typeof e.name==`string`?e.name:void 0;if(!t)continue;let n=ot(e);n.size>0&&s.set(t,n)}let c=(e,n,r)=>{if(!r)return;let i=s.get(r);if(!i)return;let a=sn(n);if(a)for(let[n,o]of $t(a))i.has(n)&&t.push({where:e,message:`\`${o}\` reads '${n}', an injected system column with NO storage behind it: '${r}' is an external object (ADR-0015), so the remote database owns its schema and the platform registers this anchor without provisioning a column. The predicate can never match a real value \u2014 on SQLite it silently degrades to constant-false (HTTP 200, zero rows, no error). If the remote table really carries this column, declare '${n}' in the object's own fields (mapped through the external binding's columnMap) so the reference resolves to a column you vouch for; otherwise drop the reference, or opt the object out of the injection (\`ownership: 'none'\` for the ownership anchors, \`systemFields: { audit: false }\` for the audit family).`,source:a,severity:`warning`})},l=(e,n,r,i,o=`fail-closed`)=>{if(!i)return;let s=a.get(i);if(!s||s.size===0)return;let c=sn(r);if(c)for(let r of Kt(c,{nullableFields:s}))t.push({where:e,message:Jt(n,i,r,o),source:c,severity:`error`})},u=(e,n,a,o=`flattened`)=>{if(n==null)return;let s=a?r.get(a):void 0,l=a?i.get(a):void 0,u=ke(`predicate`,n,a?{objectName:a,fields:s,fieldTypes:l,scope:o}:{scope:o});for(let n of u.errors)t.push({where:e,message:n.message,source:n.source,severity:`error`});for(let n of u.warnings)t.push({where:e,message:n.message,source:n.source,severity:`warning`});c(e,n,a)},f=[`record`,`previous`,`parent`],p=[`current_user`,`user`,`ctx`,`os`],m=`the predicate faults, and a faulting rule never produces the verdict you declared — each slot resolves the fault to its own fallback, and none of those fallbacks is yours`,h={visibleWhen:"the predicate faults and the renderer falls back to VISIBLE (`resolveFieldRuleState` evaluates visibility with `fallback: true`, and no server-side gate evaluates a field-level `visibleWhen` at all), leaving the field the test was meant to hide showing for everyone (#6146)",readonlyWhen:"the predicate faults — and the two ends fault in OPPOSITE directions. The server treats the field as LOCKED (`isReadonlyWhenLocked` will not waive a declared lock it could not evaluate, #4889) and drops your value from the payload, while the form still renders the field editable (`fallback: false`). The server is the one that decides: the field looks writable, the save reports success, and the value silently never lands",requiredWhen:`the predicate faults and the requirement is never enforced anywhere — the server logs it and SKIPS the check (fail-open, #4977 deliberately did not take #4889's carve-out) and the form does not mark the field required either, so a record saves with the field empty`,conditionalRequired:m},g=(e,n,r)=>{let i=sn(r);if(!i)return;let a=d(i);if(!a.ok)return;let o=me.filter(e=>!f.includes(e)&&a.roots.includes(e));if(o.length===0)return;let s=p.find(e=>o.includes(e))??o[0],c=p.includes(s)?"To gate the CHOICES of a select by user, move the predicate to the option's own `visibleWhen` (`options: [{ …, visibleWhen: … }]`) — per-option is the one `*When` surface that binds `current_user` and its ADR-0068 aliases. To hide the FIELD by role, declare field-level security on a permission set (`fields: { '<object>.<field>': { readable: false } }`), which the server enforces. To gate on record state, rewrite the predicate against `record`.":s===`data`?"`data` is the root of a METADATA form (a `*.form` module — the metadata row being edited); this is an OBJECT field, whose runtime form binds the row as `record` — one key name, two form kinds, two roots. Rewrite `data.<key>` as `record.<field>`.":`\`${s}\` is declared platform-wide and bound at OTHER evaluation sites (flow, automation, screen and action predicates), never at the field level. Rewrite the predicate against \`record\` (plus \`previous\`, and \`parent\` on a master-detail line item), or move the decision to a surface that binds \`${s}\`.`;t.push({where:e,message:`\`${n}\` reads \`${s}\`, but a field-level conditional rule binds only \`record\` (plus \`previous\`, and \`parent\` on a master-detail line item) \u2014 \`${s}\` is unbound here, so ${h[n]??m}. `+c,source:i,severity:`error`})},_=(e,n)=>{if(n==null)return;let r=ke(`predicate`,n);for(let n of r.errors)t.push({where:e,message:n.message,source:n.source,severity:`error`});for(let n of r.warnings)t.push({where:e,message:n.message,source:n.source,severity:`warning`})};for(let n of Yt(e.flows)){let e=typeof n.name==`string`?n.name:`(unnamed flow)`,r=(Array.isArray(n.nodes)?n.nodes:[]).find(e=>e.type===`start`)?.config??{},i=typeof r.objectName==`string`?r.objectName:void 0;for(let r of o(n)){let n=r.scope?`flow '${e}' \xB7 ${r.scope}`:`flow '${e}'`;for(let e of r.nodes){let r=e.config??{};u(`${n} \xB7 node '${e.id}' (${e.type}) condition`,r.condition,i);let a=typeof e.type==`string`?e.type:``;for(let t of Be(a,r))t.entry.role===`predicate`&&_(`${n} \xB7 node '${e.id}' (${a}) ${t.entry.label} at config.${t.path}`,t.value);if(e.type===`script`){let i=(typeof r.function==`string`?r.function.trim():``)||(typeof r.functionName==`string`?r.functionName.trim():``),a=typeof r.actionType==`string`?r.actionType.trim():``,o=[`actionType`,`template`,`recipients`,`variables`,`script`].filter(e=>r[e]!=null);o.length>0?t.push({where:`${n} \xB7 node '${e.id}' (script) callable`,message:`script node carries \`${o.map(e=>`config.${e}`).join("`, `")}\` \u2014 retired in @objectstack/spec 17 (#4343). The built-in 'email'/'slack' actions were logger-backed stubs that delivered nothing, and inline \`config.script\` was never executed. `+(a&&a!==`invoke_function`&&![`email`,`slack`].includes(a)?`\`actionType: '${a}'\` named a registered function \u2014 move it to \`function: '${a}'\`. `:"Use a `notify` node for mail, a `connector_action` (Slack connector) or `http` node for Slack, and a registered function for logic. ")+"Run `os migrate meta --from 16` to list the mechanical edits for existing sources; apply them by hand.",source:JSON.stringify({id:e.id,type:e.type,config:r})}):i||t.push({where:`${n} \xB7 node '${e.id}' (script) callable`,message:"script node declares no `function` — it would do nothing at runtime. Name a registered function (`function: 'my_fn'`, registered via `defineStack({ functions })`).",source:JSON.stringify({id:e.id,type:e.type,config:r})})}}for(let e of r.edges)u(`${n} \xB7 edge '${e.id}' (${e.source}\u2192${e.target}) condition`,e.condition,i)}}for(let e of n){let n=typeof e.name==`string`?e.name:void 0,a=e.validations;for(let e of Yt(a)){let t=`object '${n}' \xB7 validation '${e.name??`?`}'`;u(t,e.condition,n,`record`),u(`${t} when`,e.when,n,`record`);for(let t of cn(e,``))l(`object '${n}' \xB7 ${t.label}`,t.label,t.raw,n)}let o=e.fields,s=Array.isArray(o)?o.filter(e=>!!e&&typeof e==`object`).map(e=>[typeof e.name==`string`?e.name:`?`,e]):o&&typeof o==`object`?Object.entries(o).filter(([,e])=>!!e&&typeof e==`object`).map(([e,t])=>[e,t]):[],d=on(e);for(let[e,a]of s){for(let t of[`requiredWhen`,`readonlyWhen`,`conditionalRequired`,`visibleWhen`])u(`object '${n}' \xB7 field '${e}' ${t}`,a[t],n,`record`),g(`object '${n}' \xB7 field '${e}' ${t}`,t,a[t]);for(let[t,r]of Yt(a.options).entries())u(`object '${n}' \xB7 field '${e}' option ${typeof r.value==`string`?`'${r.value}'`:`#${t}`} visibleWhen`,r.visibleWhen,n,`record`);for(let[r,i,o]of[[`readonlyWhen`,a.readonlyWhen,`the field would be locked on every write`],[`requiredWhen`,a.requiredWhen,`the requirement would never be enforced — the predicate faults, the server logs and skips it, and the field stays optional in the database`]]){let a=sn(i);d===1||!a||!an(a)||t.push({where:`object '${n}' \xB7 field '${e}' ${r}`,message:`\`${r}\` reads \`parent\`, but object '${n}' declares ${d===0?`no`:`${d}`} \`master_detail\` relationship${d===1?``:`s`} \u2014 so the server has no header record to bind as \`parent\` and ${o}. `+(d===0?"Declare the owning relationship as `Field.masterDetail('<master>')`, or rewrite the predicate against `record`.":"`parent` needs exactly one master; name the header explicitly through `record.<fk>` state instead, or model the extra relationship as a `lookup`."),source:a,severity:`error`})}if(l(`object '${n}' \xB7 field '${e}' requiredWhen`,`field '${e}' requiredWhen`,a.requiredWhen,n,`fail-open`),a.expression){let o=ke(`value`,a.expression,n?{objectName:n,fields:r.get(n),fieldTypes:i.get(n),scope:`record`}:{scope:`record`}),s=`object '${n}' \xB7 field '${e}' expression`;for(let e of o.errors)t.push({where:s,message:e.message,source:e.source,severity:`error`});for(let e of o.warnings)t.push({where:s,message:e.message,source:e.source,severity:`warning`});c(s,a.expression,n)}}}let v=new Set,y=(e,t,n)=>{let r=n??(typeof t.objectName==`string`?t.objectName:void 0),i=typeof t.name==`string`?t.name:`?`,a=`${r??``}:${i}`;v.has(a)||(v.add(a),u(`${e} \xB7 action '${i}' visible`,t.visible,r,`record`),typeof t.disabled!=`boolean`&&u(`${e} \xB7 action '${i}' disabled`,t.disabled,r,`record`))};for(let t of Yt(e.actions))y(`stack`,t);for(let e of n){let t=typeof e.name==`string`?e.name:void 0;for(let n of Yt(e.actions))y(`object '${t}'`,n,t)}for(let t of Yt(e.sharingRules)){let e=typeof t.object==`string`?t.object:void 0;u(`sharingRule '${t.name??`?`}'${e?` (${e})`:``} condition`,t.condition,e,`record`)}for(let n of Yt(e.hooks)){let e=n.name??`?`;if(typeof n.object==`string`){u(`hook '${e}' (${n.object}) condition`,n.condition,n.object,`record`),l(`hook '${e}' (${n.object}) condition`,`hook '${e}' condition`,n.condition,n.object);continue}let r=Array.isArray(n.object)?n.object.filter(e=>typeof e==`string`&&e!==`*`):[];if(r.length===0){u(`hook '${e}' condition`,n.condition,void 0,`record`);continue}let i=t.length,a=new Set,o=[];for(let i of r){let r=t.length;u(`hook '${e}' (${i}) condition`,n.condition,i,`record`),l(`hook '${e}' (${i}) condition`,`hook '${e}' condition`,n.condition,i);for(let e=r;e<t.length;e++){let n=t[e],r=`${n.message}\0${n.source??``}`;a.has(r)||(a.add(r),o.push(n))}}t.length=i,t.push(...o)}return t}function un(e,t,n,r){let i=e.createSourceFile(t,n,r.target,r.setParentNodes,r.scriptKind),a=i.parseDiagnostics;if(!a||a.length===0)return{sourceFile:i};let o=a[0],{line:s,character:c}=i.getLineAndCharacterOfPosition(o.start??0),l=r.synthesizedLinesBefore??0;return{sourceFile:i,failure:{message:e.flattenDiagnosticMessageText(o.messageText,` `),line:Math.max(1,s+1-l),column:c+1,count:a.length}}}function dn(e){let t=e.count>1?`; ${e.count} syntax errors in total`:``;return`line ${e.line}, column ${e.column}: ${e.message}${t}`}var fn=`The source is parsed (never executed) so it can be checked. A source with syntax errors is only partially recovered, so the checks that follow may have skipped real problems — fix the syntax error and re-run to get a verdict that covers the whole source.`,pn=null;function mn(){if(pn)return pn;let e=import.meta.url?import.meta.url:typeof __filename<`u`?__filename:process.cwd()+`/`;try{pn=(0,S.createRequire)(e)(`typescript`)}catch(e){throw Error(`@objectstack/lint: checking plugin source for startup registry verdicts requires the "typescript" package, which could not be loaded (${e instanceof Error?e.message:String(e)}). It is a declared dependency of @objectstack/lint \u2014 if this deployment prunes packages, keep "typescript" in the image; it is only loaded when plugin source is actually checked.`)}return pn}var hn=`startup-open-vocabulary-verdict`,gn=`startup-verdict-assertive-wording`,_n=`startup-source-unparseable`,vn=new Map([[`getRegisteredNodeTypes`,`ADR-0018 keeps the flow node-type vocabulary open and runtime-extensible — a plugin registers its executor from its own init()/start(), which can be after this line (#4771)`],[`knownNodeTypes`,`ADR-0018 keeps the flow node-type vocabulary open and runtime-extensible — a plugin registers its executor from its own init()/start(), which can be after this line (#4771)`],[`getUnknownNodeTypeAudit`,`the unknown-node-type audit is a snapshot of an OPEN vocabulary a plugin can still extend during boot; it is read-only by design and answers "unknown as of now", never "unknown for this deployment" (#4771)`],[`getActionDescriptors`,`ADR-0018 action descriptors are published by plugins during boot, so a type missing from them here means "not published YET" (#4771)`],[`getRegisteredExecutors`,`executors are contributed by plugins during boot — an executor missing here may simply be a plugin that has not started`],[`listExecutors`,`executors are contributed by plugins during boot — an executor missing here may simply be a plugin that has not started`],[`getRegisteredTools`,`AI tools are contributed by plugins during boot, so the registered set is not final until every plugin has started`],[`listConnectors`,`connectors are contributed by plugins during boot (StackSchema.connectors documents provider-bound instances registered by plugins), so the list is not final until every plugin has started`],[`getRegisteredConnectors`,`connectors are contributed by plugins during boot, so the registered set is not final until every plugin has started`],[`listCapabilities`,`ADR-0066 capabilities are declared by every installed package, so the set is not final until every plugin has contributed its declarations`],[`getRegisteredCapabilities`,`ADR-0066 capabilities are declared by every installed package, so the set is not final until every plugin has contributed its declarations`],[`listProviders`,`providers are contributed by plugins during boot — a provider missing here may simply be a plugin that has not started`],[`getRegisteredProviders`,`providers are contributed by plugins during boot — a provider missing here may simply be a plugin that has not started`]]),yn=new Map([[`constructor`,`the constructor runs at composition time — before ANY plugin has been initialized`],[`init`,`another plugin's init() may not have run yet (ADR-0116), so the vocabulary is still filling`],[`start`,`sibling plugins' start() have not all run, and ADR-0018 lets a plugin register its contributions from start() — the vocabulary is still filling`]]),bn=[`seal`],xn=new Set([`warn`,`error`,`fatal`]),Sn=new Set([`warn`,`error`,`fatal`,`info`,`debug`,`trace`,`log`]),Cn=new Set([`insert`,`insertOne`,`update`,`updateOne`,`upsert`,`save`,`saveMetaItem`]),wn=[`will fail`,`fails at execution`,`nothing will register`,`no plugin provides`,`is not installed`,`is not configured`,`you need`,`you must install`,`must be provisioned`],Tn=[`not yet`,`yet been registered`,`so far`,`as of`,`may still`,`might still`,`still be registered`,`has started`,`have started`],En='Take one of the three shapes the fixes took: (1) resolve where the value is USED, not where you start — a lazy accessor or a `kernel:ready`/`kernel:bootstrapped` hook sees a provider that registered later (`createLazyCacheRateLimitStorage()` in plugin-auth, #4772); (2) seal the vocabulary, then judge — have the host declare the moment it can no longer grow and draw the conclusion there (`AutomationEngine.sealNodeTypeVocabulary()`, called at `kernel:bootstrapped`, #4771); (3) order the verdict AFTER the mutation it describes, so it cannot attest to a state this same boot goes on to contradict (the ADR-0104 attestation, #4769). If the conclusion must stay here, keep the two worlds apart in the wording: "no executor registered YET (as of plugin start)" is true; "will fail at execution time" is a claim about a world that has not finished forming.';function Dn(e,t){return e.isFunctionDeclaration(t)||e.isFunctionExpression(t)||e.isArrowFunction(t)||e.isMethodDeclaration(t)||e.isConstructorDeclaration(t)||e.isGetAccessorDeclaration(t)||e.isSetAccessorDeclaration(t)}function On(e,t,n){t.forEachChild(t=>{Dn(e,t)||e.isClassDeclaration(t)||e.isClassExpression(t)||(n(t),On(e,t,n))})}function kn(e,t,n){t.forEachChild(t=>{n(t),kn(e,t,n)})}function An(e,t){if(!e.isCallExpression(t))return;let n=t.expression;if(e.isIdentifier(n))return n.text;if(e.isPropertyAccessExpression(n)&&e.isIdentifier(n.name))return n.name.text}function jn(e,t){if(!e.isCallExpression(t))return;let n=t.expression;if(!e.isPropertyAccessExpression(n)||!e.isIdentifier(n.name))return;let r=n.name.text;if(!Sn.has(r))return;let i=n.expression,a;if(e.isIdentifier(i)?a=i.text:e.isPropertyAccessExpression(i)&&e.isIdentifier(i.name)&&(a=i.name.text),a)return/^(logger|log|console)$/i.test(a)?r:void 0}function Mn(e,t){let n=[],r=t=>{(e.isStringLiteralLike(t)||e.isTemplateHead(t)||e.isTemplateMiddle(t)||e.isTemplateTail(t))&&n.push(t.text)};return r(t),kn(e,t,r),n.join(` `).toLowerCase()}function Nn(e,t){let n=!1,r=t=>{if(!n&&e.isIdentifier(t)){let e=t.text.toLowerCase();bn.some(t=>e.includes(t))&&(n=!0)}};return r(t),kn(e,t,r),n}function Pn(e,t){let n=new Set;for(let r of t.statements)if(e.isVariableStatement(r)&&!(r.declarationList.flags&e.NodeFlags.Const))for(let t of r.declarationList.declarations)e.isIdentifier(t.name)&&n.add(t.name.text);return n}function Fn(e,t){let n=new Map;return kn(e,t,t=>{e.isFunctionDeclaration(t)&&t.name&&t.body||e.isMethodDeclaration(t)&&e.isIdentifier(t.name)&&t.body?n.set(t.name.text,t.body):e.isVariableDeclaration(t)&&e.isIdentifier(t.name)&&t.initializer&&(e.isArrowFunction(t.initializer)||e.isFunctionExpression(t.initializer))&&t.initializer.body&&n.set(t.name.text,t.initializer.body)}),n}function In(e,t){let n=[],r=t=>{let r=[],i=!1;for(let n of t.members)e.isMethodDeclaration(n)&&e.isIdentifier(n.name)?(n.name.text===`init`||n.name.text===`start`)&&(i=!0):e.isPropertyDeclaration(n)&&e.isIdentifier(n.name)&&(n.name.text===`init`||n.name.text===`start`)&&n.initializer&&(e.isArrowFunction(n.initializer)||e.isFunctionExpression(n.initializer))&&(i=!0);if(i){for(let n of t.members)e.isConstructorDeclaration(n)&&n.body?r.push({phase:`constructor`,body:n.body}):e.isMethodDeclaration(n)&&e.isIdentifier(n.name)&&n.body?yn.has(n.name.text)&&r.push({phase:n.name.text,body:n.body}):e.isPropertyDeclaration(n)&&e.isIdentifier(n.name)&&yn.has(n.name.text)&&n.initializer&&(e.isArrowFunction(n.initializer)||e.isFunctionExpression(n.initializer))&&n.initializer.body&&r.push({phase:n.name.text,body:n.initializer.body});r.length&&n.push({label:t.name?.text??`<anonymous class>`,phases:r})}},i=t=>{let r=[],i,a=!1;for(let n of t.properties){if(!e.isPropertyAssignment(n)||!e.isIdentifier(n.name))continue;let t=n.name.text;t===`name`&&e.isStringLiteralLike(n.initializer)&&(i=n.initializer.text),(t===`init`||t===`start`)&&Dn(e,n.initializer)&&(a=!0),yn.has(t)&&(e.isArrowFunction(n.initializer)||e.isFunctionExpression(n.initializer))&&n.initializer.body&&r.push({phase:t,body:n.initializer.body})}!i||!a||!r.length||n.push({label:`${i} (object plugin)`,phases:r})};return kn(e,t,t=>{e.isClassDeclaration(t)||e.isClassExpression(t)?r(t):e.isObjectLiteralExpression(t)&&i(t)}),n}function Ln(e,t={}){if(!e||!e.trim())return[];let n=!1;for(let t of vn.keys())if(e.includes(t)){n=!0;break}if(!n)return[];let r=mn(),i=t.file??`source`,{sourceFile:a,failure:o}=un(r,i,e,{target:r.ScriptTarget.Latest,setParentNodes:!0,scriptKind:r.ScriptKind.TS}),s=[];o&&s.push({severity:`warning`,rule:_n,where:i,path:`${i}:${o.line}`,message:`source did not parse (${dn(o)}), so this rule read a partially recovered tree \u2014 a startup verdict in the unread part is not reported.`,hint:fn});let c=Pn(r,a),l=Fn(r,a),u=e=>a.getLineAndCharacterOfPosition(e.getStart(a)).line+1;for(let e of In(r,a))for(let{phase:t,body:n}of e.phases){let a=[],o=new Set,d=(e,t)=>{a.push(e),!(t>=2)&&On(r,e,e=>{let n=An(r,e);if(!n||o.has(n))return;let i=l.get(n);i&&(o.add(n),d(i,t+1))})};d(n,0);let f=[];for(let e of a)On(r,e,e=>{let t=An(r,e);t&&vn.has(t)&&f.push({probe:t,node:e})});if(!f.length||a.some(e=>Nn(r,e)))continue;let p=[];for(let e of a)On(r,e,e=>{let t=jn(r,e);if(t&&xn.has(t)){p.push({kind:`announced`,detail:`${t} log`,line:u(e),node:e});return}let n=An(r,e);if(n&&Cn.has(n)){p.push({kind:`persisted`,detail:`${n}()`,line:u(e),node:e});return}if(r.isBinaryExpression(e)&&e.operatorToken.kind===r.SyntaxKind.EqualsToken){let t=e.left,n;r.isPropertyAccessExpression(t)&&r.isIdentifier(t.name)?n=t.expression.kind===r.SyntaxKind.ThisKeyword?`this.${t.name.text}`:`<obj>.${t.name.text}`:r.isIdentifier(t)&&c.has(t.text)&&(n=`module-level \`${t.text}\``),n&&p.push({kind:`cached`,detail:n,line:u(e),node:e})}});if(!p.length)continue;let m=f[0],h=p[0],g=`${e.label}.${t}${t===`constructor`?``:`()`}`,_=vn.get(m.probe),v=yn.get(t);s.push({severity:`warning`,rule:hn,where:g,path:`${i}:${u(m.node)}`,message:`\`${m.probe}()\` reads a vocabulary that is still filling, and the conclusion is recorded (${h.kind}: ${h.detail}, line ${h.line}). ${_}; ${v}. "absent" here has two meanings the recorded verdict cannot tell apart \u2014 no provider in this deployment, or a provider that registers later in this same boot \u2014 and nothing retracts the record when the second one turns out to be the case (#4771 / #4772).`,hint:En});for(let e of p){if(e.kind!==`announced`)continue;let t=Mn(r,e.node);if(!t||Tn.some(e=>t.includes(e)))continue;let n=wn.find(e=>t.includes(e));n&&s.push({severity:`warning`,rule:gn,where:g,path:`${i}:${e.line}`,message:`the diagnostic says "${n}" about a vocabulary that can still grow during this boot. #4771 printed "will fail at execution time" for eight approval flows 0.8s before the executor that runs them was registered, and a deployment that genuinely lacked the plugin printed the identical eight \u2014 so the line could not tell an operator which of the two they had. #4772's remedy ("you need Redis") sent operators to fix a problem they did not have, and connecting Redis did not change the message.`,hint:En})}}return s}var Rn=`list-view-filters-in-views-mode`;function zn(e){return Array.isArray(e)?e:e&&typeof e==`object`?Object.entries(e).map(([e,t])=>({name:e,...t})):[]}function Bn(e,t,n,r){if(!e||typeof e!=`object`)return;let i=e;i.quickFilters!=null&&r.push({severity:`error`,rule:Rn,where:t,path:`${n}.quickFilters`,message:'`quickFilters` is a page filters-mode control and is ignored on an object list view ("views" mode) — the ViewTabBar owns nav here.',hint:'Move `quickFilters` to a page list (InterfaceListPage, "filters" mode), or remove it. See ADR-0047.'});let a=i.userFilters;if(a&&typeof a==`object`){let e=a;(e.element===`tabs`||e.tabs!=null)&&r.push({severity:`error`,rule:Rn,where:t,path:`${n}.userFilters`,message:'`userFilters` with `element: "tabs"` is page-only and is ignored on an object list view ("views" mode) — it would collide with the ViewTabBar.',hint:'Use `listViews` for named presets on an object (each becomes a segmented tab), switch to `element: "dropdown"` for value chips, or move the `tabs` filter to a page list (InterfaceListPage, "filters" mode). See ADR-0047.'})}}function Vn(e,t,n,r){if(!(!e||typeof e!=`object`))for(let[i,a]of Object.entries(e))Bn(a,`${t} \u203A listViews.${i}`,`${n}.listViews.${i}`,r)}function Hn(e){let t=[];return zn(e.objects).forEach((e,n)=>{let r=typeof e.name==`string`?`object "${e.name}"`:`objects[${n}]`;Vn(e.listViews,r,`objects[${n}]`,t)}),zn(e.views).forEach((e,n)=>{let r=typeof e.objectName==`string`?e.objectName:typeof e.name==`string`?e.name:void 0,i=r?`view "${r}"`:`views[${n}]`;Bn(e.list,`${i} \u203A list`,`views[${n}].list`,t),Vn(e.listViews,i,`views[${n}]`,t)}),t}var Un=e=>!!e&&typeof e==`object`&&!Array.isArray(e);function Wn(e){return Array.isArray(e)?e.flatMap((e,t)=>Un(e)?[{name:String(e.name??t),def:e,key:`[${t}]`}]:[]):Un(e)?Object.entries(e).flatMap(([e,t])=>Un(t)?[{name:e,def:{name:e,...t},key:`.${e}`}]:[]):[]}function Gn(e,t,n,r){for(let i of t)e.push({severity:i.severity,rule:i.rule,where:n,path:`${r}.${i.path}`,message:i.message,hint:i.fix})}function Kn(e){let t=[];if(!Un(e))return t;for(let[n,r]of Wn(e.objects).entries())for(let e of Wn(r.def.fields))Gn(t,ae(e.def),`object "${r.name}" \u203A fields.${e.name}`,`objects[${n}].fields${e.key}`);for(let[n,r]of Wn(e.views).entries()){let e=r.def.object?`view container "${r.name}"`:`view container [${n}]`;Un(r.def.list)&&Gn(t,u(r.def.list),`${e} \u203A list`,`views[${n}].list`);for(let i of Wn(r.def.listViews))Gn(t,u(i.def),`${e} \u203A listViews.${i.name}`,`views[${n}].listViews${i.key}`)}for(let n of Wn(e.webhooks))Gn(t,h(n.def),`webhook "${n.name}"`,`webhooks${n.key}`);return t}var qn=`object/managed-api-method-unaffordable`,Jn=e=>!!e&&typeof e==`object`&&!Array.isArray(e);function Yn(e){return Array.isArray(e)?e.flatMap((e,t)=>Jn(e)?[{name:String(e.name??t),def:e,key:`[${t}]`}]:[]):Jn(e)?Object.entries(e).flatMap(([e,t])=>Jn(t)?[{name:e,def:{name:e,...t},key:`.${e}`}]:[]):[]}function Xn(e){let t=[];if(!Jn(e))return t;for(let[n,r]of Yn(e.objects).entries()){let e=Ee(r.def);if(e.length===0)continue;let i=e.map(e=>e.verb).join(`, `),a=[...new Set(e.map(e=>e.needs))];t.push({severity:`error`,rule:qn,where:`object "${r.name}"`,path:`objects[${n}].enable.apiMethods`,message:`\`managedBy: '${String(r.def.managedBy)}'\` object "${r.name}" `+s(e)+` The registry STRIPS [${i}] at registration, so this declaration and the API you actually get already disagree \u2014 today the only trace is a line in the boot log.`,hint:`Either add \`userActions: { ${a.map(e=>`${e}: true`).join(`, `)} }\` to the object \u2014 only if the write is genuinely one a user context may perform, and only once the guard enforcing it exists (ADR-0092 D4: affordance never ships ahead of the guard) \u2014 or remove [${i}] from \`enable.apiMethods\`, which is what the runtime does for you today.`})}return t}var Zn=`flow-trigger-unknown-object`,Qn=`flow-draft-status-ambiguous`,$n=`flow-trigger-unknown-event`,er=`flow-time-relative-descriptor-invalid`,tr=`flow-time-relative-descriptor-unroutable`,nr=`flow-trigger-unroutable`,rr=/^record-(?:before|after)-(?:create|insert|update|delete|write)$/;function ir(e){return Array.isArray(e)?e:e&&typeof e==`object`?Object.entries(e).map(([e,t])=>({name:e,...t})):[]}function ar(e){let t=typeof e;return t===`string`||t===`number`||t===`boolean`?`${JSON.stringify(e)} (a ${t})`:t===`bigint`?`${String(e)}n (a bigint)`:`a ${t}`}function or(e){if(typeof e==`string`)return`'${e}'`;let t=JSON.stringify(e);return t===void 0?`a ${typeof e}`:t}function sr(e){let t=Array.isArray(e.nodes)?e.nodes:[],n=t.findIndex(e=>e?.type===`start`);return n>=0?{node:t[n],index:n}:void 0}function cr(e){let t=[],n=ir(e.flows);if(n.length===0)return t;let r=new Set(ir(e.objects).map(e=>typeof e.name==`string`?e.name:void 0).filter(e=>!!e));return n.forEach((e,n)=>{let i=typeof e.name==`string`?e.name:`#${n}`,o=sr(e),s=o?.node.config??{},c=typeof s.triggerType==`string`?s.triggerType:void 0,l=!!c&&c.startsWith(`record-`),u=Array.isArray(s.triggerType)&&s.triggerType.some(e=>typeof e==`string`&&e.startsWith(`record-`)),d=s.timeRelative!=null&&typeof s.timeRelative==`object`,f=l||c===`api`||s.schedule!=null||d||e.type===`schedule`||e.type===`api`;if(l&&o){let e=typeof s.objectName==`string`?s.objectName:void 0;e&&!r.has(e)&&!e.startsWith(`sys_`)&&t.push({severity:`warning`,rule:Zn,where:`flow "${i}" \u203A start node`,path:`flows[${n}].nodes[${o.index}].config.objectName`,message:`targets object '${e}', which this stack does not define \u2014 if the name is wrong, the flow will never fire (and the runtime stays silent about it).`,hint:`Object names match exactly. Check config.objectName against the object's registered name (e.g. 'app_candidate', not 'candidate'). If the object comes from another installed package, this warning can be ignored.`})}if(d&&o){let e=s.timeRelative,c=typeof e.object==`string`?e.object:void 0;c&&!r.has(c)&&!c.startsWith(`sys_`)&&t.push({severity:`warning`,rule:Zn,where:`flow "${i}" \u203A start node`,path:`flows[${n}].nodes[${o.index}].config.timeRelative.object`,message:`sweeps object '${c}', which this stack does not define \u2014 if the name is wrong, the sweep will match nothing (and the runtime stays quiet about it).`,hint:`Object names match exactly. Check config.timeRelative.object against the object's registered name. If the object comes from another installed package, this warning can be ignored.`});let l=a.safeParse(e);if(!l.success){let e=l.error.issues.map(e=>`${e.path.join(`.`)||`(root)`}: ${e.message.replace(/\s+/g,` `).trim()}`).join(`; `);t.push({severity:`error`,rule:er,where:`flow "${i}" \u203A start node`,path:`flows[${n}].nodes[${o.index}].config.timeRelative`,message:`has a config.timeRelative descriptor the time-relative trigger REFUSES at bind time, so the sweep is never installed \u2014 the flow declares a time-relative trigger and then never runs (the only trace is one warn in the server log). ${e}`,hint:`Those messages are TimeRelativeTriggerSchema's own — the same schema the trigger safeParses at bind time, so a descriptor that satisfies them binds. An unrecognized key names the declared key it was probably meant to be; see content/docs/references/automation/time-relative-trigger.mdx.`})}}if(o&&l&&!rr.test((c??``).trim())&&t.push({severity:`error`,rule:$n,where:`flow "${i}" \u203A start node`,path:`flows[${n}].nodes[${o.index}].config.triggerType`,message:`triggerType '${c}' is not a recognized record trigger \u2014 the flow binds to the record-change trigger but never fires (the runtime stays silent about it).`,hint:`Use record-{before,after}-{create,update,delete,write}. 'write' fires on create OR update in one flow (#3427); create/insert are synonyms. There is no "any change" token — pick the specific event(s).`}),o&&u&&t.push({severity:`error`,rule:$n,where:`flow "${i}" \u203A start node`,path:`flows[${n}].nodes[${o.index}].config.triggerType`,message:`triggerType is an array (${JSON.stringify(s.triggerType)}), which is not supported \u2014 a start node takes a single trigger event, so the flow binds to nothing and never fires (the runtime stays silent about it).`,hint:`Use one triggerType string. For "created or updated" use record-after-write (one flow, both events, #3427). For any other combination, author one flow per event — multi-event arrays are deferred (#3457).`}),o&&s.timeRelative!=null&&typeof s.timeRelative!=`object`){let r=l||u?`its record-change trigger`:s.schedule!=null||e.type===`schedule`?"its plain `config.schedule` cadence":c===`api`||e.type===`api`?`its api trigger`:void 0,a=r?`The flow still binds through ${r}, so the descriptor is silently DROPPED \u2014 it fires on that trigger's terms (once per firing, with no record on the context) instead of once per matching record, and nothing anywhere reports the difference.`:`Nothing else on this start node declares a trigger either, so the flow binds to NOTHING and never fires — with zero diagnostics at any layer, not even the one bind-time warn a descriptor that IS an object gets when the trigger refuses it.`;t.push({severity:`error`,rule:tr,where:`flow "${i}" \u203A start node`,path:`flows[${n}].nodes[${o.index}].config.timeRelative`,message:`has config.timeRelative = ${ar(s.timeRelative)}, which is not the descriptor OBJECT this slot takes \u2014 the engine routes a flow to the time-relative sweep only when config.timeRelative is an object, so this one is never routed there and the sweep is never installed. ${a}`,hint:`config.timeRelative describes WHICH records to sweep — an object: { object, dateField, and exactly one of withinDays | offsetDays } (plus optional filter / maxRecords). A cadence like 'daily' is not a descriptor: HOW OFTEN the sweep runs is the sibling key config.schedule on the same start node (it defaults to daily, so it is usually omitted). See TimeRelativeTriggerSchema and content/docs/references/automation/time-relative-trigger.mdx.`})}let p=l||u||d||s.schedule!=null||e.type===`schedule`||e.type===`api`||c===`api`;if(o&&e.type===`record_change`&&!p){let e=s.triggerType!=null;t.push({severity:`error`,rule:nr,where:`flow "${i}" \u203A start node`,path:`flows[${n}].nodes[${o.index}].config.triggerType`,message:`declares type: 'record_change' but `+(e?`its start node's triggerType is ${or(s.triggerType)}, which the engine routes to NO trigger`:`its start node has no triggerType at all, so there is nothing for the engine to route`)+` — it binds a record-change flow only for a token starting with 'record-', so this flow is demoted to a manual one and never fires. Nothing NAMES it: the unbound-flow audit resolves the same binding and skips the flow as "manual — nothing to bind", so neither the boot warning nor the startup summary lists it; the only trace is the banner's flow count being one higher than its bound count.`,hint:`Use record-{before,after}-{create,update,delete,write} ('write' is create OR update in one flow, #3427; create/insert are synonyms). If the flow really is launched by hand or from a screen, declare type: 'autolaunched' or 'screen' instead of 'record_change' — those types have no trigger to be missing.`})}f&&(e.status==null||e.status===`draft`)&&t.push({severity:`warning`,rule:Qn,where:`flow "${i}"`,path:`flows[${n}].status`,message:`has status 'draft' (the default when none is authored). Draft flows DO still fire their triggers (only 'obsolete'/'invalid' disable), so the intent is ambiguous.`,hint:`Declare status: 'active' to arm it deliberately, or status: 'obsolete' to disable it.`})}),t}function lr(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function ur(e){return typeof e==`string`&&e.length>0?e:void 0}var dr=new Map([...ue].map(([e,t])=>[e,t.map(e=>e.key)])),fr=$e,pr=16;function mr(e,t){return ur(e.label)??ur(e.id)??`#${t}`}function hr(e){if(!lr(e))return;let t;for(let n of Object.keys(e))fr.has(n)&&(t??={...e},delete t[n]);return t??e}function gr(e,t){let n=[];if(!lr(e))return n;let r=(e,t,i,a)=>{!Array.isArray(e)||a>pr||e.forEach((e,o)=>{if(!lr(e))return;let s=`${t}[${o}]`;n.push({node:e,path:s,localConfig:hr(e.config),regionTrail:i,depth:a});let c=ur(e.type),l=c?dr.get(c):void 0;if(!l||!lr(e.config))return;let u=e.config,d=`${c} "${mr(e,o)}"`;for(let e of l){let t=u[e];if(e===`branches`){if(!Array.isArray(t))continue;t.forEach((e,t)=>{if(!lr(e))return;let n=ur(e.name)??`#${t}`;r(e.nodes,`${s}.config.branches[${t}].nodes`,_r(i,`${d} \u203A branch ${n}`),a+1)});continue}lr(t)&&r(t.nodes,`${s}.config.${e}.nodes`,_r(i,`${d} \u203A ${e}`),a+1)}})};return r(e.nodes,`${t}.nodes`,``,0),n}function _r(e,t){return e?`${e} \u203A ${t}`:t}var vr=`flow-template-unknown-field`,yr=`flow-template-lookup-traversal`,br=`flow-template-field-unprovisioned`;function xr(e){return Array.isArray(e)?e:e&&typeof e==`object`?Object.entries(e).map(([e,t])=>({name:e,...t})):[]}var Sr=new Set([...it,`name`,`owner`,`record_type`]),Cr=new Set([`lookup`,`master_detail`,`user`,`tree`]),wr=new Set([`get_record`,`update_record`,`delete_record`]);function Tr(e){let t=new Map;for(let n of xr(e.fields))typeof n.name==`string`&&t.set(n.name,typeof n.type==`string`?n.type:``);return t}function Er(e){let t=[],n=/\{([^{}]+)\}/g,r;for(;(r=n.exec(e))!==null;){let e=r[1].trim();if(!/^[A-Za-z_$][\w$]*(?:\.(?:[A-Za-z_$][\w$]*|\d+))*$/.test(e))continue;let n=e.split(`.`);if(n[0]!==`record`)continue;let i=n.slice(1);i.length>0&&t.push(i)}return t}function Dr(e,t){if(typeof e==`string`){e.includes(`{`)&&t.push(e);return}if(Array.isArray(e)){for(let n of e)Dr(n,t);return}if(e&&typeof e==`object`)for(let n of Object.values(e))Dr(n,t)}var Or=[`config`,`notify`,`update_record`,`create_record`,`http`,`script`,`screen`,`wait`,`approval`,`connector_action`,`subflow`,`decision`,`start`];function kr(e,t){let n=[],r=[];for(let i of Or){if(!(i in e))continue;let a=e[i];if(t&&a&&typeof a==`object`&&!Array.isArray(a)){let{filter:e,...t}=a,i=[];Dr(e,i);for(let e of i)n.push({text:e,inFilter:!0});let o=[];Dr(t,o);for(let e of o)r.push({text:e,inFilter:!1});continue}let o=[];Dr(a,o);for(let e of o)r.push({text:e,inFilter:!1})}return[...n,...r]}function Ar(e,t){if(e.type===`record_change`)return!0;let n=typeof t.triggerType==`string`?t.triggerType:void 0;return!!n&&n.startsWith(`record-`)}function jr(e){let t=(Array.isArray(e.nodes)?e.nodes:[]).find(e=>e?.type===`start`);if(!t)return;let n=t.config??{},r=t.start??{},i=typeof n.objectName==`string`?n.objectName:void 0,a=typeof r.objectName==`string`?r.objectName:void 0;return i??a}function Mr(e){let t=((Array.isArray(e.nodes)?e.nodes:[]).find(e=>e?.type===`start`)?.config??{}).expand;return typeof t==`string`?new Set(t?[t]:[]):Array.isArray(t)?new Set(t.filter(e=>typeof e==`string`&&e.length>0)):new Set}function Nr(e){let t=[],n=xr(e.flows);if(n.length===0)return t;let r=new Map;for(let t of xr(e.objects))typeof t.name==`string`&&r.set(t.name,t);return n.forEach((e,n)=>{let i=typeof e.name==`string`?e.name:`#${n}`;if(!Ar(e,(Array.isArray(e.nodes)?e.nodes:[]).find(e=>e?.type===`start`)?.config??{}))return;let a=jr(e);if(!a)return;let o=r.get(a);if(!o)return;let s=Tr(o),c=ot(o),l=Mr(e);gr(e,`flows[${n}]`).forEach(({node:e,path:n,regionTrail:r,localConfig:o},u)=>{let d=typeof e.type==`string`?e.type:typeof e.id==`string`?e.id:`#${u}`,f=r?`flow "${i}" ${r} node "${d}"`:`flow "${i}" node "${d}"`,p=typeof e.type==`string`?e.type:``,m=wr.has(p),h=kr(o!==void 0&&o!==e.config?{...e,config:o}:e,m);if(h.length===0)return;let g=new Set,_=new Set,v=new Set;for(let e of h){let r=e.inFilter;for(let i of Er(e.text)){let e=i[0],o=i.length>1&&!/^\d+$/.test(i[1]),u=s.has(e)||Sr.has(e);if(c.has(e)&&(v.has(e)||(v.add(e),t.push({severity:`warning`,rule:br,where:f,path:n,message:(r?`${p} filter references `:`template references `)+`'{record.${i.join(`.`)}}', and ${C(a,e)} \u2014 `+(r?`the token resolves to nothing on every run, which DROPS the condition from the query instead of narrowing it; the node then refuses to run at execution time (#3810).`:`the token resolves to an empty string on every run (silently).`),hint:w(a,e)}))),!u){if(g.has(e))continue;g.add(e),t.push({severity:r?`error`:`warning`,rule:vr,where:f,path:n,message:r?`${p} filter references '{record.${i.join(`.`)}}', but '${e}' is not a field on object '${a}' \u2014 the token resolves to nothing, which DROPS the condition from the query instead of narrowing it. The node refuses to run at execution time (#3810).`:`template references '{record.${i.join(`.`)}}', but '${e}' is not a field on object '${a}' \u2014 it resolves to an empty string at runtime (silently).`,hint:r?`Check the field name against the object's field definitions (e.g. '{record.full_name}', not '{record.full_naem}'); system columns like id/created_at/owner are also addressable. This gates the build rather than warning: an absent condition WIDENS the query, so the runtime has already decided to refuse this node.`:`Check the field name against the object's field definitions (e.g. '{record.full_name}', not '{record.full_naem}'). System columns like id/created_at/owner are also addressable.`});continue}if(o){let o=s.get(e)??``;if(Cr.has(o)&&!l.has(e)){let s=i.join(`.`);if(_.has(s))continue;_.add(s),t.push({severity:r?`error`:`warning`,rule:yr,where:f,path:n,message:r?`${p} filter references '{record.${s}}', a cross-object hop through the ${o} field '${e}' \u2014 the flow record carries '${e}' as a scalar id, not an expanded object, so the token resolves to nothing and the condition is DROPPED from the query instead of narrowing it. The node refuses to run at execution time (#3810).`:`template references '{record.${s}}', a cross-object hop through the ${o} field '${e}' \u2014 the flow record carries '${e}' as a scalar id, not an expanded object, so this resolves to an empty string at runtime (silently).`,hint:r?`Opt in to resolve it: add '${e}' to the start node's config.expand (#3475) and the engine re-reads it as the run's identity. Otherwise filter on the foreign-key id directly ('{record.${e}}'), or project the value via a formula field on '${a}'. This gates the build rather than warning: an absent condition WIDENS the query.`:`Opt in to resolve it: add '${e}' to the start node's config.expand (#3475) and the engine re-reads it as the run's identity. Otherwise reference the foreign-key id directly ('{record.${e}}'), or project the value via a formula field on '${a}'.`})}}}}})}),t}var Pr=`flow-update-readonly-field`,Fr=`flow-update-readonly-when-field`;function Ir(e){return Array.isArray(e)?e:e&&typeof e==`object`?Object.entries(e).map(([e,t])=>({name:e,...t})):[]}function Lr(e){let t=new Map;for(let n of e){let e=typeof n.name==`string`?n.name:void 0;if(!e)continue;let r=new Map,i=(e,t)=>{let n=t?.readonlyWhen,i=n!=null&&(typeof n!=`string`||n.trim()!==``);r.set(e,{readonly:t?.readonly===!0,readonlyWhen:i})},a=n.fields;if(Array.isArray(a))for(let e of a){let t=e?.name;typeof t==`string`&&i(t,e)}else if(a&&typeof a==`object`)for(let[e,t]of Object.entries(a))i(e,t);t.set(e,r)}return t}function Rr(e){let t=e.objectName??e.object;if(!(typeof t!=`string`||t.includes(`{`)))return t||void 0}function zr(e){let t=[],n=Ir(e.flows);if(n.length===0)return t;let r=Lr(Ir(e.objects));return n.forEach((e,n)=>{if(e.runAs===`system`)return;let i=e.runAs===`user`||e.runAs===`system`?e.runAs:`user`,a=typeof e.name==`string`?e.name:`#${n}`;gr(e,`flows[${n}]`).forEach(({node:e,path:n,regionTrail:o},s)=>{if(e?.type!==`update_record`)return;let c=e.config??{},l=Rr(c);if(!l)return;let u=r.get(l);if(!u)return;let d=c.fields;if(!d||typeof d!=`object`||Array.isArray(d))return;let f=mr(e,s),p=o?`flow "${a}" \u203A ${o} \u203A node "${f}"`:`flow "${a}" \u203A node "${f}"`;for(let e of Object.keys(d)){let r=u.get(e);r&&(r.readonly?t.push({severity:`error`,rule:Pr,where:p,path:`${n}.config.fields.${e}`,message:`writes field '${e}', which object '${l}' declares readonly:true. Under runAs:'${i}' the engine silently strips readonly fields from the UPDATE payload (#2948), so this write never lands \u2014 while the step still reports success.`,hint:`If automation is meant to maintain this field, declare the flow runAs:'system' (the intended channel \u2014 readonly governs the end-user/API surface, not trusted system writers). Otherwise remove '${e}' from this update_record node.`}):r.readonlyWhen&&t.push({severity:`warning`,rule:Fr,where:p,path:`${n}.config.fields.${e}`,message:`writes field '${e}', which object '${l}' declares readonlyWhen. On records where that predicate is TRUE, a runAs:'${i}' UPDATE strips the field (#3042), so this write may silently not land depending on the record's state.`,hint:`If automation must maintain this field regardless of record state, run the flow runAs:'system'. Otherwise confirm this node only targets records whose readonlyWhen predicate is FALSE.`}))}})}),t}var Br=`view-container-shape`,Vr=[`list`,`form`,`listViews`,`formViews`];function Hr(e){return Array.isArray(e)?e.map((e,t)=>({key:`[${t}]`,value:e})):e&&typeof e==`object`?Object.entries(e).map(([e,t])=>({key:`.${e}`,value:t})):[]}function Ur(e){let t=e=>e&&typeof e==`object`&&!Array.isArray(e)?Object.keys(e).length:0;return+!!e.list+ +!!e.form+t(e.listViews)+t(e.formViews)}function Wr(e){let t=[];if(!e||typeof e!=`object`)return t;let n=e.viewItems;n!=null&&Hr(n).length>0&&t.push({severity:`error`,rule:Br,where:`viewItems`,path:`viewItems`,message:"`viewItems` is the machine-assembled channel for non-container view artifacts in runtime-assembled manifests (package export, environment artifacts) — it is not an authoring surface.",hint:"Author views as defineView containers in `views:`; author a standalone view through the metadata door (Studio / `PUT /api/v1/meta/view`), not in stack source."});for(let{key:n,value:r}of Hr(e.views)){if(!r||typeof r!=`object`||Array.isArray(r))continue;let e=r;if(e.viewKind!=null){let r=typeof e.name==`string`?` ("${e.name}")`:``;t.push({severity:`error`,rule:Br,where:`views${n}${r}`,path:`views${n}`,message:"A ViewItem record is not a view container: the stack `views:` collection carries containers only — `viewKind` belongs to a single VIEW, not to the container. The registration loop refuses this entry (#5320).",hint:"Wrap it in a defineView container: defineView({ list: { type, data, columns, ... }, listViews: { ... } }) — or author the standalone view through the metadata door (Studio / `PUT /api/v1/meta/view`). Machine-assembled manifests carry it under `viewItems:`."});continue}if(Ur(e)>0)continue;let i=typeof e.name==`string`?` ("${e.name}")`:``,a=!Vr.some(t=>t in e)&&[`type`,`columns`,`data`,`filter`,`sort`].some(t=>t in e);t.push({severity:`error`,rule:Br,where:`views${n}${i}`,path:`views${n}`,message:a?"Flat list-view object is not a view container: `ViewSchema` strips its keys, so it parses to an EMPTY container — zero views register and the Console renders no view for it.":"View container defines no views — all of `list` / `form` / `listViews` / `formViews` are absent or empty, so nothing registers.",hint:`Wrap every view in a defineView container: defineView({ list: { type, data, columns, ... }, listViews: { ... }, formViews: { ... } }). See examples/app-showcase/src/ui/views/task.view.ts.`})}return t}var Gr=`style-node-missing-id`,Kr=`style-classname-tailwind`,qr=`style-responsive-no-base`,Jr=`style-unknown-css-property`,Yr=`style-unknown-token`,Xr=[`large`,`medium`,`small`,`xsmall`],Zr=new Set(`space-1.space-2.space-3.space-4.space-5.space-6.space-8.space-10.space-12.radius.radius-sm.radius-md.radius-lg.radius-xl.shadow-sm.shadow-md.shadow-lg.surface.surface-sunken.text-strong.text-muted.brand.brand-foreground.hairline.background.foreground.card.card-foreground.popover.popover-foreground.primary.primary-foreground.secondary.secondary-foreground.muted.muted-foreground.accent.accent-foreground.destructive.destructive-foreground.border.input.ring.success.success-foreground.warning.warning-foreground.chart-1.chart-2.chart-3.chart-4.chart-5`.split(`.`)),Qr=new Set(`display.position.top.right.bottom.left.inset.zIndex.overflow.overflowX.overflowY.visibility.boxSizing.float.clear.width.height.minWidth.minHeight.maxWidth.maxHeight.aspectRatio.margin.marginTop.marginRight.marginBottom.marginLeft.marginInline.marginBlock.padding.paddingTop.paddingRight.paddingBottom.paddingLeft.paddingInline.paddingBlock.flex.flexDirection.flexWrap.flexGrow.flexShrink.flexBasis.alignItems.alignContent.alignSelf.justifyContent.justifyItems.justifySelf.gap.rowGap.columnGap.order.placeItems.placeContent.grid.gridTemplate.gridTemplateColumns.gridTemplateRows.gridTemplateAreas.gridColumn.gridRow.gridArea.gridAutoFlow.gridAutoColumns.gridAutoRows.color.backgroundColor.background.backgroundImage.backgroundSize.backgroundPosition.backgroundRepeat.backgroundClip.opacity.mixBlendMode.fontSize.fontWeight.fontFamily.fontStyle.lineHeight.letterSpacing.textAlign.textTransform.textDecoration.textOverflow.whiteSpace.wordBreak.overflowWrap.fontVariantNumeric.verticalAlign.textShadow.border.borderTop.borderRight.borderBottom.borderLeft.borderColor.borderWidth.borderStyle.borderRadius.borderTopLeftRadius.borderTopRightRadius.borderBottomLeftRadius.borderBottomRightRadius.outline.outlineOffset.boxShadow.transform.transformOrigin.transition.transitionProperty.transitionDuration.transitionTimingFunction.transitionDelay.animation.filter.backdropFilter.willChange.cursor.pointerEvents.userSelect.objectFit.objectPosition.content`.split(`.`)),$r=/var\(\s*--([a-zA-Z0-9-]+)\s*[,)]/g,ei=/^(sm|md|lg|xl|2xl|hover|focus|active|disabled|dark|group-hover|peer-[a-z]+|first|last|odd|even):/,ti=/^-?(p|m|px|py|pt|pb|pl|pr|mx|my|mt|mb|ml|mr|gap|gap-x|gap-y|space-x|space-y|w|h|min-w|max-w|min-h|max-h|size|text|leading|tracking|bg|border|rounded|shadow|ring|opacity|inset|top|bottom|left|right|z|order|col|row|grid-cols|grid-rows|basis)-(\d+(\.\d+)?|\d+\/\d+|px|full|auto|none|screen|min|max|fit|xs|sm|md|lg|xl|2xl|3xl|4xl|5xl|6xl)$/,ni=/^(flex|grid|block|inline|inline-block|inline-flex|hidden|contents|table|flow-root|grow|shrink|truncate|italic|underline|uppercase|lowercase|capitalize|antialiased|absolute|relative|fixed|sticky|static|isolate|flex-col|flex-row|flex-wrap|flex-nowrap|items-center|items-start|items-end|items-stretch|justify-center|justify-between|justify-around|justify-start|justify-end|text-center|text-left|text-right|font-bold|font-semibold|font-medium|font-normal|tabular-nums)$/;function ri(e){return e.split(/\s+/).some(e=>e?!!(ei.test(e)||/\[[^\]]+\]/.test(e)||ti.test(e)||ni.test(e)):!1)}function ii(e){return Array.isArray(e)?e:e&&typeof e==`object`?Object.entries(e).map(([e,t])=>({name:e,...t})):[]}function ai(e){let t=e.properties??{},n=[];for(let r of[e.children,t.children,e.body,t.body])Array.isArray(r)&&n.push(...r.filter(e=>e&&typeof e==`object`));return n}function oi(e,t,n,r){let i=typeof e.id==`string`?e.id:void 0,a=typeof e.type==`string`?e.type:`node`,o=`page "${t}" \u203A ${i?`node "${i}"`:`<${a}>`}`,s=e.responsiveStyles,c=!!s&&typeof s==`object`&&Xr.some(e=>s[e]);if(c&&!i&&r.push({severity:`error`,rule:Gr,where:o,path:n,message:"Node has responsiveStyles but no `id`; scoped CSS cannot be generated and the styles are silently dropped.",hint:"Add a stable `id` to this node."}),c&&!s.large&&Xr.slice(1).some(e=>s[e])&&r.push({severity:`warning`,rule:qr,where:o,path:n,message:"responsiveStyles sets a smaller breakpoint but no `large` base; the node is unstyled at desktop width.",hint:"Put the unconditional/base styles under `responsiveStyles.large` (desktop-first)."}),typeof e.className==`string`&&e.className.trim()&&ri(e.className)&&r.push({severity:`warning`,rule:Kr,where:o,path:n,message:`\`className\` contains Tailwind-looking utilities ("${e.className.trim().slice(0,60)}"); these are not compiled from metadata and will silently do nothing.`,hint:"Style this node with `responsiveStyles` + design tokens instead of `className` (ADR-0065)."}),s&&typeof s==`object`)for(let e of Xr){let t=s[e];if(!(!t||typeof t!=`object`)){for(let[i,a]of Object.entries(t))if(!i.startsWith(`--`)&&!Qr.has(i)&&r.push({severity:`warning`,rule:Jr,where:o,path:`${n}.responsiveStyles.${e}`,message:`Unknown CSS property "${i}" (typo?); if unintended it will not apply.`,hint:"Use a camelCase CSS property name (e.g. `flexDirection`, `backgroundColor`)."}),typeof a==`string`){let t;for($r.lastIndex=0;t=$r.exec(a);){let a=t[1];!Zr.has(a)&&!a.startsWith(`tw-`)&&r.push({severity:`warning`,rule:Yr,where:o,path:`${n}.responsiveStyles.${e}.${i}`,message:`References unknown design token \`var(--${a})\` (typo?); it will not resolve.`,hint:"Use a token from the ADR-0065 palette (e.g. `var(--space-6)`, `var(--surface)`, `hsl(var(--primary))`)."})}}}}let l=ai(e);for(let e=0;e<l.length;e++)oi(l[e],t,`${n}.children[${e}]`,r)}function si(e){let t=[],n=ii(e.pages);for(let e=0;e<n.length;e++){let r=n[e],i=typeof r.name==`string`?r.name:`pages[${e}]`,a=ii(r.regions);for(let n=0;n<a.length;n++){let r=ii(a[n].components);for(let a=0;a<r.length;a++)oi(r[a],i,`pages[${e}].regions[${n}].components[${a}]`,t)}}return t}var ci=e=>Array.isArray(e)?e:[];function li(e,t={}){let n=[],r=ci(e.pages);for(let e=0;e<r.length;e++){let i=r[e];if(!i||i.kind!==`html`&&i.kind!==`jsx`)continue;let a=String(i.name??`#${e}`),o=i.source;if(typeof o!=`string`||o.trim()===``){n.push({severity:`error`,rule:`jsx-page-empty-source`,where:`page "${a}"`,path:`pages[${e}].source`,message:`kind:'${i.kind}' page has no \`source\`.`,hint:"Author the page as a constrained JSX/Tailwind string in `source`."});continue}let{diagnostics:s}=t.manifest?Je(o,t.manifest):Ie(o);for(let t of s)n.push({severity:t.severity,rule:`jsx-${t.code}`,where:t.tag?`page "${a}" \u203A <${t.tag}>`:`page "${a}"`,path:`pages[${e}].source`,message:t.message,hint:`The source is parsed (never executed) and compiled to the SDUI tree at save time — fix the JSX.`})}return n}var ui=null;function di(){if(ui)return ui;let e=import.meta.url?import.meta.url:typeof __filename<`u`?__filename:process.cwd()+`/`;try{ui=(0,S.createRequire)(e)(`sucrase`).transform}catch(e){throw Error(`@objectstack/lint: validating a kind:'react' page requires the "sucrase" package, which could not be loaded (${e instanceof Error?e.message:String(e)}). It is a declared dependency of @objectstack/lint \u2014 if this deployment prunes packages, keep "sucrase" in the image; it is only loaded when a react-source page is validated.`)}return ui}var fi=e=>Array.isArray(e)?e:[];function pi(e){let t=[],n=fi(e.pages);for(let e=0;e<n.length;e++){let r=n[e];if(!r||r.kind!==`react`)continue;let i=String(r.name??`#${e}`),a=r.source;if(typeof a!=`string`||a.trim()===``){t.push({severity:`error`,rule:`react-page-empty-source`,where:`page "${i}"`,path:`pages[${e}].source`,message:"kind:'react' page has no `source`.",hint:"Author the page as a real React component string in `source`."});continue}let o=di();try{o(a,{transforms:[`jsx`,`typescript`],production:!0})}catch(n){let r=n instanceof Error?n.message:String(n);t.push({severity:`error`,rule:`react-page-syntax`,where:`page "${i}"`,path:`pages[${e}].source`,message:`kind:'react' source has a syntax error: ${r.split(`
2
- `)[0]}`,hint:`The source is transpiled (never executed) at build to catch syntax errors early — fix the JS/JSX.`})}}return t}var mi=`searchable-field-unknown`,hi=`searchable-field-unsearchable`,gi=`searchable-field-unprovisioned`;function _i(e){return Array.isArray(e)?e:e&&typeof e==`object`?Object.entries(e).map(([e,t])=>({name:e,...t})):[]}function D(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function O(e){return typeof e==`string`&&e.length>0?e:void 0}function vi(e){let t=e.fields;if(!t||typeof t!=`object`)return null;let n=new Set,r={};for(let e of _i(t)){let t=O(e.name);t&&(n.add(t),r[t]={type:typeof e.type==`string`?e.type:void 0,hidden:e.hidden===!0})}return n.size===0?null:{names:n,fields:r,searchableFields:Array.isArray(e.searchableFields)?e.searchableFields.filter(e=>typeof e==`string`):void 0,displayField:O(e.nameField)??O(e.displayNameField)}}function yi(e){let t=e.fields,n=(e.searchableFields??[]).filter(t=>!e.names.has(t)&&it.has(t));if(n.length>0){t={...t};for(let e of n)t[e]={}}let{allowed:r,source:i}=fe({fields:t,searchableFields:e.searchableFields,displayField:e.displayField});return{allowed:new Set(r),source:i,declaredList:r}}function bi(e,t){let n,r=1/0;for(let i of t){let t=xi(e,i);t<r&&(r=t,n=i)}let i=Math.max(2,Math.floor(e.length/3));return n&&r<=i?` Did you mean "${n}"?`:``}function xi(e,t){let n=e.length,r=t.length;if(n===0)return r;if(r===0)return n;let i=Array.from({length:r+1},(e,t)=>t);for(let a=1;a<=n;a++){let n=[a,...Array(r).fill(0)];for(let o=1;o<=r;o++){let r=e[a-1]===t[o-1]?0:1;n[o]=Math.min(n[o-1]+1,i[o]+1,i[o-1]+r)}i=n}return i[r]}function Si(e){let t=new Map;if(!D(e))return t;for(let n of _i(e.objects)){let e=O(n.name);e&&t.set(e,vi(n))}return t}function Ci(e,t,n,r,i,a,o=`narrowing`,s){let c=[];if(!Array.isArray(e)||e.length===0||!t||!n.has(t))return c;let l=n.get(t);if(!l)return c;let u=l.names,d=s?.get(t),f=o===`narrowing`?yi(l):void 0;for(let n=0;n<e.length;n++){let s=e[n],p=O(s);if(!p)continue;if(!u.has(p)&&!it.has(p)){let e=p.includes(`.`);c.push({severity:`error`,rule:mi,where:r,path:`${i}[${n}]`,message:`${a} entry "${p}" is not a field on object "${t}". The declaration is stale: searching it can never match, and the engine silently drops it \u2014 leaving a narrower search than declared, or the auto-default set once every entry is dropped.`+(e?``:bi(p,u)),hint:(e?`'search' scans this object's own columns, so a related record's column cannot be a search target — expand the relation and search the related object, or copy the value onto a stored text field here. `:`Fix the name, or add "${p}" to ${t}.fields. `)+`Clients echo this declaration verbatim as the '$searchFields' override, so a stale entry becomes a 400 INVALID_FIELD on list search (#4254), not just a quietly narrowed one.`+(u.size>0?` Object fields: ${[...u].sort().join(`, `)}.`:``)});continue}if(d?.has(p)&&c.push({severity:`warning`,rule:gi,where:r,path:`${i}[${n}]`,message:`${a} entry "${p}" resolves on object "${t}", but ${C(t,p)}`+(o===`narrowing`?` — clients echo this declaration verbatim as the '$searchFields' override, so every toolbar search on this list scans a column that is empty on every record: it reads as search coverage and matches nothing.`:` — 'search' scans it on every record and it can never match, so the object's searchable set is narrower than it declares. Should it be the ONLY entry that resolves, the set scans nothing at all.`),hint:w(t,p)}),g(l.fields[p])){let e=l.fields[p]?.type;c.push({severity:`error`,rule:hi,where:r,path:`${i}[${n}]`,message:`${a} entry "${p}" on object "${t}" is a virtual '${e}' field: its value is computed on read and never stored, so no driver materializes a column for 'search' to scan and the entry can never match. It reads as search coverage and delivers none \u2014 the runtime used to admit it verbatim because the declaration named it (#6674).`,hint:`Mirror the computed value onto a stored text field on "${t}" and declare that instead, or drop "${p}". At runtime the ingress gate now refuses this entry with 400 INVALID_FIELD, the same answer a stale entry gets (#4254).`});continue}if(!f||f.allowed.has(p)||!u.has(p))continue;let m=l.fields[p];if(f.source===`declared`){c.push({severity:`error`,rule:hi,where:r,path:`${i}[${n}]`,message:`${a} entry "${p}" is outside object "${t}"'s declared searchableFields (${f.declaredList.join(`, `)}) \u2014 the set 'search' scans. Clients echo this declaration verbatim as the '$searchFields' override, and the runtime refuses an entry outside the allowed set: every toolbar search on this list returns 400 INVALID_FIELD (#4254).`,hint:`Add "${p}" to ${t}.searchableFields, or drop it from this view \u2014 a view narrows the object's searchable set, never widens it (ADR-0061).`});continue}let h=m?.type===`lookup`||m?.type===`master_detail`,_;if(Ue.has(p))_=`a system/audit column, which the auto-default set never includes`;else if(m?.hidden)_=`hidden`;else if(typeof m?.type==`string`)_=`of type '${m.type}', which 'search' cannot scan`;else continue;c.push({severity:`error`,rule:hi,where:r,path:`${i}[${n}]`,message:`${a} entry "${p}" on object "${t}" is ${_}. With no 'searchableFields' declared on the object, 'search' scans its text-like columns (${[...Ke,...Me].join(` / `)}). Clients echo this declaration verbatim as the '$searchFields' override, and the runtime refuses it: every toolbar search on this list returns 400 INVALID_FIELD (#4254).`,hint:(h?`A ${m?.type} column stores only the referenced record's id, so it cannot be a keyword target \u2014 drop "${p}" from this view and, to search by the related record's title, mirror it onto a stored text field here and declare that instead. `:`Drop "${p}" from this view, or target a text-like field instead. `)+`Declaring 'searchableFields' on object "${t}" chooses the searchable set explicitly.`})}return c}function wi(e){let t=[];if(!D(e))return t;let n=_i(e.objects),r=Si(e),i=ct(e),a=(e,n,a,o,s,c)=>{t.push(...Ci(e,n,r,a,o,s,c,i))};for(let e=0;e<n.length;e++){let t=n[e];if(!D(t))continue;let r=O(t.name),i=r?`object "${r}"`:`objects[${e}]`;if(a(t.searchableFields,r,i,`objects[${e}].searchableFields`,`searchableFields`,`canonical`),D(t.listViews))for(let[n,o]of Object.entries(t.listViews))D(o)&&a(o.searchableFields,Ti(o)??r,`${i} \u203A listViews.${n}`,`objects[${e}].listViews.${n}.searchableFields`,`list-view searchableFields`,`narrowing`)}let o=_i(e.views);for(let e=0;e<o.length;e++){let t=o[e];if(!D(t))continue;let n=O(t.name)??O(t.objectName)??`#${e}`,r=O(t.objectName)??O(t.object);if(t.viewKind===`list`&&!D(t.config)&&a(t.searchableFields,Ti(t)??r,`view "${n}" (flattened list overlay)`,`views[${e}].searchableFields`,`list-view searchableFields`,`narrowing`),t.viewKind===`list`&&D(t.config)&&a(t.config.searchableFields,Ti(t.config)??r,`view "${n}" (ViewItem record)`,`views[${e}].config.searchableFields`,`list-view searchableFields`,`narrowing`),D(t.list)&&a(t.list.searchableFields,Ti(t.list)??r,`view "${n}" \u203A list`,`views[${e}].list.searchableFields`,`list-view searchableFields`,`narrowing`),D(t.listViews))for(let[i,o]of Object.entries(t.listViews))D(o)&&a(o.searchableFields,Ti(o)??r,`view "${n}" \u203A listViews.${i}`,`views[${e}].listViews.${i}.searchableFields`,`list-view searchableFields`,`narrowing`)}return t}function Ti(e){let t=e.data;return D(t)?O(t.object):void 0}function Ei(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function Di(e){return typeof e==`string`&&e.length>0?e:void 0}var Oi=new Set([`html`,`react`,`jsx`]);function ki(e){let t=Di(e.kind);return t!==void 0&&Oi.has(t)}function Ai(e,t){let n=[];if(!Ei(e)||ki(e))return n;let r=Di(e.object),i=(e,t,r)=>{if(!Ei(e))return;let a=Ei(e.properties)?e.properties:void 0,o=Di((Ei(e.dataSource)?e.dataSource:void 0)?.object)??Di(a?.object)??r;if(n.push({component:e,path:t,objectName:o}),a){if(Array.isArray(a.items))for(let e=0;e<a.items.length;e++){let n=a.items[e];if(!(!Ei(n)||!Array.isArray(n.children)))for(let r=0;r<n.children.length;r++)i(n.children[r],`${t}.properties.items[${e}].children[${r}]`,o)}if(Array.isArray(a.children))for(let e=0;e<a.children.length;e++)i(a.children[e],`${t}.properties.children[${e}]`,o);for(let e of[`body`,`footer`]){let n=a[e];if(Array.isArray(n))for(let r=0;r<n.length;r++)i(n[r],`${t}.properties.${e}[${r}]`,o)}}},a=Array.isArray(e.regions)?e.regions:[];for(let e=0;e<a.length;e++){let n=a[e];if(!(!Ei(n)||!Array.isArray(n.components)))for(let a=0;a<n.components.length;a++)i(n.components[a],`${t}.regions[${e}].components[${a}]`,r)}let o=Ei(e.slots)?e.slots:void 0;if(o)for(let[e,n]of Object.entries(o)){let a=Array.isArray(n)?n:[n],o=Array.isArray(n);for(let n=0;n<a.length;n++)i(a[n],`${t}.slots.${e}${o?`[${n}]`:``}`,r)}return n}var ji=`page-field-unknown`,Mi=`page-field-unprovisioned`;function Ni(e){return Array.isArray(e)?e:e&&typeof e==`object`?Object.entries(e).map(([e,t])=>({name:e,...t})):[]}function k(e){return typeof e==`string`&&e.length>0?e:void 0}function Pi(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function A(e,t){let n=[],r=(e,t)=>{let r=k(e);if(r){n.push({name:r,path:t});return}if(!Pi(e))return;let i=k(e.field)??k(e.name);i&&n.push({name:i,path:`${t}.${k(e.field)?`field`:`name`}`})};if(Array.isArray(e))for(let n=0;n<e.length;n++)r(e[n],`${t}[${n}]`);else r(e,t);return n}function Fi(e,t){if(typeof e==`string`){let n=e.trim().split(/\s+/)[0];return n?[{name:n,path:t}]:[]}return A(e,t)}var Ii={"record:highlights":{props:[`fields`]},"record:details":{props:[`fields`,`hideFields`],nestedSections:[`sections`]},"record:path":{props:[`statusField`]},"element:number":{props:[`field`]},"element:form":{props:[`fields`]},"element:record_picker":{props:[`labelField`]}},Li=`record:related_list`;function Ri(e,t,n,r=`.`){let i=Ii[e];if(!i)return null;let a=[];for(let e of i.props??[])a.push(...A(t[e],`${n}${r}${e}`));for(let e of i.nestedSections??[]){let i=Array.isArray(t[e])?t[e]:[];for(let t=0;t<i.length;t++){let o=i[t];Pi(o)&&a.push(...A(o.fields,`${n}${r}${e}[${t}].fields`))}}return a}function zi(e,t,n=`.`){let r=Pi(e.add)?e.add:void 0,i=r&&Pi(r.picker)?r.picker:void 0,a=e=>`${t}${n}${e}`;return{relatedObject:k(e.objectName),related:[...A(e.columns,a(`columns`)),...Fi(e.sort,a(`sort`)),...A(e.filter,a(`filter`)),...A(e.relationshipField,a(`relationshipField`)),...r?A(r.linkField,a(`add.linkField`)):[]],parent:A(e.relationshipValueField,a(`relationshipValueField`)),pickerObject:i?k(i.object):void 0,picker:i?[...A(i.valueField,a(`add.picker.valueField`)),...A(i.labelField,a(`add.picker.labelField`))]:[]}}function Bi(e){let t=new Map;if(!Pi(e))return t;for(let n of Ni(e.objects)){let e=k(n.name);if(!e)continue;let r=new Set;for(let e of Ni(n.fields)){let t=k(e.name);t&&r.add(t)}t.set(e,r)}return t}function Vi(e,t,n,r,i=`skipped`,a){let o=[];if(!t)return o;let s=n.get(t);if(!s)return o;let c=a?.get(t);for(let n of e)if(!n.name.includes(`.`)){if(s.has(n.name)||it.has(n.name)){c?.has(n.name)&&o.push({severity:`warning`,rule:Mi,where:r,path:n.path,message:`field "${n.name}" resolves on object "${t}", but ${C(t,n.name)}`+(i===`queried`?` — it is used in a QUERY, so the predicate can never match a real value: on SQLite it silently degrades to constant-false and the surface renders an empty result that looks exactly like "there is no data".`:` — the component renders it, blank, on every record.`),hint:w(t,n.name)});continue}o.push({severity:i===`queried`?`error`:`warning`,rule:ji,where:r,path:n.path,message:`field "${n.name}" is not a field on object "${t}" \u2014 `+(i===`queried`?`it is used in a QUERY, so the predicate can never match: the surface renders an empty result that looks exactly like "there is no data".`:`the component silently skips it, so it never renders.`),hint:`Fix the field name, or add "${n.name}" to ${t}. References must match the object's field names exactly.`+(s.size>0?` Object fields: ${[...s].sort().join(`, `)}.`:``)})}return o}function Hi(e){let t=[];if(!e||typeof e!=`object`)return t;let n=Bi(e),r=ct(e),i=Ni(e.pages);for(let e=0;e<i.length;e++){let a=i[e];if(!a||typeof a!=`object`)continue;let o=k(a.name)??`#${e}`,s=(e,i,a)=>{t.push(...Vi(e,i,n,a,`skipped`,r))};for(let{component:t,path:n,objectName:r}of Ai(a,`pages[${e}]`)){let e=k(t.type),i=Pi(t.properties)?t.properties:void 0;if(!e||!i)continue;let a=`page "${o}" \xB7 ${e}`,c=`${n}.properties`;if(e===Li){let e=zi(i,c);s(e.related,e.relatedObject,a),s(e.parent,r,a),s(e.picker,e.pickerObject,a);continue}let l=Ri(e,i,c);l&&s(l,r,a)}let c=Pi(a.interfaceConfig)?a.interfaceConfig:void 0;if(c){let t=k(c.source)??k(a.object),n=`pages[${e}].interfaceConfig`,r=[...A(c.columns,`${n}.columns`),...Fi(c.sort,`${n}.sort`),...A(c.filterBy,`${n}.filterBy`)],i=Pi(c.userFilters)?c.userFilters:void 0;i&&r.push(...A(i.fields,`${n}.userFilters.fields`)),s(r,t,`page "${o}" \xB7 interfaceConfig`)}}return t}var Ui=e=>!!e&&typeof e==`object`&&!Array.isArray(e),Wi=(e,t)=>{let n=e;for(let e of t){if(!Ui(n)&&!Array.isArray(n))return;n=n[e]}return n},Gi=e=>{let t;try{t=JSON.stringify(e)??String(e)}catch{t=String(e)}return t.length>80?`${t.slice(0,77)}\u2026`:t};function Ki(e,t,n=0){let r=n===0?Wi(t,e.path):void 0,i=n>0||e.code===`custom`||e.message.includes(`received `)?``:r===void 0?` (nothing is set there)`:` (received ${Gi(r)})`,a=e.code===`invalid_union`?e.errors:void 0;if(!a||a.length===0)return`${e.message}${i}`;let o=a.map(e=>e.map(e=>`${e.path.length?`${e.path.join(`.`)} \u2014 `:``}${Ki(e,t,n+1)}`).join(`; `)).filter(e=>e.length>0);return o.length===0?`${e.message}${i}`:`${e.message}${i} \u2014 no accepted form matched: `+o.map((e,t)=>`(${t+1}) ${e}`).join(` `)}var qi=null;function Ji(){if(qi)return qi;let e=import.meta.url?import.meta.url:typeof __filename<`u`?__filename:process.cwd()+`/`;try{qi=(0,S.createRequire)(e)(`typescript`)}catch(e){throw Error(`@objectstack/lint: validating a kind:'react' page requires the "typescript" package, which could not be loaded (${e instanceof Error?e.message:String(e)}). It is a declared dependency of @objectstack/lint \u2014 if this deployment prunes packages, keep "typescript" in the image; it is only loaded when a react-source page is validated.`)}return qi}var Yi=e=>Array.isArray(e)?e:[],Xi=new Map(je.map(e=>[e.tag,{requiredBindings:e.interactions.filter(e=>e.required).map(e=>e.name),knownProps:new Set(e.interactions.map(e=>e.name))}]));function Zi(e,t,n=2){if(Math.abs(e.length-t.length)>n)return n+1;let r=Array.from({length:e.length+1},(e,t)=>t);for(let n=1;n<=t.length;n++){let i=r[0];r[0]=n;for(let a=1;a<=e.length;a++){let o=r[a];r[a]=Math.min(r[a]+1,r[a-1]+1,i+(e[a-1]===t[n-1]?0:1)),i=o}}return r[e.length]}function Qi(e,t){if(t.has(e))return null;let n=null,r=3;for(let i of t){let t=Zi(e,i);t<r&&(r=t,n=i)}return r<=2?n:null}var j=Symbol(`not-static`);function $i(e,t,n){if(!n)return j;if(e.isParenthesizedExpression(n))return $i(e,t,n.expression);if(e.isStringLiteral(n)||e.isNoSubstitutionTemplateLiteral(n))return n.text;if(e.isNumericLiteral(n))return Number(n.text);if(n.kind===e.SyntaxKind.TrueKeyword)return!0;if(n.kind===e.SyntaxKind.FalseKeyword)return!1;if(n.kind===e.SyntaxKind.NullKeyword)return null;if(e.isArrayLiteralExpression(n)){let r=[];for(let i of n.elements){let n=$i(e,t,i);if(n===j)return j;r.push(n)}return r}if(e.isObjectLiteralExpression(n)){let r={};for(let i of n.properties){if(!e.isPropertyAssignment(i))return j;let n=e.isIdentifier(i.name)||e.isStringLiteral(i.name)?i.name.text:null;if(n===null)return j;let a=$i(e,t,i.initializer);if(a===j)return j;r[n]=a}return r}return j}function ea(e,t,n){let r=n.initializer;return r?e.isStringLiteral(r)?r.text:e.isJsxExpression(r)?$i(e,t,r.expression):j:!0}function ta(e,t,n){let r=n.initializer;if(!r||!e.isJsxExpression(r))return j;let i=n=>n?e.isParenthesizedExpression(n)?i(n.expression):e.isArrayLiteralExpression(n)?n.elements.map(e=>i(e)):$i(e,t,n):j;return i(r.expression)}var na=`react-page-source-unparseable`,ra=`react-chart-field-unknown`,ia=`react-chart-field-unprovisioned`,aa=`react-chart-aggregate-invalid`,oa=`react-chart-axis-unknown`,sa=`react-chart-drilldown-invalid`;function ca(e,t){if(e===void 0||e===j)return;if(!M(e)){t(`error`,sa,`drillDown must be a configuration object, not ${Array.isArray(e)?`an array`:typeof e}.`,`Write drillDown={{ … }} — or, to turn the drill on with all defaults, drillDown={{}}. Omit the prop entirely to leave drill off.`);return}let n=ve.safeParse(e);if(!n.success)for(let e of n.error.issues)t(`error`,sa,`${e.path.length?`drillDown.${e.path.join(`.`)}`:`drillDown`}: ${e.message}`,`The drill config is declared by ChartDrillDownSchema (@objectstack/spec/ui) — the rejection above carries the fix.`)}function la(e,t){if(e===void 0||e===j)return;if(!M(e)){t(`error`,aa,`aggregate must be a configuration object, not ${Array.isArray(e)?`an array`:typeof e}.`,`Write aggregate={{ function: "count", groupBy: "<field>" }} — or bind data={…} instead to chart precomputed rows.`);return}let n=e.groupBy===void 0;n&&t(`warning`,aa,`aggregate.groupBy is not set, so the aggregate returns ONE ungrouped row and the chart plots a single point.`,`Add aggregate.groupBy (a field name, or { field, dateGranularity } to bucket dates) to give the chart a category axis. objectstack#5583 ruled that an ungrouped single-value chart is NOT a supported <ObjectChart> shape — groupBy stays required, and a single number belongs in an object-metric block instead. This stays a warning rather than an error only because promoting it is its own step.`);let r=be.safeParse(e);if(!r.success)for(let i of r.error.issues)n&&i.path[0]===`groupBy`||t(`error`,aa,`${i.path.length?`aggregate.${i.path.join(`.`)}`:`aggregate`}: ${Ki(i,e)}`,`The aggregate is declared by ChartAggregateSchema (@objectstack/spec/ui) — the rejection above carries the fix.`)}var M=e=>!!e&&typeof e==`object`&&!Array.isArray(e),N=e=>typeof e==`string`&&e.length>0?e:void 0;function ua(e,t,n,r=new Map){let{values:i,where:a,path:o}=e,s=(e,t,r,i)=>n.push({severity:e,rule:t,where:a,path:o,message:r,hint:i});if(ca(i.get(`drillDown`),s),i.has(`data`))return;let c=i.get(`aggregate`);if(la(c,s),c===void 0||c===j||!M(c))return;let u=N(c.function),d=N(c.field),f=c.groupBy,p=N(f)??(M(f)?N(f.field):void 0),m=N(i.get(`objectName`)),h=m?t.get(m):void 0;if(m&&h){let e=r.get(m),t=(t,n)=>{if(t&&!t.includes(`.`)){if(h.has(t)||it.has(t)){e?.has(t)&&s(`warning`,ia,`aggregate.${n} "${t}" resolves on object "${m}", but ${C(m,t)} \u2014 the aggregate query reads a column that is empty on every row, so the chart ${n===`groupBy`?`groups everything into one empty bucket`:`aggregates nothing`} instead of failing.`,w(m,t));return}s(`error`,ra,`aggregate.${n} "${t}" is not a field on object "${m}" \u2014 the aggregate query has nothing to ${n===`groupBy`?`group by`:`aggregate`}, so the chart comes back empty.`,`Fix the field name, or add "${t}" to ${m}.`+(h.size>0?` Object fields: ${[...h].sort().join(`, `)}.`:``))}};t(d,`field`),t(p,`groupBy`)}let g=l({field:d,function:u,groupBy:f}),_=[g.category,g.value].filter(e=>!!e);if(_.length===0)return;let v=(e,t)=>{e&&(_.includes(e)||g.comparison&&e===g.comparison||s(`error`,oa,`"${e}" is not a column this aggregate returns, so the axis plots nothing. Object-bound aggregate rows are keyed by the RAW FIELD NAMES (unlike a dataset, whose rows are keyed by measure name).`,`Result columns: ${_.join(`, `)}`+(g.comparison?` (plus "${g.comparison}" with a comparison overlay)`:``)+`. Bind ${t} to one of them.`))},y=i.get(`xAxis`),b=N(i.get(`xAxisKey`))??N(y)??(M(y)?N(y.field):void 0),x=i.has(`xAxisKey`)?`xAxisKey`:`xAxis.field`;v(b,x);let ee=i.get(`yAxis`),te=Array.isArray(ee)?ee:ee===void 0?[]:[ee];for(let e of te)v(N(e)??(M(e)?N(e.field):void 0),`yAxis[].field`);let ne=i.get(`series`);if(Array.isArray(ne))for(let e of ne){if(!M(e))continue;let t=N(e.dataKey);v(t??N(e.name),t?`series[].dataKey`:`series[].name`)}b&&g.category&&b!==g.category&&b===g.value&&s(`error`,oa,`${x} "${b}" is the aggregate's VALUE column, not its category column.`,`The category axis is keyed by groupBy \u2014 bind it to "${g.category}".`)}var da={ListView:{fields:[`fields`,`columns`,`hiddenFields`,`fieldOrder`,`filterableFields`],sorts:[`sort`],nestedFields:[`userFilters`,`grouping`],filterArrays:[`filters`]},ObjectForm:{fields:[`fields`],keyedByField:[`initialValues`],sections:[`sections`,`groups`]},ObjectChart:{filterArrays:[`filter`]}},fa=` › `,pa=new Map(je.map(e=>[e.tag,e.schemaType])),ma=new Set(Object.values(da).flatMap(e=>e.filterArrays??[]));function ha(e){let t={};for(let[n,r]of e)r!==j&&(t[n]=r);return t}function ga(e,t){let n=[],r=[];if(!Array.isArray(e))return{child:n,parent:r};for(let i=0;i<e.length;i++){let a=e[i];if(!M(a))continue;let o=e=>`${t}[${i}].${e}`;n.push({objectName:N(a.childObject),refs:[...A(a.columns,o(`columns`)),...A(a.relationshipField,o(`relationshipField`)),...A(a.amountField,o(`amountField`))]}),r.push(...A(a.totalField,o(`totalField`)))}return{child:n,parent:r}}function _a(e,t,n){if(!Array.isArray(e)||e.length===0)return;let r=e[0];if(typeof r==`string`&&(r.toLowerCase()===`and`||r.toLowerCase()===`or`)){for(let r=1;r<e.length;r++)_a(e[r],`${t}[${r}]`,n);return}if(Array.isArray(r)){for(let r=0;r<e.length;r++)_a(e[r],`${t}[${r}]`,n);return}typeof r==`string`&&r.length>0&&e.length>=2&&typeof e[1]==`string`&&Pe.has(e[1].toLowerCase())&&n.push({name:r,path:`${t}[0]`})}function va(e,t,n){let r=[],i=[],a=e=>{let n=t.get(e);return n===j?void 0:n},o=e=>`${n}${fa}${e}`;for(let t of e.fields??[])r.push(...A(a(t),o(t)));for(let t of e.sorts??[])r.push(...Fi(a(t),o(t)));for(let t of e.nestedFields??[]){let e=a(t);M(e)&&r.push(...A(e.fields,o(`${t}.fields`)))}for(let t of e.sections??[]){let e=a(t);if(Array.isArray(e))for(let n=0;n<e.length;n++){let i=e[n];M(i)&&r.push(...A(i.fields,o(`${t}[${n}].fields`)))}}for(let t of e.keyedByField??[]){let e=a(t);if(M(e))for(let n of Object.keys(e))r.push({name:n,path:o(`${t}.${n}`)})}for(let n of e.filterArrays??[])_a(t.get(n),o(n),i);return{own:r,queried:i}}function ya(e,t,n,r,i,a){let o=N(t.get(`objectName`)),s=[],c=da[e];if(c){let{own:e,queried:l}=va(c,t,i);s.push(...Vi(e,o,n,r,`skipped`,a)),s.push(...Vi(l,o,n,r,`queried`,a))}if(e===`ObjectForm`){let e=t.get(`subforms`),c=ga(e===j?void 0:e,`${i}${fa}subforms`);for(let e of c.child)s.push(...Vi(e.refs,e.objectName,n,r,`skipped`,a));s.push(...Vi(c.parent,o,n,r,`skipped`,a))}let l=e===`Block`?N(t.get(`type`)):pa.get(e);return l&&Ii[l]&&s.push(...Vi(Ri(l,ha(t),i,fa)??[],o,n,r,`skipped`,a)),s}var ba=`react-block-needs-record-context`,xa="author the page as `type:'record'` — a record page mounts the record context these blocks render from.";function Sa(e,t,n,r){return{severity:`error`,rule:ba,where:n,path:r,message:`<${e}> renders "${t}", which reads its record from the record context a record page mounts \u2014 a kind:'react' page never mounts one, so the block renders empty no matter how it is bound (its objectName/recordId are not read by the renderer).`,hint:`On a react page bind the record yourself: ${Ge[t]??xa}`}}function Ca(e,t){let n=new Set,r=t=>{(e.isFunctionDeclaration(t)&&t.name||e.isVariableDeclaration(t)&&e.isIdentifier(t.name)||e.isImportSpecifier(t))&&n.add(t.name.text),e.forEachChild(t,r)};return r(t),n}function wa(e){let n=[],r=Bi(e),i=ct(e),a=Si(e),o=Yi(e.pages);for(let e=0;e<o.length;e++){let s=o[e];if(!s||s.kind!==`react`)continue;let c=s.source;if(typeof c!=`string`||c.trim()===``)continue;let l=String(s.name??`#${e}`),u=Ji(),{sourceFile:d,failure:f}=un(u,`page.tsx`,c,{target:u.ScriptTarget.Latest,setParentNodes:!0,scriptKind:u.ScriptKind.TSX});f&&n.push({severity:`warning`,rule:na,where:`page "${l}"`,path:`pages[${e}].source`,message:`kind:'react' source did not parse (${dn(f)}), so the component-contract checks read a partially recovered tree and may have missed real problems.`,hint:fn});let p=Ca(u,d),m=o=>{if(u.isJsxOpeningElement(o)||u.isJsxSelfClosingElement(o)){let s=o.tagName.getText(d),c=`page "${l}" \u203A <${s}>`,f=`pages[${e}].source`,h=He.get(s);if(h&&!p.has(s)){n.push(Sa(s,h,c,f)),u.forEachChild(o,m);return}let g=Xi.get(s);if(g){let e=!1,l=new Set,p=new Map;for(let t of o.attributes.properties){if(u.isJsxSpreadAttribute(t)){e=!0;continue}if(u.isJsxAttribute(t)){let e=t.name.getText(d);l.add(e),p.set(e,ma.has(e)?ta(u,d,t):ea(u,d,t))}}if(s===`Block`){let e=N(p.get(`type`));if(e&&t(e)){n.push(Sa(s,e,c,f)),u.forEachChild(o,m);return}}if(!e)for(let e of g.requiredBindings)l.has(e)||n.push({severity:`error`,rule:`react-prop-missing-required`,where:c,path:f,message:`<${s}> is missing the required prop "${e}".`,hint:`Pass ${e}={\u2026}. See the react-tier component contract.`});for(let e of l){let t=Qi(e,g.knownProps);t&&n.push({severity:`warning`,rule:`react-prop-typo`,where:c,path:f,message:`<${s}> has prop "${e}" \u2014 did you mean "${t}"?`,hint:`Likely a typo of a contract prop. Fix it or remove it.`})}s===`ObjectChart`&&!e&&ua({values:p,where:c,path:f},r,n,i),s===`ListView`&&!e&&n.push(...Ci(p.get(`searchableFields`),N(p.get(`objectName`)),a,c,`${f} \u203A searchableFields`,`searchableFields`,`narrowing`,i)),e||n.push(...ya(s,p,r,c,f,i))}}u.forEachChild(o,m)};m(d)}return n}var Ta=`page-source-className-tailwind`,Ea=e=>Array.isArray(e)?e:[],Da=/\bclassName\s*=\s*["'{]/g;function Oa(e){let t=[],n=Ea(e.pages);for(let e=0;e<n.length;e++){let r=n[e];if(!r)continue;let i=r.kind;if(i!==`html`&&i!==`react`&&i!==`jsx`)continue;let a=r.source;if(typeof a!=`string`||a.trim()===``)continue;let o=String(r.name??`#${e}`);Da.lastIndex=0;let s=0;for(;Da.exec(a)!==null;)s++;s!==0&&t.push({severity:`warning`,rule:Ta,where:`page "${o}"`,path:`pages[${e}].source`,message:`${s} \`className\` attribute${s>1?`s`:``} in ${String(i)}-source page \u2014 Tailwind utilities in page source silently produce no CSS (the build never scans authored metadata; ADR-0065).`,hint:i===`react`?`Style with inline style={{}} using hsl(var(--token)) theme colors (e.g. color:'hsl(var(--foreground))', background:'hsl(var(--card))'); render drawer/modal via <ObjectForm formType="drawer"|"modal"> instead of hand-rolled overlays.`:`Lay out with the components' structured props (<flex direction gap>, <grid columns>) and add CSS via a JSON style object style={{"color":"hsl(var(--foreground))"}}; do not use Tailwind className.`})}return t}var ka=`title-format-retired`,Aa=`title-unresolvable`;function ja(e){return Array.isArray(e)?e:e&&typeof e==`object`?Object.entries(e).map(([e,t])=>({name:e,...t})):[]}function Ma(e){let t=[],n=ja(e.objects);for(let e=0;e<n.length;e++){let r=n[e],i=typeof r.name==`string`?r.name:`(object ${e})`,a=`object "${i}"`,o=`objects[${e}]`;r.titleFormat!==void 0&&r.titleFormat!==null&&r.titleFormat!==``&&t.push({severity:`warning`,rule:ka,where:a,path:o,message:`${i}: titleFormat is retired (ADR-0079) \u2014 migrate to nameField (single field) or a formula field designated nameField`,hint:`titleFormat is a render-only template the server cannot return or query, and an explicit nameField now takes precedence. For a single-field title set nameField: '<field>'. For a composite title, add a formula field (returnType: 'text') and designate it via nameField.`}),ee(r).status===`none`&&t.push({severity:`warning`,rule:Aa,where:a,path:o,message:`${i}: no resolvable record title \u2014 records will have no meaningful name (no nameField and no title-eligible field to derive one)`,hint:`Set nameField to a text/email field (or a formula field with returnType: 'text'), or add a text field named "name"/"title". The runtime auto-provisions a primary and falls back to "Record #<id>", but an explicit title is far more useful.`})}return t}var Na=`field-group-undeclared`,Pa=`field-group-empty`,Fa=`field-group-shadowed`,Ia=`semantic-role-field-unknown`,La=`semantic-role-field-unprovisioned`;function Ra(e){return Array.isArray(e)?e:e&&typeof e==`object`?Object.entries(e).map(([e,t])=>({name:e,...t})):[]}function za(e){let t=[],n=Ra(e.objects);for(let e=0;e<n.length;e++){let r=n[e];if(!r||typeof r!=`object`)continue;let i=typeof r.name==`string`?r.name:`(object ${e})`,a=`object "${i}"`,o=`objects[${e}]`,s=r.fields&&typeof r.fields==`object`&&!Array.isArray(r.fields)?r.fields:{},c=new Set([...Object.keys(s),...at(r)]),l=ot(r),u=(e,t)=>({severity:`warning`,rule:La,where:a,path:`${o}.${e}`,message:`${i}: ${e} points at "${t}", an injected system column with no storage behind it \u2014 this object is external (ADR-0015), so the platform registers the anchor but the remote schema owns the table and no column backs it. Every consumer renders it empty on every record.`,hint:`If the remote table really carries "${t}", declare it in the object's own fields (mapped through the external binding's columnMap); otherwise point ${e} at a real remote column.`}),d=new Set((Array.isArray(r.fieldGroups)?r.fieldGroups:[]).filter(e=>!!e&&typeof e==`object`).map(e=>e.key).filter(e=>typeof e==`string`&&e.length>0)),f=new Set;for(let[e,n]of Object.entries(s)){let r=n?.group;typeof r==`string`&&r.length!==0&&(f.add(r),d.has(r)||t.push({severity:`warning`,rule:Na,where:a,path:`${o}.fields.${e}.group`,message:`${i}.${e}: group "${r}" is not declared in fieldGroups \u2014 the field renders in the ungrouped bucket, not under "${r}"`,hint:`Declare { key: '${r}', label: '\u2026' } in ${i}.fieldGroups, or fix the field's group reference. Group keys are snake_case and must match exactly.`}))}for(let e of d)f.has(e)||t.push({severity:`warning`,rule:Pa,where:a,path:`${o}.fieldGroups`,message:`${i}: fieldGroups declares "${e}" but no field references it \u2014 the group never renders`,hint:`Assign at least one field via group: '${e}', or remove the unused group declaration.`});let p=r.stageField;typeof p==`string`&&p.length>0&&!c.has(p)?t.push({severity:`warning`,rule:Ia,where:a,path:`${o}.stageField`,message:`${i}: stageField "${p}" is not a field on this object \u2014 consumers fall back to heuristic stage detection`,hint:`Point stageField at an existing select/status field, or set stageField: false to declare the object has no linear lifecycle.`}):typeof p==`string`&&l.has(p)&&t.push(u(`stageField`,p));let m=Array.isArray(r.highlightFields)?r.highlightFields:Array.isArray(r.compactLayout)?r.compactLayout:[];for(let e of m)if(typeof e==`string`&&e.length!==0){if(c.has(e)){l.has(e)&&t.push(u(`highlightFields`,e));continue}t.push({severity:`warning`,rule:Ia,where:a,path:`${o}.highlightFields`,message:`${i}: highlightFields entry "${e}" is not a field on this object \u2014 it is silently skipped by every consumer`,hint:`Fix the field name (highlightFields drives default columns, cards, previews and the detail highlight strip, in order).`})}let h=m.filter(e=>typeof e==`string`&&e.length>0);if(h.length>0&&d.size>0){let e=[r.nameField,r.displayNameField].find(e=>typeof e==`string`&&e.length>0&&c.has(e))??[`name`,`full_name`,`title`,`subject`,`display_name`].find(e=>c.has(e)),n=new Set(h.filter(t=>t!==e).slice(0,4)),l=new Set(n);e&&l.add(e);for(let e of d){let n=Object.entries(s).filter(([,t])=>t?.group===e&&t?.hidden!==!0).map(([e])=>e);n.length!==0&&n.every(e=>l.has(e))&&t.push({severity:`warning`,rule:Fa,where:a,path:`${o}.fieldGroups`,message:`${i}: every field in group "${e}" (${n.join(`, `)}) is hoisted into the detail highlight strip (or is the record title) \u2014 the group renders on forms but never on detail pages`,hint:`Keep at least one non-highlighted field in "${e}", or remove the group if the strip already covers it. (Detail pages show the first 4 highlightFields as the top strip and hide them from the body.)`})}}}return t}function Ba(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function Va(e,t){if(Array.isArray(e)){let n=[];for(let r=0;r<e.length;r++)Ba(e[r])&&n.push({rec:e[r],path:`${t}[${r}]`});return n}return Ba(e)?Object.entries(e).filter(([,e])=>Ba(e)).map(([e,n])=>({rec:{name:e,...n},path:`${t}.${e}`})):[]}function Ha(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function Ua(e){return typeof e==`string`&&e.length>0?e:void 0}function Wa(e){return Ua(e.objectName)??Ua(e.object)??(Ha(e.data)?Ua(e.data.object):void 0)}function Ga(e,t){if(!Ha(e))return[];let n=[{view:e,path:t,surface:``,kind:`self`}];Ha(e.form)&&n.push({view:e.form,path:`${t}.form`,surface:`form`,kind:`form`});for(let r of[`listViews`,`formViews`]){let i=e[r];if(!Ha(i))continue;let a=r===`listViews`?`listView`:`formView`;for(let[e,o]of Object.entries(i))Ha(o)&&n.push({view:o,path:`${t}.${r}.${e}`,surface:`${r}.${e}`,kind:a})}return n}function Ka(e,t){return Ga(e,t).filter(e=>e.kind!==`listView`)}var qa=`form-field-unknown`,Ja=`absolute-colspan-discouraged`;function Ya(e){return Array.isArray(e)?e:e&&typeof e==`object`?Object.entries(e).map(([e,t])=>({name:e,...t})):[]}function Xa(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function Za(e){return typeof e==`string`&&e.length>0?e:void 0}function Qa(e){if(typeof e==`string`)return e.length>0?e:null;if(e&&typeof e==`object`&&!Array.isArray(e)){let t=e.field;return typeof t==`string`&&t.length>0?t:null}return null}function $a(e){let t=[],n=new Map;for(let t of Ya(e.objects)){let e=typeof t.name==`string`?t.name:void 0;if(!e)continue;let r=t.fields&&typeof t.fields==`object`&&!Array.isArray(t.fields)?Object.keys(t.fields):[];n.set(e,new Set(r))}for(let{rec:r,path:i}of Va(e.views,`views`)){let e=Za(r.name)??Za(r.object)??i,a=Wa(r);for(let o of Ka(r,i)){let r=Wa(o.view)??a,i=r?n.get(r):void 0,s=o.surface?`view "${e}" \xB7 ${o.surface}`:`view "${e}"`;for(let n of[`sections`,`groups`]){let a=Array.isArray(o.view[n])?o.view[n]:[];for(let c=0;c<a.length;c++){let l=a[c],u=Xa(l)&&Array.isArray(l.fields)?l.fields:[];for(let a=0;a<u.length;a++){let l=u[a],d=Qa(l),f=`${o.path}.${n}[${c}].fields[${a}]`;d&&i&&!i.has(d)&&t.push({severity:`warning`,rule:qa,where:s,path:f,message:`${e}: field "${d}" is not a field on object "${r}" \u2014 it is silently skipped and never renders on the form`,hint:`Fix the field name, or add "${d}" to ${r}. Section field references must match the object's field names exactly.`});let p=Xa(l)?l.colSpan:void 0;p!=null&&t.push({severity:`warning`,rule:Ja,where:s,path:`${f}.colSpan`,message:`${e}: field "${d??`?`}" sets absolute colSpan ${String(p)} \u2014 the form's column count is derived per surface (mobile 1 / modal 2 / page 3-4), so a fixed span only aligns at one width`,hint:`Prefer span: 'full' (whole row at any column count), or omit for auto width. The renderer clamps colSpan to the current column count.`})}}}}}return t}function eo(e){return!!e&&typeof e==`object`&&typeof e.op==`string`}var to=new Set([`==`,`!=`]),no=new Set([`all`,`exists`,`exists_one`,`map`,`filter`]);function ro(e){return eo(e)&&e.op===`id`&&typeof e.args==`string`?e.args:null}function io(e){let t=new Set,n=new Set,r=(e,i)=>{if(Array.isArray(e)){for(let t of e)r(t,i);return}if(!eo(e))return;let a=e.args;if(e.op===`rcall`&&Array.isArray(a)&&typeof a[0]==`string`&&no.has(a[0])){r(a[1],i),r(a[2],!1);return}if(typeof e.op==`string`&&to.has(e.op)&&Array.isArray(a)&&a.length===2){let e=i?ro(a[1]):null;if(r(a[0],i),e!==null){t.add(e);return}r(a[1],i);return}let o=ro(e);if(o!==null){n.add(o);return}r(a,i)};r(e,!0);for(let e of n)t.delete(e);return t}function ao(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function oo(e){let t=e.data;if(ao(t)&&t.provider===`schema`)return typeof t.schemaId==`string`?t.schemaId:void 0}var so=`visibility-root-mislayered`,co=`visibility-bare-identifier`,lo=`visibility-predicate-syntax`,uo=`visibility-predicate-over-budget`,fo=`visibleWhen`;function po(e){if(typeof e==`string`)return e;if(e&&typeof e==`object`&&typeof e.source==`string`)return e.source}function mo(e,t){return RegExp(`(^|[^.\\w$])${t}\\.\\w`).test(e)}function ho(e){return e.replace(/'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"/g,e=>` `.repeat(e.length))}var go=[{wrote:`===`,cel:`==`,example:`record.country == 'USA'`,re:/===/},{wrote:`!==`,cel:`!=`,example:`record.country != 'USA'`,re:/!==/},{wrote:`<>`,cel:`!=`,example:`record.country != 'USA'`,re:/<>/},{wrote:`and`,cel:`&&`,example:`record.a == 1 && record.b == 2`,re:/(?<![.\w$])and(?![\w$])/i},{wrote:`or`,cel:`||`,example:`record.a == 1 || record.b == 2`,re:/(?<![.\w$])or(?![\w$])/i},{wrote:`not`,cel:`!`,example:`!record.archived`,re:/(?<![.\w$])not(?![\w$])/i},{wrote:`=`,cel:`==`,example:`record.status == 'open'`,re:/(?<![=!<>])=(?!=)/}];function _o(e){let t=e.replace(/\s+/g,` `).trim();return t.length>120?`${t.slice(0,117)}...`:t}function vo(e){if(!e.trim())return null;let t=oe(e);if(t.ok||t.kind===`empty`)return null;if(t.kind===`bounds`)return{kind:`bounds`,overrun:t.overrun};let n=d(e),r=n.ok?`the expression could not be parsed`:n.error.split(`
3
- `)[0].trim(),i=ho(e);return{kind:`syntax`,detail:r,token:go.find(e=>e.re.test(i))??null}}function yo(e){return e.limit&&e.limitValue!==null?`the \`${e.limit}\` budget (platform limit ${e.limitValue})`:`one of the platform's parse budgets`}var bo=[`current_user`,`page`];function xo(e){return!!e&&typeof e==`object`&&typeof e.op==`string`}function So(e,t){if(Array.isArray(e)){for(let n of e)So(n,t);return}if(!xo(e))return;let n=e.args;if(Array.isArray(n)){let r=e.op===`rcall`?n[1]:n[0];(e.op===`.`||e.op===`.?`||e.op===`[]`||e.op===`rcall`)&&xo(r)&&r.op===`id`&&typeof r.args==`string`&&t.add(r.args)}So(n,t)}function Co(e,t){let n=xe(e);if(!n)return null;let r=new Set;So(n,r);let i=t?io(n):[];return _(e,[...bo,...r,...i])}var wo={runtime:`record`,metadata:`data`},To={runtime:{forbiddenRoot:`data`,message:"visibility predicate is rooted at `data.` — that is the root a metadata-editing form binds (the row under edit), not a runtime surface. A runtime view/page predicate that binds `data.` never matches and the element renders unconditionally (ADR-0089).",hint:"Runtime record surfaces bind `record` + `current_user` (pages also expose `page.<var>`). Use e.g. `record.status == 'open'` instead of `data.status == 'open'`."},metadata:{forbiddenRoot:`record`,message:"visibility predicate is rooted at `record.` — that is the root a runtime view/page surface binds (the live record), not the root a metadata-editing form binds. On a metadata-editing form — the row under edit — a `record.`-rooted predicate never matches and the element renders unconditionally (ADR-0089).",hint:"Metadata-editing forms bind `data` (the row under edit). Use e.g. `data.type == 'grid'` instead of `record.type == 'grid'`."}};function Eo(e,t,n,r,i,a=!1){let o=po(e[fo]??e.visibleOn??e.visibility),s=To[r];o&&mo(o,s.forbiddenRoot)&&i.push({severity:`warning`,rule:so,where:t,path:n,message:s.message,hint:s.hint});let c=o?vo(o):null;if(o&&c?.kind===`bounds`){let e=yo(c.overrun),a=wo[r];i.push({severity:`error`,rule:uo,where:t,path:n,message:`visibility predicate is syntactically valid CEL but overruns ${e} (${c.overrun.summary}) (predicate: \`${_o(o)}\`). The canonical front end refuses it, so it can never evaluate, and the console falls OPEN: the element renders unconditionally and looks exactly like one with no predicate at all (#5149).`,hint:`There is no syntax or dialect error to correct here \u2014 this is a SIZE fault, not a dialect mistake, so re-spelling the predicate will not fix it. Make it smaller, or move the work off the predicate: (1) collapse a long \`${a}.f == 'a' || ${a}.f == 'b' || \u2026\` chain into a single \`${a}.f in ['a', 'b', \u2026]\`, which is far fewer AST nodes (\`maxListElements\` is 64, so a very large set needs option 2); (2) precompute the heavy part into a formula/rollup field on the object and test that one field instead. Logic genuinely this large is not element visibility \u2014 compute it once on the record rather than re-deriving it in every predicate that needs it.`})}if(o&&c?.kind===`syntax`&&i.push({severity:`error`,rule:lo,where:t,path:n,message:`visibility predicate is not valid CEL \u2014 ${c.detail} (predicate: \`${_o(o)}\`). A predicate that does not parse can never evaluate, and the console falls OPEN: the element renders unconditionally and looks exactly like one with no predicate at all (#5149).`,hint:c.token?`\`${c.token.wrote}\` is not a CEL operator \u2014 CEL spells it \`${c.token.cel}\`. Replace \`${c.token.wrote}\` with \`${c.token.cel}\`, e.g. \`${c.token.example}\`.`:"Visibility predicates are bare CEL, e.g. `record.status == 'open'`. Spellings from other languages do not parse: write `==` (not `===`), `!=` (not `!==` or `<>`), `&&` (not `and`), `||` (not `or`), `!` (not `not`)."}),o&&!c){let e=Co(o,a);if(e){let a=wo[r];i.push({severity:`error`,rule:co,where:t,path:n,message:`visibility predicate references \`${e}\` as a bare identifier. Values are bound under a namespace on this surface \u2014 they are never flattened to top level \u2014 so \`${e}\` resolves to nothing, the predicate can never evaluate, and the console falls OPEN: the element renders unconditionally and looks exactly like one with no predicate at all (#5149).`,hint:`Write \`${a}.${e}\` instead of \`${e}\``+(r===`runtime`?" (runtime view/page surfaces bind `record` + `current_user`; a page component also exposes page state as `page.<var>`).":" (a metadata-editing form binds the row under edit as `data`).")})}}}function Do(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function Oo(e,t={}){let n=t.layer??`runtime`,r=[];for(let{rec:t,path:i}of Va(e.views,`views`)){let e=typeof t.name==`string`?t.name:typeof t.object==`string`?t.object:i;for(let a of Ka(t,i)){let t=a.surface?`view "${e}" \xB7 ${a.surface}`:`view "${e}"`,i=oo(a.view)!==void 0,o=i,s=i?`metadata`:n;for(let e of[`sections`,`groups`]){let n=Array.isArray(a.view[e])?a.view[e]:[];for(let i=0;i<n.length;i++){let c=n[i];if(!c||typeof c!=`object`)continue;let l=`${a.path}.${e}[${i}]`;Eo(c,t,l,s,r,o);let u=Array.isArray(c.fields)?c.fields:[];for(let e=0;e<u.length;e++){let n=u[e];Do(n)&&Eo(n,t,`${l}.fields[${e}]`,s,r,o)}}}}}for(let{rec:t,path:i}of Va(e.pages,`pages`)){let e=`page "${(typeof t.name==`string`?t.name:void 0)??i}"`;for(let a of Ai(t,i))Eo(a.component,e,a.path,n,r)}return r}var ko=`predicate-path-unresolved`,Ao=`predicate-path-unrooted`,jo=`predicate-rhs-path-shaped`,Mo=[`visibleWhen`,`visibleOn`],P=`data`;function No(e){if(!e||typeof e!=`object`&&typeof e!=`function`)return;let t=e;return t.def??t._def}function F(e,t=0){if(!e||t>25)return e;let n=No(e);if(!n)return e;switch(n.type){case`optional`:case`nullable`:case`default`:case`prefault`:case`readonly`:case`catch`:case`nonoptional`:return F(n.innerType,t+1);case`lazy`:return F(n.getter(),t+1);case`pipe`:{let e=F(n.in,t+1);return No(e)?.type===`transform`?F(n.out,t+1):e}default:return e}}function Po(e){return Array.isArray(e?.options)?e.options:[]}function Fo(e,t=0){if(t>25)return null;let n=F(e),r=No(n);if(r?.type===`object`)return Object.keys(r.shape??n.shape??{});if(r?.type===`union`||r?.type===`discriminated_union`){let e=new Set,n=!1;for(let i of Po(r)){let r=Fo(i,t+1);if(r){n=!0;for(let t of r)e.add(t)}}return n?[...e]:null}if(r?.type===`intersection`){let e=Fo(r.left,t+1),n=Fo(r.right,t+1);return!e&&!n?null:[...new Set([...e??[],...n??[]])]}return null}function Io(e,t,n=0){if(n>25)return;let r=F(e),i=No(r);if(i?.type===`object`)return(i.shape??r.shape??{})[t];if(i?.type===`union`||i?.type===`discriminated_union`)for(let e of Po(i)){let r=Io(e,t,n+1);if(r!==void 0)return r}if(i?.type===`intersection`)return Io(i.left,t,n+1)??Io(i.right,t,n+1)}function Lo(e,t){let n=Io(e,t);if(n===void 0)return;let r=F(n);for(let e=0;e<25;e++){let e=No(r);if(e?.type===`array`)r=F(e.element);else if(e?.type===`record`)r=F(e.valueType);else return r}return r}function Ro(e,t){let n=F(e),r=No(n);if(r?.type===`record`)return{kind:`declared`,next:r.valueType};let i=Fo(n);return i===null?{kind:`opaque`}:i.includes(t)?{kind:`declared`,next:Io(n,t)}:{kind:`undeclared`,declared:i}}function zo(e){return!!e&&typeof e==`object`&&typeof e.op==`string`}function Bo(e){if(!zo(e))return null;if(e.op===`id`&&typeof e.args==`string`)return[e.args];if(e.op===`.`&&Array.isArray(e.args)&&typeof e.args[1]==`string`){let t=Bo(e.args[0]);return t?[...t,e.args[1]]:null}return null}function Vo(e,t){if(Array.isArray(e)){for(let n of e)Vo(n,t);return}if(zo(e)){if(e.op===`.`){let n=Bo(e);if(n&&n[0]===P&&n.length>1){t.push(n.slice(1));return}}Vo(e.args,t)}}var Ho=/^[A-Za-z_$][A-Za-z0-9_$]*(?:\.[A-Za-z_$][A-Za-z0-9_$]*)*$/;function Uo(e,t){if(Array.isArray(e)){for(let n of e)Uo(n,t);return}if(!zo(e))return;let n=e.args;if(e.op===`rcall`&&Array.isArray(n)&&typeof n[0]==`string`&&no.has(n[0])){Uo(n[1],t);return}typeof e.op==`string`&&to.has(e.op)&&Array.isArray(n)&&n.length===2&&t.push({op:e.op,right:n[1]}),Uo(n,t)}function Wo(e,t,n){if(Array.isArray(e)){for(let r of e)Wo(r,t,n);return}if(!zo(e))return;let r=e.args;if(Array.isArray(r)){let t=e.op===`rcall`?r[1]:r[0];if((e.op===`.`||e.op===`.?`||e.op===`[]`||e.op===`rcall`)&&zo(t)&&t.op===`id`&&typeof t.args==`string`&&n.add(t.args),e.op===`rcall`&&typeof r[0]==`string`&&no.has(r[0])){let e=r[2];if(Array.isArray(e)&&e.length>=2){let t=e[0];zo(t)&&t.op===`id`&&typeof t.args==`string`&&n.add(t.args)}}}if(e.op===`id`&&typeof e.args==`string`){t.add(e.args);return}Wo(r,t,n)}function Go(e){if(typeof e==`string`)return e;if(e&&typeof e==`object`&&typeof e.source==`string`)return e.source}function Ko(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function qo(e,t,n,r,i){let a=xe(e);if(!a)return;let o=[];Vo(a,o);for(let e of o){let a=t,o=[];for(let t of e){let e=Ro(a,t);if(e.kind===`opaque`)break;if(e.kind===`undeclared`){let a=[P,...o,t].join(`.`),s=o.length?`${P}.${o.join(`.`)}`:P;i.push({severity:`error`,rule:ko,where:n,path:r,message:`predicate references \`${a}\`, which the target schema does not declare \u2014 \`${t}\` is not a key of \`${s}\`. The reference resolves to nothing, so the predicate can never evaluate and the console falls OPEN: the element renders unconditionally and looks exactly like one carrying no predicate at all (#5149).`,hint:`${f(he(t,e.declared))||`\`${s}\` declares: ${e.declared.slice(0,12).sort().join(`, `)}`} Every reference must resolve against the schema the form edits.`});break}o.push(t),a=e.next}}let s=Fo(t),c=io(a);if(s){let e=new Set,t=new Set;Wo(a,e,t);for(let a of e)t.has(a)||c.has(a)||!s.includes(a)||i.push({severity:`error`,rule:Ao,where:n,path:r,message:`predicate references \`${a}\` as a bare identifier, but \`${a}\` is a key of the schema this form edits \u2014 the binding root was dropped. Values are bound under \`${P}\` and are never flattened to top level, so \`${a}\` resolves to nothing, the predicate can never evaluate and the console falls OPEN: the element renders unconditionally and looks exactly like one carrying no predicate at all (#5149, #6254).`,hint:`Write \`${P}.${a}\` instead of \`${a}\`. A metadata-editing form binds the row under edit as \`${P}\` at every depth \u2014 inside a repeater \`${P}\` is the ROW, but it is still spelled \`${P}\` (there is no implicit row scope).`})}let l=[];Uo(a,l);for(let{op:e,right:t}of l){let a=Bo(t);if(!a)continue;let o=a.join(`.`);if(!Ho.test(o))continue;let s=a.length>1;i.push({severity:s?`error`:`warning`,rule:jo,where:n,path:r,message:s?`predicate compares against \`${o}\` on the RIGHT of \`${e}\`, which is a path but is not evaluated as one. A metadata-editing form resolves paths on the LEFT of \`${e}\` only; the right-hand side goes to the literal parser, so \`${o}\` is compared as the literal string "${o}". The verdict therefore does not depend on the right-hand path at all: \`a == ${o}\` is FALSE even when both sides hold the same value, and \`a != ${o}\` is correspondingly TRUE. An \`==\` written this way hides the element on every row, and nothing in the console says why (objectui#4049).`:`predicate compares against the unquoted word \`${o}\` on the RIGHT of \`${e}\`. The right-hand side of \`${e}\` is a literal, never a reference, so this is read as the literal string "${o}" \u2014 which is probably what you meant, and is why it appears to work. It is outside the declared subset all the same (\`path == 'literal'\`), and it stops working when this surface moves to the real CEL evaluator, where a bare \`${o}\` resolves to nothing (objectui#4049). The token also reads as a \`${P}.\` root someone dropped, so this one finding carries BOTH readings: which one you meant is the thing no linter can know, and it changes the fix (#7696).`,hint:s?`Two sanctioned spellings. (1) If you meant the TEXT, quote it: \`${e} '${o}'\`. (2) If you meant the PATH, restructure so the path is on the LEFT and a literal is on the right \u2014 comparing one path against another is outside the subset this surface renders, which is \`path == 'literal'\` / \`path != 'literal'\` and nothing wider. There is no third spelling that compares two paths here.`:`Two sanctioned spellings, and you must pick \u2014 they are not the same predicate. (1) If you meant the TEXT \`${o}\`, quote it: \`${e} '${o}'\`. That is what this renders as today, so it changes no behaviour and is the fix unless you know otherwise. (2) If you meant the FIELD \`${P}.${o}\`, move it to the LEFT and put a literal on the right, e.g. \`${P}.${o} == 'yes'\`. \u26D4 Do NOT simply add the root in place: \`${e} ${P}.${o}\` is a path on the RIGHT, which this surface parses as the literal string "${P}.${o}" \u2014 it is refused by this same rule at \`error\`, and it is FALSE on every row. The subset here is \`path == 'literal'\` and nothing wider.`})}}function Jo(e,t,n,r,i,a){if(!(!Array.isArray(e)||a>12))for(let o=0;o<e.length;o++){let s=e[o];if(!Ko(s))continue;let c=`${r}[${o}]`;for(let e of Mo){let r=Go(s[e]);if(r!==void 0&&r.trim()){qo(r,t,n,`${c}.${e}`,i);break}}if(Array.isArray(s.fields)&&s.fields.length>0&&typeof s.field==`string`){let e=t===void 0?void 0:Lo(t,s.field);Jo(s.fields,e,n,`${c}.fields`,i,a+1)}}}function Yo(e,t={}){let n=t.resolveSchema??(e=>ce(e)),r=[];for(let{rec:t,path:i}of Va(e.views,`views`)){let e=typeof t.name==`string`?t.name:typeof t.object==`string`?t.object:i;for(let a of Ka(t,i)){let t=oo(a.view);if(!t)continue;let i;try{i=n(t)}catch{i=void 0}let o=a.surface?`view "${e}" \xB7 ${a.surface} (schema "${t}")`:`view "${e}" (schema "${t}")`;for(let e of[`sections`,`groups`]){let t=Array.isArray(a.view[e])?a.view[e]:[];for(let n=0;n<t.length;n++){let s=t[n];if(!Ko(s))continue;let c=`${a.path}.${e}[${n}]`;for(let e of Mo){let t=Go(s[e]);if(t!==void 0&&t.trim()){qo(t,i,o,`${c}.${e}`,r);break}}Jo(s.fields,i,o,`${c}.fields`,r,0)}}}}return r}var Xo=`capability-reference-unknown`;function Zo(e){return Array.isArray(e)?e:e&&typeof e==`object`?Object.entries(e).map(([e,t])=>({name:e,...t})):[]}function Qo(e){return Array.isArray(e)?e.filter(e=>typeof e==`string`&&e.length>0):[]}function $o(e){if(Array.isArray(e))return Qo(e).map(e=>({cap:e}));if(e&&typeof e==`object`){let t=[];for(let[n,r]of Object.entries(e))for(let e of Qo(r))t.push({cap:e,key:n});return t}return[]}function es(e){let t=[];if(!e||typeof e!=`object`)return t;let n=new Set(r);for(let t of Zo(e.capabilities))typeof t.name==`string`&&t.name.length>0&&n.add(t.name);for(let t of Zo(e.permissions))for(let e of Qo(t.systemPermissions))n.add(e);for(let t of Zo(e.data))if(t.object===`sys_capability`)for(let e of Array.isArray(t.records)?t.records:[]){let t=e?.name;typeof t==`string`&&t.length>0&&n.add(t)}let i=(e,r,i)=>{n.has(e)||t.push({severity:`warning`,rule:Xo,where:r,path:i,message:`requiredPermissions references capability "${e}" which is registered nowhere \u2014 no built-in capability, no permission set in this package grants it via systemPermissions, and no sys_capability seed declares it`,hint:`Fix the capability name, define it with defineCapability (stack.capabilities), declare it on a permission set’s systemPermissions, ship a sys_capability seed row, or ignore this if the capability is provided by another installed package (references fail closed at runtime).`})},a=Zo(e.objects);for(let e=0;e<a.length;e++){let t=a[e];if(!t||typeof t!=`object`)continue;let n=typeof t.name==`string`?t.name:`(object ${e})`,r=`objects[${e}]`;for(let{cap:e,key:a}of $o(t.requiredPermissions))i(e,`object "${n}"`,`${r}.requiredPermissions${a?`.${a}`:``}`);let o=Zo(t.fields);for(let e of o){let t=typeof e.name==`string`?e.name:`(field)`;for(let a of Qo(e.requiredPermissions))i(a,`field "${n}.${t}"`,`${r}.fields.${t}.requiredPermissions`)}for(let[e,a]of Zo(t.actions).entries()){let t=typeof a.name==`string`?a.name:`(action ${e})`;for(let o of Qo(a.requiredPermissions))i(o,`action "${n}.${t}"`,`${r}.actions[${e}].requiredPermissions`)}}for(let[t,n]of Zo(e.actions).entries()){let e=typeof n.name==`string`?n.name:`(action ${t})`;for(let r of Qo(n.requiredPermissions))i(r,`action "${e}"`,`actions[${t}].requiredPermissions`)}let o=Zo(e.apps);for(let e=0;e<o.length;e++){let t=o[e];if(!t||typeof t!=`object`)continue;let n=typeof t.name==`string`?t.name:`(app ${e})`,r=(e,t)=>{if(!e||typeof e!=`object`)return;if(Array.isArray(e)){e.forEach((e,n)=>r(e,`${t}[${n}]`));return}let a=e;for(let e of Qo(a.requiredPermissions))i(e,`app "${n}"`,`${t}.requiredPermissions`);a.navigation&&r(a.navigation,`${t}.navigation`),a.areas&&r(a.areas,`${t}.areas`),a.tabs&&r(a.tabs,`${t}.tabs`),a.children&&r(a.children,`${t}.children`),a.items&&r(a.items,`${t}.items`)};r(t,`apps[${e}]`)}return t}var ts=`approval-approver-not-membership-tier`,ns=`approval-approver-type-deprecated`,rs=`approval-approver-type-unknown`,is=`approval-approver-type-unsupported`,as=`approval-escalation-reassign-no-target`,os=`approval-approvers-may-resolve-empty`,ss=`approval-expression-invalid`,cs=`approval-expression-no-empty-policy`,ls=`approval-decision-outputs-reserved`,us=`approval-approver-cross-org-unsupported`,ds=new Set([`current`,`trigger`,`vars`]),fs=new Set([`decision`,`requestId`]),ps=new Set([`position`,`team`,`department`]),ms=new Set(x),hs=x.join(`/`),gs={business_unit:`department`,bu:`department`};function _s(e){return Array.isArray(e)?e:e&&typeof e==`object`?Object.entries(e).map(([e,t])=>({name:e,...t})):[]}function vs(e){let t=[];if(!e||typeof e!=`object`)return t;let n=_s(e.flows),r=new Set(tt.options);for(let e=0;e<n.length;e++){let i=n[e];if(!i||typeof i!=`object`)continue;let a=typeof i.name==`string`?i.name:`(flow ${e})`,o=gr(i,`flows[${e}]`);for(let e=0;e<o.length;e++){let{node:n,path:i}=o[e];if(!n||n.type!==`approval`)continue;let s=typeof n.id==`string`?n.id:`(node ${e})`,l=n.config??{},u=Array.isArray(l.approvers)?l.approvers:[],f=`flow "${a}" \xB7 node "${s}"`;for(let e=0;e<u.length;e++){let n=u[e];if(!n||typeof n!=`object`)continue;let a=typeof n.type==`string`?n.type:``,o=typeof n.value==`string`?n.value:``,s=`${i}.config.approvers[${e}]`;if(a&&!r.has(a)){let e=gs[a];t.push({severity:`warning`,rule:rs,where:f,path:`${s}.type`,message:`approver type '${a}' is not an ApproverType (${tt.options.join(` | `)}).`,hint:e?`Use the spec value: { type: '${e}', value: '${o}' }.`:`Pick one of the spec values; unmapped types degrade to an inert '${a}:${o}' literal at runtime.`});continue}let l=c(a);if(l===`expression`){let e=o.trim();if(!e)t.push({severity:`error`,rule:ss,where:f,path:`${s}.value`,message:`expression approver has an empty expression — the node fails at entry.`,hint:`Write a CEL expression over current.* (the record's live state at node entry), trigger.* (the submit-time snapshot) or vars.* (flow variables), e.g. current.approvers_dynamic or vars.approval_lead.picked_departments.`});else{let n=d(e);if(!n.ok)t.push({severity:`error`,rule:ss,where:f,path:`${s}.value`,message:`expression approver does not parse as CEL: ${n.error}.`,hint:`Approver expressions are bare CEL (no {…} template braces), e.g. current.approvers_dynamic or vars.get_reviewers.record.owner_id.`});else{let e=n.roots.filter(e=>!ds.has(e));if(e.length){let n=e.includes(`record`)||e.includes(`previous`);t.push({severity:`error`,rule:ss,where:f,path:`${s}.value`,message:`expression approver references \`${e.join("`, `")}\` \u2014 only current.*, trigger.* and vars.* are available, and the node fails at entry on any other root.`,hint:n?'`record`/`previous` are not bound here (on this platform `record` always means "the record at event time", which is ambiguous at an approval node). Write current.<field> for the live value at node entry, trigger.<field> for the submit-time snapshot (vars.previous carries the pre-update row).':`Did you mean current.<field> (live record), trigger.<field> (submit snapshot), or vars.<name> (flow variable)?`})}}}}else n.resolveAs!=null&&t.push({severity:`info`,rule:ss,where:f,path:`${s}.resolveAs`,message:`resolveAs has no effect on a '${a}' approver \u2014 it only applies to type 'expression'.`,hint:`Remove it, or switch this approver to { type: 'expression', value: '<CEL>', resolveAs: '${String(n.resolveAs)}' }.`});if(l===`org_membership_level`&&o&&!ms.has(o.toLowerCase()))t.push({severity:`warning`,rule:ts,where:f,path:`${s}.value`,message:`approver { type: '${a}', value: '${o}' } resolves against the better-auth org-membership tier (sys_member.role: ${hs}) \u2014 '${o}' is not a membership tier, so this approver matches nobody and the request stalls.`,hint:`If '${o}' is an org position, author { type: 'position', value: '${o}' } (resolved via sys_user_position, ADR-0090 D3). Keep type 'org_membership_level' only for membership tiers (${hs}) \u2014 the vocabulary is closed (ADR-0108), so a business role is always a position.`});else if(a in Te){let e=c(a);t.push({severity:`warning`,rule:ns,where:f,path:`${s}.type`,message:`approver type '${a}' is the deprecated spelling of '${e}' (ADR-0090 D3) and is removed in the next major.`,hint:`Author { type: '${e}', value: '${o}' }. It resolves identically today.`})}else Ce[l]?.source===`unsupported`&&t.push({severity:`warning`,rule:is,where:f,path:`${s}.type`,message:`approver type '${a}' is declared but not implemented by the runtime (#3508) \u2014 the slot resolves to nobody and the request stalls.`,hint:`Route to people the engine can expand: { type: 'team' | 'department' | 'position', ... }. Queue approvers need a real ownership-queue implementation before they take effect.`});let p=n.organization;typeof p==`string`&&p.trim()!==``&&tt.options.includes(l)&&!Qe(l)&&t.push({severity:`error`,rule:us,where:f,path:`${s}.organization`,message:`approver type '${a}' does not resolve through an organization directory, so 'organization: ${p}' has no effect (ADR-0105 D9) \u2014 the runtime refuses it.`,hint:`Drop 'organization' here. Cross-organization targeting applies to 'position', 'org_membership_level', 'department' and 'expression' approvers.`})}let p=u.filter(e=>e&&typeof e==`object`&&typeof e.type==`string`);if(p.length>0&&p.every(e=>ps.has(c(String(e.type))))){let e=l.lockRecord!==!1;t.push({severity:`info`,rule:os,where:f,path:`${i}.config.approvers`,message:`every approver on this node routes to a group (position/team/department) whose members are runtime data — if none is staffed, the request resolves to an empty slate and waits forever`+(e?`, and (lockRecord) the record stays locked with no in-product recovery.`:`.`),hint:`Make sure at least one target is always staffed, or add a guaranteed-staffed fallback approver, e.g. { type: 'org_membership_level', value: 'owner' }. A request that still lands empty is recoverable only by a platform/tenant admin override (#3424).`})}u.some(e=>e&&typeof e==`object`&&c(String(e.type??``))===`expression`)&&l.onEmptyApprovers==null&&t.push({severity:`info`,rule:cs,where:f,path:`${i}.config`,message:`this node resolves approvers from an expression but declares no onEmptyApprovers — an empty result falls back to the default ('admin_rescue': request opens, only a privileged admin can act).`,hint:`Declare the empty-slate policy explicitly: onEmptyApprovers: 'admin_rescue' (hold for admin takeover), 'fail' (fail the node — config bug), or 'auto_approve' (wave through, output.autoApproved = true).`});let m=re(l.decisionOutputs).map(e=>e.key).filter(e=>fs.has(e));m.length&&t.push({severity:`error`,rule:ls,where:f,path:`${i}.config.decisionOutputs`,message:`decisionOutputs declares reserved key(s) \`${m.join("`, `")}\` \u2014 the resume envelope owns them, so every decide carrying them is rejected.`,hint:`Rename the output key(s); any name other than 'decision'/'requestId' works.`});let h=l.escalation??null;h&&typeof h==`object`&&h.action===`reassign`&&(typeof h.escalateTo==`string`&&h.escalateTo.trim()||t.push({severity:`warning`,rule:as,where:f,path:`${i}.config.escalation.escalateTo`,message:`escalation.action is 'reassign' but escalateTo is empty — at runtime the escalation degrades to a notify and the request stays with the original approvers.`,hint:`Set escalateTo to a position machine name (expanded via sys_user_position, ADR-0090 D3) or a specific user id, or change action to 'notify'.`}))}}return t}var ys=`seed-insert-mode-duplicates-on-replay`;function bs(e){let t=[];return(Array.isArray(e.data)?e.data:[]).forEach((e,n)=>{if(!e||typeof e!=`object`||e.mode!==`insert`)return;let r=typeof e.object==`string`?e.object:void 0,i=r?`seed "${r}"`:`data[${n}]`;t.push({severity:`warning`,rule:ys,where:i,path:`data[${n}].mode`,message:"`mode: 'insert'` re-inserts every record on each replay boot (dev-server restart, package re-publish) with no existing-row check, so the dataset duplicates the table on every restart — seeds are replayed, not applied once.",hint:"Use `mode: 'ignore'` (skip rows that already exist) or `'upsert'` (create-or-update), and declare an `externalId` to match on: a single natural-key field (e.g. `externalId: 'code'`), or a COMPOSITE list of fields for a join / junction table with no single natural key (e.g. `externalId: ['team', 'project']`)."})}),t}var xs=`seed-value-outside-state-machine`;function Ss(e){let t=new Map;for(let n of e){if(!n||typeof n!=`object`)continue;let e=typeof n.name==`string`?n.name:void 0;if(!e)continue;let r=Array.isArray(n.validations)?n.validations:[],i=[];for(let e of r){if(!e||typeof e!=`object`||e.type!==`state_machine`)continue;let t=typeof e.field==`string`?e.field:void 0;if(!t)continue;let n=e.transitions&&typeof e.transitions==`object`?e.transitions:{},r=new Set;for(let t of Array.isArray(e.initialStates)?e.initialStates:[])r.add(String(t));for(let e of Object.keys(n)){r.add(String(e));let t=n[e];for(let e of Array.isArray(t)?t:[])r.add(String(e))}r.size>0&&i.push({field:t,states:r})}i.length>0&&t.set(e,i)}return t}function Cs(e,t,n){let r=(Array.isArray(t)?t.map(String):typeof t==`string`?[t]:[`name`]).map(t=>e[t]).filter(e=>e!=null&&e!==``);return r.length>0?r.map(String).join(` · `):`#${n}`}function ws(e){let t=[],n=Array.isArray(e.objects)?e.objects:[],r=Array.isArray(e.data)?e.data:[];if(n.length===0||r.length===0)return t;let i=Ss(n);return i.size===0||r.forEach((e,n)=>{if(!e||typeof e!=`object`)return;let r=typeof e.object==`string`?e.object:void 0;if(!r)return;let a=i.get(r);a&&(Array.isArray(e.records)?e.records:[]).forEach((i,o)=>{if(!(!i||typeof i!=`object`))for(let s of a){let a=i[s.field];a!=null&&a!==``&&typeof a==`string`&&(s.states.has(a)||t.push({severity:`warning`,rule:xs,where:`seed "${r}" (${Cs(i,e.externalId,o)})`,path:`data[${n}].records[${o}].${s.field}`,message:`seeds '${s.field}=${a}', which the '${r}' state machine does not declare (known states: ${[...s.states].sort().join(`, `)}). Seed writes are exempt from the state_machine rule (#3433), so this is NOT rejected at write time \u2014 a typo lands silently.`,hint:`If '${a}' is a real state, add it to the state machine (as an initial state or a transition endpoint). If it is a typo, correct it to a declared state. The exemption lets a seed be born mid-lifecycle; it is not a licence to write an unknown state.`}))}})}),t}var Ts=`security-owd-unset`,Es=`security-owd-alias`,Ds=`security-external-wider-than-internal`,Os=`security-wildcard-vama`,ks=`security-anchor-high-privilege`,As=`security-role-word`,js=`security-book-audience-unknown-set`,Ms=`security-private-no-readscope`,Ns=`security-master-detail-ungranted`,Ps=`security-fls-unqualified-key`,Fs=`security-grant-expired-at-authoring`,Is=`security-delegation-missing-reason`,Ls=`security-controlled-by-parent-no-relation`,Rs=[`private`,`public_read`,`public_read_write`,`controlled_by_parent`],zs={read:`public_read`,read_write:`public_read_write`,full:`public_read_write`,public:`public_read_write`},Bs={private:0,public_read:1,public_read_write:2};function I(e){return Array.isArray(e)?e:e&&typeof e==`object`?Object.entries(e).map(([e,t])=>({name:e,...t})):[]}function Vs(e){return e.sharingModel}function Hs(e){return e.isSystem===!0||String(e.name??``).startsWith(`sys_`)}function Us(e){return typeof e==`string`&&e.toLowerCase().split(/[^a-z0-9]+/).some(e=>e===`role`||e===`roles`)}function Ws(e){return typeof e==`string`&&/\brole(s)?\b/i.test(e)}function Gs(e){let t=e.reference;return typeof t==`string`&&t?t:void 0}function Ks(e){for(let t of I(e.fields))if(t.type===`master_detail`)return{name:String(t.name??`?`),parent:Gs(t)}}function qs(e){let t=I(e.fields),n=e=>t.find(t=>e(t)&&Gs(t)),r=n(e=>e.type===`master_detail`&&!!e.required)??n(e=>e.type===`master_detail`)??n(e=>e.type===`lookup`&&!!e.required);if(r)return{field:String(r.name??`?`),type:String(r.type),master:Gs(r)}}function Js(e){return e.allowRead===!0||e.allowCreate===!0||e.allowEdit===!0||e.allowDelete===!0||e.viewAllRecords===!0||e.modifyAllRecords===!0}function Ys(e,t){let n=[];if(!e||typeof e!=`object`)return n;let r=I(e.objects),i=I(e.permissions);for(let e=0;e<r.length;e++){let t=r[e];if(!t||typeof t!=`object`)continue;let i=typeof t.name==`string`?t.name:`(object ${e})`,a=`objects[${e}]`,o=Vs(t),s=t.externalSharingModel;Hs(t)||(o==null?n.push({severity:`error`,rule:Ts,where:`object "${i}"`,path:`${a}.sharingModel`,message:`custom object "${i}" declares no sharingModel (OWD). The runtime fails CLOSED to 'private' (ADR-0090 D1), but the baseline must be an authored decision, not an accident \u2014 this is the exact shape of the leave_request incident (objectui#2348).`,hint:`Declare sharingModel explicitly: 'private' (owner + shares; recommended default), 'public_read', 'public_read_write', or 'controlled_by_parent' (master-detail children).`}):typeof o==`string`&&zs[o]?n.push({severity:`error`,rule:Es,where:`object "${i}"`,path:`${a}.sharingModel`,message:`sharingModel '${o}' is a retired alias (ADR-0090 D4). The runtime fails CLOSED to 'private' on unknown values, so this object is NOT ${o===`read`?`readable`:`writable`} org-wide.`,hint:`Replace with the canonical value: sharingModel: '${zs[o]}'.`}):typeof o==`string`&&!Rs.includes(o)&&n.push({severity:`error`,rule:Es,where:`object "${i}"`,path:`${a}.sharingModel`,message:`sharingModel '${o}' is not a canonical OWD value; the runtime fails CLOSED to 'private'.`,hint:`Use one of: ${Rs.join(`, `)}.`})),o===`controlled_by_parent`&&!qs(t)&&n.push({severity:`error`,rule:Ls,where:`object "${i}"`,path:`${a}.sharingModel`,message:`"${i}" declares sharingModel 'controlled_by_parent' but has no relation the platform can derive access from. ADR-0055 resolves the master through a required master_detail, then any master_detail, then a required lookup \u2014 each of which must also name a reference target \u2014 and this object matches none of the three. At runtime every read is DENIED and every write is refused with 422 INVALID_METADATA (#7474), so the object is unusable rather than merely locked down.`,hint:`Add the master relation this object is derived from, e.g. fields.parent: { type: 'master_detail', reference: '<master_object>', required: true }. If the object has no master, its baseline is its own decision — use sharingModel: 'private' (owner + shares), 'public_read', or 'public_read_write'.`}),typeof s==`string`&&(zs[s]?n.push({severity:`error`,rule:Es,where:`object "${i}"`,path:`${a}.externalSharingModel`,message:`externalSharingModel '${s}' is a retired alias (ADR-0090 D4).`,hint:`Replace with the canonical value: externalSharingModel: '${zs[s]}'.`}):typeof o==`string`&&s in Bs&&o in Bs&&Bs[s]>Bs[o]&&n.push({severity:`error`,rule:Ds,where:`object "${i}"`,path:`${a}.externalSharingModel`,message:`externalSharingModel '${s}' is WIDER than the internal sharingModel '${o}' \u2014 the external baseline must never exceed the internal one (ADR-0090 D11).`,hint:`Narrow externalSharingModel to '${o}' or below (ordering: private < public_read < public_read_write).`}))}for(let e=0;e<i.length;e++){let t=i[e];if(!t||typeof t!=`object`)continue;let r=typeof t.name==`string`?t.name:`(permission set ${e})`,a=`permissions[${e}]`,o=t.objects&&typeof t.objects==`object`?t.objects:{},s=t.fields&&typeof t.fields==`object`?t.fields:{};for(let e of Object.keys(s))e.includes(`.`)||n.push({severity:`error`,rule:Ps,where:`permission set "${r}"`,path:`${a}.fields["${e}"]`,message:`field-permission key '${e}' is not object-qualified \u2014 the runtime matches FLS keys by '<object>.<field>' prefix, so a bare key is silently IGNORED and the declared masking never enforces.`,hint:`Qualify the key with its object, e.g. 'crm_opportunity.${e}': { readable: true, editable: false }.`});let c=o[`*`];if(c&&(c.viewAllRecords===!0||c.modifyAllRecords===!0)&&n.push({severity:`error`,rule:Os,where:`permission set "${r}"`,path:`${a}.objects.*`,message:`'*' wildcard carrying View All / Modify All Data — a package-authored superuser. Only the platform's own admin set may combine the wildcard with VAMA (ADR-0066).`,hint:`Enumerate the objects this set really needs, or drop viewAllRecords/modifyAllRecords from the wildcard entry. App-level admins belong in an ordinary set the customer binds to a position of their choosing (ADR-0090 D9).`}),t.isDefault===!0){let e=pe(t,`everyone`);e&&n.push({severity:`error`,rule:ks,where:`permission set "${r}"`,path:`${a}.isDefault`,message:`isDefault:true suggests binding this set to the 'everyone' audience anchor, but it carries ${e} \u2014 the runtime will refuse the binding (ADR-0090 D5/D9).`,hint:`Split the powerful bits into a separate set granted through ordinary positions, and keep the everyone-suggested set low-privilege.`})}}let a=new Set(i.map(e=>typeof e.name==`string`?e.name:void 0).filter(e=>!!e));for(let[t,r]of I(e.books).entries()){let e=r.audience;if(!e||typeof e!=`object`)continue;let i=e.permissionSet;typeof i==`string`&&i.length!==0&&(a.has(i)||n.push({severity:`warning`,rule:js,where:`book "${String(r.name??t)}"`,path:`books[${t}].audience.permissionSet`,message:`book audience references permission set "${i}", which this stack does not declare. The runtime fails closed \u2014 no holder means NO reader can open the book.`,hint:`Gate the book on one of this package's own permission sets (ADR-0090 D9, e.g. its admin set), or fix the typo. Ignore if the set is intentionally provided by another installed package.`}))}let o=new Set(r.filter(e=>e&&typeof e==`object`&&!Hs(e)).filter(e=>{let t=Vs(e);return t==null||t===`private`}).map(e=>String(e.name??``)));if(o.size>0)for(let e=0;e<i.length;e++){let t=i[e];if(!t||typeof t!=`object`)continue;let r=typeof t.name==`string`?t.name:`(permission set ${e})`,a=t.objects&&typeof t.objects==`object`?t.objects:{};for(let[t,i]of Object.entries(a)){if(!o.has(t))continue;let a=i??{};a.allowRead===!0&&a.readScope==null&&a.viewAllRecords!==!0&&n.push({severity:`info`,rule:Ms,where:`permission set "${r}"`,path:`permissions[${e}].objects.${t}.readScope`,message:`"${t}" is private (OWD) and this set grants allowRead without a readScope \u2014 holders see ONLY records they own (plus explicit shares).`,hint:`If that is intended (personal data), ignore this. Otherwise add readScope: 'own_and_reports' | 'unit' | 'unit_and_below' | 'org', or widen the object's sharingModel.`})}}if(i.length>0&&!i.some(e=>Js(e.objects?.[`*`]??{}))){let e=new Set;for(let t of i){let n=t.objects&&typeof t.objects==`object`?t.objects:{};for(let[t,r]of Object.entries(n))t!==`*`&&Js(r??{})&&e.add(t)}for(let t=0;t<r.length;t++){let i=r[t];if(!i||typeof i!=`object`||Hs(i))continue;let a=typeof i.name==`string`?i.name:``;if(!a||e.has(a))continue;let o=Ks(i);if(!o)continue;let s=o.parent?` \u2192 "${o.parent}"`:``;n.push({severity:`warning`,rule:Ns,where:`object "${a}"`,path:`objects[${t}].fields.${o.name}`,message:`detail object "${a}" (master_detail "${o.name}"${s}) has no object-level CRUD grant in any permission set. A master-detail child derives its RECORD-level access from the master (ADR-0055 controlled_by_parent), but object-level CRUD is a SEPARATE gate that is never derived \u2014 role-bound non-admin users are denied (403) before the parent-derived access is ever consulted (the silent "can't submit the subtable" trap).`,hint:`Grant "${a}" in at least one permission set that already grants its master${o.parent?` "${o.parent}"`:``} \u2014 e.g. permissions[i].objects.${a} = { allowRead: true, allowCreate: true, allowEdit: true }. If no role should ever touch it (a pure system/internal table), name it sys_* or set isSystem: true.`})}}let s=new Set([`sys_user_position`,`sys_user_permission_set`]),c=new Set([`sys_user_position`]),l=t?.nowMs??Date.now();for(let[t,r]of I(e.data).entries()){let e=typeof r.object==`string`?r.object:``;if(!s.has(e))continue;let i=Array.isArray(r.records)?r.records:[];for(let r=0;r<i.length;r++){let a=i[r]??{},o=`seed "${e}" record #${r}`,s=a.valid_until;if(s!=null&&s!==``){let e=typeof s==`number`?s<0xe8d4a51000?s*1e3:s:s instanceof Date?s.getTime():typeof s==`string`?Date.parse(s):NaN;(Number.isNaN(e)||e<=l)&&n.push({severity:`error`,rule:Fs,where:o,path:`data[${t}].records[${r}].valid_until`,message:Number.isNaN(e)?`valid_until ${JSON.stringify(s)} is not a parseable timestamp \u2014 the resolver fails closed (ADR-0091 D2), so this grant will NEVER be active.`:`valid_until ${JSON.stringify(s)} is already in the past \u2014 this grant is expired at authoring time and will never resolve (ADR-0091 D2 filters it fail-closed).`,hint:`Set valid_until to a future instant (ISO-8601 UTC), or drop the column for an unbounded grant. If the row is a historical record, it belongs in audit history, not seed data.`})}let u=a.delegated_from;if(c.has(e)&&u!=null&&u!==``){let e=a.reason;(typeof e!=`string`||e.trim().length===0)&&n.push({severity:`error`,rule:Is,where:o,path:`data[${t}].records[${r}].reason`,message:`delegation row (delegated_from = ${JSON.stringify(u)}) has no reason. ADR-0091 D3 requires a mandatory reason on every delegation for the dual audit trail (granted_by = writer, delegated_from = authority source, reason = why).`,hint:`Add reason: 'vacation stand-in for 张三, 2026-08-01..15' (free text, required).`})}}}return n}function Xs(e){let t=[];if(!e||typeof e!=`object`)return t;let n=I(e.objects),r=I(e.permissions),i=(e,n,r,i,a)=>{Us(n)?t.push({severity:`error`,rule:As,where:i,path:a,message:`${e} name "${String(n)}" uses the reserved word "role" \u2014 the platform vocabulary is permission_set (capability), position (distribution), business_unit (hierarchy) (ADR-0090 D3).`,hint:`Rename using 'position' for distribution groups or a domain word (e.g. 'function', 'duty').`}):Ws(r)&&t.push({severity:`error`,rule:As,where:i,path:`${a.replace(/\.name$/,``)}.label`,message:`${e} label "${String(r)}" uses the reserved word "role" (ADR-0090 D3).`,hint:`Relabel with 'Position' (distribution) or a domain word — admins must meet ONE vocabulary.`})};for(let e=0;e<n.length;e++){let t=n[e];if(!t||typeof t!=`object`||Hs(t))continue;let r=typeof t.name==`string`?t.name:`(object ${e})`;i(`object`,t.name,t.label,`object "${r}"`,`objects[${e}].name`);for(let n of I(t.fields))i(`field`,n.name,n.label,`field "${r}.${String(n.name??`?`)}"`,`objects[${e}].fields.${String(n.name??`?`)}.name`);for(let[n,a]of I(t.actions).entries())i(`action`,a.name,a.label,`action "${r}.${String(a.name??`?`)}"`,`objects[${e}].actions[${n}].name`)}for(let e=0;e<r.length;e++){let t=r[e];!t||typeof t!=`object`||i(`permission set`,t.name,t.label,`permission set "${String(t.name??e)}"`,`permissions[${e}].name`)}for(let[t,n]of I(e.positions).entries())i(`position`,n.name,n.label,`position "${String(n.name??t)}"`,`positions[${t}].name`);for(let[t,n]of I(e.apps).entries())i(`app`,n.name,n.label,`app "${String(n.name??t)}"`,`apps[${t}].name`);for(let[t,n]of I(e.books).entries())i(`book`,n.name,n.label,`book "${String(n.name??t)}"`,`books[${t}].name`);return t}var Zs=`org-axis-permission-inheritance`,Qs=`org-axis-cross-org-bu-grant`,$s=`parent_organization_id`,ec=new Set([`business_unit`,`unit_and_subordinates`]);function tc(e){return Array.isArray(e)?e:e&&typeof e==`object`?Object.entries(e).map(([e,t])=>({name:e,...t})):[]}function nc(e){return typeof e==`string`?e:``}function rc(e){if(typeof e==`string`)return e;if(e&&typeof e==`object`){let t=e;if(typeof t.source==`string`)return t.source;if(t.ast!==void 0)return JSON.stringify(t.ast)??``}return``}function ic(e){let t=e.tenancy;if(t&&typeof t==`object`&&t.enabled===!1)return!0;let n=e.systemFields;return!!(n&&typeof n==`object`&&n.tenant===!1)}var ac=`Remove the ${$s} reference. Cross-organization visibility comes from MEMBERSHIP: under the \`group\` tenancy posture the engine's Layer 0 wall is \`organization_id IN accessible_org_ids\`, so a user who should see several organizations is made a member of them (ADR-0105 D2). A Layer-1 policy cannot widen Layer 0 anyway, so this rule would not grant the access it appears to. For a hierarchy INSIDE one organization, use the business-unit tree (\`unit_and_subordinates\` sharing, or a depth scope anchored on \`sys_user_position\`).`;function oc(e){let t=[],n=e??{};tc(n.permissions).forEach((e,n)=>{tc(e.rowLevelSecurity).forEach((r,i)=>{for(let a of[`using`,`check`])nc(r[a]).includes($s)&&t.push({severity:`error`,rule:Zs,where:`permission set "${nc(e.name)||n}" policy "${nc(r.name)||i}"`,path:`permissions[${n}].rowLevelSecurity[${i}].${a}`,message:`RLS ${a} reads \`${$s}\`, which builds a permission hierarchy along the organization axis. ADR-0105 D6 forbids it: the org tree is a REPORTING dimension only.`,hint:ac})})}),tc(n.sharingRules).forEach((e,n)=>{let r=[{key:`condition`,text:rc(e.condition)},{key:`sharedWith`,text:JSON.stringify(e.sharedWith??``)??``}];for(let i of r)i.text.includes($s)&&t.push({severity:`error`,rule:Zs,where:`sharing rule "${nc(e.name)||n}"`,path:`sharingRules[${n}].${i.key}`,message:`Sharing rule ${i.key} reads \`${$s}\`, granting access by walking the organization tree. ADR-0105 D6 forbids permission inheritance along the org axis.`,hint:ac})});let r=new Set(tc(n.objects).filter(e=>ic(e)).map(e=>nc(e.name)).filter(Boolean));return tc(n.sharingRules).forEach((e,n)=>{let i=nc(e.object);if(!i||!r.has(i))return;let a=e.sharedWith,o=nc(a?.type);if(!ec.has(o))return;let s=o===`unit_and_subordinates`?`a business unit AND every descendant unit`:`a business unit`;t.push({severity:`error`,rule:Qs,where:`sharing rule "${nc(e.name)||n}" on object "${i}"`,path:`sharingRules[${n}].sharedWith`,message:`Sharing rule recipient \`${o}\` (${s}) targets "${i}", which opted out of tenancy (\`tenancy.enabled: false\`). Platform-global objects carry no organization column, so this grant spans EVERY organization \u2014 a cross-organization business-unit grant, which ADR-0105 D6 forbids (BU trees are org-internal).`,hint:"Either scope the object to organizations (drop `tenancy.enabled: false` so Layer 0 walls it), or share it to a `user` / `team` / `position` audience instead — those expand flat, with no business-unit tree to resolve. A platform-global catalog that everyone should read wants an OWD of `public_read`, not a BU grant."})}),t}var sc=`sharing-rule-unlowerable-condition`,cc=`sharing-rule-runtime-variable-condition`,lc=`sharing-rule-object-not-shareable`,uc=`sharing-rule-object-controlled-by-parent`;function dc(e){return Array.isArray(e)?e:e&&typeof e==`object`?Object.entries(e).map(([e,t])=>({name:e,...t})):[]}function fc(e){return typeof e==`string`?e:``}function pc(e){if(typeof e==`string`)return e.trim()?e:null;if(e&&typeof e==`object`){let t=e.source;if(typeof t==`string`&&t.trim())return{source:t}}return null}function mc(e){let t=pc(e);return typeof t==`string`?t:fc(t?.source)}var hc="The lowerable subset is: `==` `!=` `>` `<` `>=` `<=`, `in`, `&&` `||` `!`, `== null` / `!= null`, and the string methods `startsWith` / `endsWith` / `contains` — over SINGLE-column `record.<field>` paths (ADR-0058 D2).";function gc(e){let t=e.sharingModel;return t===`private`?`private`:t===`public_read`?`read`:t===`public_read_write`||t===`controlled_by_parent`||t==null&&(e.isSystem===!0||fc(e.name).startsWith(`sys_`))?`public`:`private`}function _c(e){for(let t of dc(e.fields))if(t.type===`master_detail`){let e=t.reference;if(typeof e==`string`&&e)return e}}function vc(e,t,n){let r=fc(e.object);if(!r)return[];let i=n.get(r);if(!i)return[];let a=fc(e.name)||String(t),o=`sharing rule "${a}" on object "${r}"`,s=`sharingRules[${t}].object`,c=i.sharingModel;if(c===`controlled_by_parent`){let e=_c(i);return[{severity:`error`,rule:uc,where:o,path:s,message:`Sharing rule "${a}" is anchored on object "${r}", which declares sharingModel 'controlled_by_parent'. A detail record has no record-level access of its own \u2014 its visibility is DERIVED from its master (ADR-0055), so it holds no shares to widen. \`SharingService.assertNotInertGrant\` refuses the grant with SHARING_NOT_ENABLED ("'${r}' is controlled by its parent (master-detail); share the master record instead"), so the rule's boot backfill fails, no \`sys_record_share\` row is ever written, and the recipients this rule names get whatever the MASTER grants them \u2014 which may be nothing. The grant is declared and does not exist.`,hint:`Move the rule onto the MASTER object`+(e?` \u2014 "${r}" derives from "${e}" through its master_detail field, so share "${e}" and the detail rows follow`:`, and share that instead; the detail rows follow`)+`. If "${r}" is meant to carry a record-level baseline of its own, that is a different decision: change its sharingModel to 'private' (owner + shares) or 'public_read', and this rule becomes enforceable where it stands.`}]}return gc(i)===`public`?[{severity:`error`,rule:lc,where:o,path:s,message:`Sharing rule "${a}" is anchored on object "${r}", which ${c===`public_read_write`?`declares sharingModel 'public_read_write'`:"declares no sharingModel and is a system object (`isSystem: true` or a `sys_` name), which ADR-0090 D1 resolves to public"}. Its effective sharing model is therefore \`public\`, and sharing only ever WIDENS an OWD baseline \u2014 on the widest baseline there is nothing left to widen. \`SharingService.assertNotInertGrant\` refuses the grant with SHARING_NOT_ENABLED ("'${r}' is not under record-sharing enforcement"), so the rule's boot backfill fails and no \`sys_record_share\` row is ever written. Measured: \`buildReadFilter\` returns \`null\` for this object, i.e. NO record-level filter at all \u2014 every principal already reads every row, so this rule advertises a restriction that does not exist.`,hint:`Decide which half is wrong. If the ACCESS is right \u2014 everyone should read and write these records \u2014 the rule is dead metadata: delete it (ADR-0049 enforce-or-remove). If the RULE is right \u2014 only the named audience should reach these records \u2014 then "${r}"'s OWD is the defect: set sharingModel: 'private' (owner + shares) or 'public_read', and this rule starts enforcing. Do NOT re-home the rule onto another public object; that moves the inertness instead of removing it.`}]:[]}function yc(e){let t=[],n=e??{},r=new Map;for(let e of dc(n.objects)){let t=fc(e.name);t&&r.set(t,e)}return dc(n.sharingRules).forEach((e,n)=>{vc(e,n,r).forEach(e=>t.push(e));let i=pc(e.condition);if(i===null)return;let a=y(i,{variables:{}});if(a.ok||a.reason===`parse-error`)return;let o=fc(e.name)||String(n),s=fc(e.object),c=`sharing rule "${o}"${s?` on object "${s}"`:``}`,l=`sharingRules[${n}].condition`,u=mc(e.condition);if(a.reason===`unresolved-variable`){t.push({severity:`error`,rule:cc,where:c,path:l,message:`Sharing-rule condition \`${u}\` reads a runtime variable (${a.detail}), so \`bootstrapDeclaredSharingRules\` SKIPS the rule at boot: it is never written to \`sys_sharing_rule\`, no \`sys_record_share\` grant is ever materialised, and the only signal is one WARN line in the boot log. The rule is declared and grants nothing (ADR-0049: an unlowerable condition is never seeded as a permissive match-all).`,hint:"A criteria sharing rule is MATERIALISED: the seeder compiles ONE static `criteria_json` per rule and the evaluator writes `sys_record_share` rows from it, so there is no \"current user\" for the condition to read. Express per-user access with the mechanism that runs per request instead — an RLS policy on a permission set (`rowLevelSecurity[].using`, where `current_user.*` IS resolved), or the record-ownership path. Keep this rule for the part of the predicate that is a property of the RECORD (e.g. `record.stage == 'closed_won'`) and name the audience through `sharedWith`."});return}t.push({severity:`error`,rule:sc,where:c,path:l,message:`Sharing-rule condition \`${u}\` is outside the pushdown subset the runtime can compile (${a.detail}), so \`bootstrapDeclaredSharingRules\` SKIPS the rule at boot: it is never written to \`sys_sharing_rule\`, no \`sys_record_share\` grant is ever materialised, and the only signal is one WARN line in the boot log. The rule is declared and grants nothing (ADR-0049: an unlowerable condition is never seeded as a permissive match-all).`,hint:`Rewrite the predicate inside the lowerable subset. `+hc+" Two traps in particular: (1) `has(record.x)` is correct in an object VALIDATION rule, which is INTERPRETED, and wrong here, where the condition is COMPILED — write the null test as `record.x != null`; (2) a related-record path (`record.account.region`) is a join, which the compiler refuses by design (ADR-0055) — denormalise the value onto this object (a formula/rollup field) and test that column, or share the related object instead."})}),t}var bc=`rls-predicate-unenforceable`,xc=`rls-predicate-unparseable`,Sc=`rls-predicate-over-budget`;function Cc(e){return Array.isArray(e)?e:e&&typeof e==`object`?Object.entries(e).map(([e,t])=>({name:e,...t})):[]}function wc(e){return typeof e==`string`?e:``}var Tc="The lowerable subset is: `==` `!=` `>` `<` `>=` `<=`, `in`, `&&` `||` `!`, `== null` / `!= null`, and the string methods `startsWith` / `endsWith` / `contains` — over SINGLE-column field paths (ADR-0058 D2), compared against a literal or a `current_user.*` value.";function Ec(e){let t=oe(e);return!t.ok&&t.kind===`bounds`?t.overrun:null}function Dc(e){return e.length>200?`${e.slice(0,197)}...`:e}function Oc(e){return e===`using`?'so `RLSCompiler` DROPS the policy at request time (one WARN line — "has an uncompilable predicate … and was DROPPED (no enforcement)" — is the only signal, and nothing reports it at authoring time). When it is the only applicable policy for that object and operation, `compileFilter` returns the `RLS_DENY_FILTER` sentinel instead, which is AND-ed onto the where clause: every select / update / delete on the object matches ZERO rows. When other policies also apply, this one just vanishes from the OR and grants none of the access it appears to.':'so `RLSCompiler` DROPS the policy at request time (one WARN line — "has an uncompilable predicate … and was DROPPED (no enforcement)" — is the only signal, and nothing reports it at authoring time). On the ADR-0058 D4 write path that leaves the post-image `check` as the `RLS_DENY_FILTER` sentinel, which no record can satisfy: every insert / update the policy governs fails with `PermissionDeniedError`. The policy reads as a write rule and behaves as a blanket refusal.'}function kc(t){let n=[];return Cc((t??{}).permissions).forEach((t,r)=>{Cc(t.rowLevelSecurity).forEach((i,a)=>{for(let o of[`using`,`check`]){let s=wc(i[o]);if(!s.trim()||_e(s))continue;let c=e(s),l=ye(c),u=l.ok?``:l.detail,d=!l.ok&&l.reason===`parse-error`,f=d?Ec(c):null,p=wc(t.name)||String(r),m=wc(i.name)||String(a),h=wc(i.object),g=`permission set "${p}" policy "${m}"`+(h?` on object "${h}"`:``),_=`permissions[${r}].rowLevelSecurity[${a}].${o}`;if(f){let e=f.limit??`an unnamed platform CEL bound`,t=f.limitValue===null?``:` (platform limit ${f.limitValue})`,r=f.measured===null?``:`, this predicate measures ${f.measured}`;n.push({severity:`error`,rule:Sc,where:g,path:_,message:`RLS ${o} \`${Dc(s)}\` is syntactically valid, lowerable CEL but overruns the platform parse bound ${e}${t}${r} (${f.summary}), `+Oc(o),hint:`There is no syntax or dialect error to correct here \u2014 the predicate is well-formed CEL and is simply too large for ${e}${t}, so the fix is to make it smaller or to move the work off the predicate. (1) Collapse a long \`field == a || field == b || \u2026\` chain into a single \`field in [a, b, \u2026]\`, which is far fewer AST nodes (\`maxListElements\` is 64, so a very large set needs option 2). (2) Pre-resolve the set into a membership key the runtime exposes and test \`field in current_user.<key>\` (ADR-0105 D11) \u2014 one comparison whatever the set size. (3) Denormalise a repeated sub-expression onto this object as a formula/rollup field and test that single column. (4) Split a TOP-LEVEL \`||\` across several \`rowLevelSecurity\` policies: applicable policies are OR-ed, so that is equivalent \u2014 but never split a top-level \`&&\` this way, which would WIDEN access rather than preserve it. Logic genuinely this large is not a row filter: move it to a hook or action body (\`ScriptBody { language: 'js' }\`, the L2 sandboxed surface).`});continue}if(d){n.push({severity:`error`,rule:xc,where:g,path:_,message:`RLS ${o} \`${s}\` does not parse as CEL even after the legacy SQL bridge (\`=\` \u2192 \`==\`, \`IN\` \u2192 \`in\`) has been applied (${u}), `+Oc(o),hint:"Author the predicate in canonical CEL (ADR-0058 D1). The bridge covers only the historic SQL subset — a bare `=` and `IN` — so everything else must already be CEL: combine with `&&` / `||` rather than SQL `AND` / `OR`, negate with `!`, and use `startsWith` / `endsWith` / `contains` rather than `LIKE`. A subquery has no CEL spelling at all: RLS cannot join (ADR-0055), so pre-resolve the set into a membership key the runtime exposes (`field in current_user.<key>`, ADR-0105 D11) or denormalise the value onto this object."});continue}n.push({severity:`error`,rule:bc,where:g,path:_,message:`RLS ${o} \`${s}\` is outside the pushdown subset the runtime can compile (${u}), `+Oc(o),hint:`Rewrite the predicate inside the lowerable subset. `+Tc+" Three traps in particular: (1) a function call — `size(record.tags) > 0`, `has(record.x)` — is correct in an object VALIDATION rule, which is INTERPRETED, and wrong here, where the predicate is COMPILED to a filter; write the null test as `field != null`. (2) A related-record path (`record.account.region`) is a join, which the compiler refuses by design (ADR-0055) — denormalise the value onto this object (a formula/rollup field) and test that column. (3) Arithmetic on a column (`amount * 2 > 100`) never lowers — precompute it into a field, or compare the column against the literal directly."})}})}),n}var Ac=`dashboard-action-target-undefined`,jc=`dashboard-action-route-unresolved`;function Mc(e){return Array.isArray(e)?e:e&&typeof e==`object`?Object.entries(e).map(([e,t])=>({name:e,...t})):[]}function L(e){return typeof e==`string`&&e.length>0?e:void 0}var Nc={object:`objects`,objects:`objects`,report:`reports`,reports:`reports`,dashboard:`dashboards`,dashboards:`dashboards`,page:`pages`,pages:`pages`,view:`views`,views:`views`};function Pc(e){return L(e.name)??L(e.id)??L(e.object)??L(e.list?.data&&e.list.data.object)??L(e.form?.data&&e.form.data.object)}function Fc(e){let t=new Set,n=new Set,r=new Set,i=new Set,a=new Set,o=new Set,s=(e,t,n)=>{for(let r of Mc(e)){if(!r||typeof r!=`object`)continue;let e=n(r);e&&t.add(e)}};s(e.actions,t,e=>L(e.name));for(let r of Mc(e.objects)){if(!r||typeof r!=`object`)continue;let e=L(r.name);e&&n.add(e),s(r.actions,t,e=>L(e.name))}s(e.reports,r,e=>L(e.name)),s(e.dashboards,i,e=>L(e.name)),s(e.pages,a,e=>L(e.name)),s(e.views,o,Pc);for(let e of n)o.add(e);return{actions:t,objects:n,reports:r,dashboards:i,pages:a,views:o}}function Ic(e,t,n){return e===`modal`?n.pages.has(t):n.actions.has(t)}function Lc(e,t){if(/^[a-z][a-z0-9+.-]*:\/\//i.test(e)||e.startsWith(`//`)||e.includes("${")||!e.startsWith(`/`))return null;let n=e.split(/[?#]/,1)[0].split(`/`).filter(Boolean);for(let e=0;e<n.length-1;e++){let r=Nc[n[e]];if(!r)continue;let i=n[e+1];return t[r].has(i)?void 0:{collection:n[e],name:i}}return null}function Rc(e){let t=[];if(!e||typeof e!=`object`)return t;let n=Mc(e.dashboards);if(n.length===0)return t;let r=Fc(e),i=(e,n,i)=>{let a=L(e.actionUrl);if(!a||a.includes("${"))return;let o=L(e.actionType)??`url`;if(o===`script`||o===`modal`){if(Ic(o,a,r))return;t.push({severity:`error`,rule:Ac,where:n,path:i,message:o===`modal`?`modal action target "${a}" names no declared page \u2014 a modal target names a PAGE, only (objectstack#6739). The button renders but the runtime refuses the dispatch when clicked \u2014 a dangling reference (ADR-0049: a declared reference must resolve).`:`script action target "${a}" resolves to no defined action. The button renders but does nothing when clicked \u2014 a dangling reference the runtime cannot dispatch (ADR-0049: a declared reference must resolve).`,hint:o===`modal`?`Point actionUrl at a declared page (stack.pages), or use actionType: 'form' with an "<object>.<view>" form-view target to open an object's form, or remove the button.`:`Define a script action named "${a}" (stack.actions or the object's actions) with an inline body or a registered handler, or remove the button.`});return}if(o===`url`){let e=Lc(a,r);if(!e)return;t.push({severity:`warning`,rule:jc,where:n,path:i,message:`url action target "${a}" points at ${e.collection}/${e.name}, but no ${e.collection.replace(/s$/,``)} named "${e.name}" is registered in this stack \u2014 the button likely navigates to a dead route.`,hint:`Check the path for a typo, define the referenced ${e.collection.replace(/s$/,``)}, or ignore this if the route is served by another installed package or a host/console route.`});return}};for(let e=0;e<n.length;e++){let t=n[e];if(!t||typeof t!=`object`)continue;let r=L(t.name)??`(dashboard ${e})`,a=`dashboards[${e}]`,o=Mc(t.header?.actions);for(let e=0;e<o.length;e++){let t=o[e];!t||typeof t!=`object`||i(t,`dashboard "${r}" \xB7 header action "${L(t.label)??L(t.actionUrl)??`#${e}`}"`,`${a}.header.actions[${e}].actionUrl`)}}return t}var zc=new Set([`filter`,`filters`,`runtimeFilter`,`relatedListFilter`]);function Bc(e){return Array.isArray(e)?e:e&&typeof e==`object`?Object.entries(e).map(([e,t])=>({name:e,...t})):[]}function Vc(e,t){return typeof e==`string`&&e.length>0?e:t}function Hc(e,t,n,r,i=new Set){if(!(!e||typeof e!=`object`)&&!i.has(e)){if(i.add(e),Array.isArray(e)){e.forEach((e,a)=>Hc(e,`${t}[${a}]`,n,r,i));return}for(let[a,o]of Object.entries(e)){let e=`${t}.${a}`;if(zc.has(a)){r({value:o,path:e,where:n});continue}Hc(o,e,n,r,i)}}}function Uc(e,t,n){if(!(!e||typeof e!=`object`))for(let{key:r,kind:i}of t)Bc(e[r]).forEach((e,t)=>{let a=Vc(e.name??e.id,`#${t}`);if(i===`dashboard`){(Array.isArray(e.widgets)?e.widgets:[]).forEach((e,i)=>{let o=Vc(e.id??e.title,`#${i}`);Hc(e,`${r}[${t}].widgets[${i}]`,`dashboard "${a}" \xB7 widget "${o}"`,n,new Set)});let{widgets:i,...o}=e;Hc(o,`${r}[${t}]`,`dashboard "${a}"`,n,new Set);return}Hc(e,`${r}[${t}]`,`${i} "${a}"`,n,new Set)})}var Wc=`filter-token-unknown`,Gc=Le.join(`}, {`),Kc=[{key:`dashboards`,kind:`dashboard`},{key:`objects`,kind:`object`},{key:`views`,kind:`view`},{key:`reports`,kind:`report`},{key:`datasets`,kind:`dataset`},{key:`pages`,kind:`page`},{key:`apps`,kind:`app`}];function qc(e,t,n,r,i){if(e!=null){if(typeof e==`string`){let i=et(e);if(i?.kind===`unknown`){let a=i.suggestion;r.push({severity:`error`,rule:Wc,where:n,path:t,message:`Filter value "${e}" is not a resolvable placeholder. It is sent to the data engine as a literal string, matches no record, and the surface renders empty.`,hint:a?`Did you mean "{${a}}"? Context tokens are {${Gc}}; time-based values use date macros such as {today} or {30_days_ago}.`:`Resolvable placeholders are the context tokens {${Gc}} and the date macros (e.g. {today}, {week_start}, {30_days_ago}). To filter on a literal value that happens to look like a placeholder, this is not supported \u2014 rename the value.`})}return}if(typeof e==`object`&&!i.has(e)){if(i.add(e),Array.isArray(e)){e.forEach((e,a)=>qc(e,`${t}[${a}]`,n,r,i));return}for(let[a,o]of Object.entries(e))qc(o,`${t}.${a}`,n,r,i)}}}function Jc(e){if(!e||typeof e!=`object`)return[];let t=[];return Uc(e,Kc,({value:e,path:n,where:r})=>{qc(e,n,r,t,new Set)}),t}var Yc=`filter-preset-comparand`,Xc=[{key:`dashboards`,kind:`dashboard`},{key:`objects`,kind:`object`},{key:`views`,kind:`view`},{key:`reports`,kind:`report`},{key:`datasets`,kind:`dataset`},{key:`pages`,kind:`page`},{key:`apps`,kind:`app`},{key:`flows`,kind:`flow`}],Zc=new Set([`$gt`,`$gte`,`$lt`,`$lte`]),Qc=new Set([`>`,`>=`,`<`,`<=`]),$c=new Set([`greater_than`,`greater_than_or_equal`,`less_than`,`less_than_or_equal`,`before`,`after`]),el=32;function tl(e){return!!e&&typeof e==`object`&&!Array.isArray(e)&&!(e instanceof Date)}function nl(e,t,n,r){return{severity:`error`,rule:Yc,where:e,path:t,message:we(n,r),hint:`Presets belong to the dashboard date-filter bar (dateRange.defaultRange, a date global filter's defaultValue). In a filter comparand, write the {date-macro} window the message names, or an ISO date.`}}function rl(e,t,r,i,a){if(!(a>el))for(let[o,s]of Object.entries(e)){let e=`${t}.${o}`;if(o===`$and`||o===`$or`){Array.isArray(s)&&s.forEach((t,n)=>{tl(t)&&rl(t,`${e}[${n}]`,r,i,a+1)});continue}if(o===`$not`){tl(s)&&rl(s,e,r,i,a+1);continue}if(!o.startsWith(`$`)&&tl(s)){if(!Object.keys(s).some(e=>e.startsWith(`$`))){rl(s,e,r,i,a+1);continue}for(let[t,a]of Object.entries(s)){if(Zc.has(t)&&n(a)){i.push(nl(r,`${e}.${t}`,a,t));continue}t===`$between`&&Array.isArray(a)&&a.forEach((a,o)=>{n(a)&&i.push(nl(r,`${e}.${t}[${o}]`,a,t))})}}}}function il(e,t,r,i){let a=ze(e.operator);if(typeof a!=`string`)return;let o=e.value;if($c.has(a)&&n(o)){i.push(nl(r,`${t}.value`,o,a));return}a===`between`&&Array.isArray(o)&&o.forEach((e,o)=>{n(e)&&i.push(nl(r,`${t}.value[${o}]`,e,a))})}function al(e,t,r,i){let a=e[1];if(typeof a!=`string`)return;let o=nt(a),s=e[2];if(Qc.has(o)&&n(s)){i.push(nl(r,`${t}[2]`,s,a));return}o===`between`&&Array.isArray(s)&&s.forEach((e,o)=>{n(e)&&i.push(nl(r,`${t}[2][${o}]`,e,a))})}function ol(e,t,n,r,i){if(!(i>el)){if(Array.isArray(e)){if(typeof e[0]==`string`&&typeof e[1]==`string`&&![`and`,`or`].includes(e[0].toLowerCase())&&Pe.has(e[1].toLowerCase())){al(e,t,n,r);return}e.forEach((e,a)=>{typeof e!=`string`&&ol(e,`${t}[${a}]`,n,r,i+1)});return}if(tl(e)){if(typeof e.field==`string`&&typeof e.operator==`string`){il(e,t,n,r);return}rl(e,t,n,r,i)}}}function sl(e){if(!e||typeof e!=`object`)return[];let t=[];return Uc(e,Xc,({value:e,path:n,where:r})=>{ol(e,n,r,t,0)}),t}var cl=`filter-empty-combinator`,ll=`filter-empty-node`,ul=[{key:`dashboards`,kind:`dashboard`},{key:`objects`,kind:`object`},{key:`views`,kind:`view`},{key:`reports`,kind:`report`},{key:`datasets`,kind:`dataset`},{key:`pages`,kind:`page`},{key:`apps`,kind:`app`},{key:`flows`,kind:`flow`}];function dl(e){if(typeof e!=`object`||!e||Array.isArray(e))return!1;let t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}var fl={$and:rt({$and:[]}),$or:rt({$or:[]}),$not:rt({$not:{}}),node:rt({}),orWithEmptyBranch:rt({$or:[{status:`open`},{}]})};function pl(e){return e===`true`?`matches EVERY row`:e===`false`?`matches NO row`:`carries a real predicate`}var ml="If you really do want a predicate that selects nothing, `{ <field>: { $in: [] } }` is the declared spelling for it (an empty `$in` list matches nothing, on every backend) — it says so where an empty combinator only implies it.",hl='To express "no filter", DELETE the key — an absent `filter` and a filter that reduces to TRUE run identically, and only the absent key says so to the next reader (and to the next AI author that copies this metadata).';function gl(e,t,n){let r=e===`$not`?"`$not: {}`":`\`${e}: []\``,i=e===`$and`?`\`$and: []\` is a conjunction of ZERO conditions. Under the #5322 identity ruling it ${pl(fl.$and)} \u2014 the key is authored, and it constrains nothing, so this surface reads as filtered and is not.`:e===`$or`?`\`$or: []\` is a disjunction of ZERO branches. Under the #5322 identity ruling it ${pl(fl.$or)}: this surface renders permanently empty, and on a read scope it hides every row (fail-closed by design \u2014 #5134).`:`\`$not: {}\` negates an EMPTY node. An empty node is TRUE and NOT TRUE is FALSE, so it ${pl(fl.$not)} \u2014 the opposite of the "no filter" an empty operand looks like.`,a=e===`$and`?`${hl} To express a constraint, put the conditions in the array. ${ml}`:e===`$or`?`If you meant "no filter", this is its OPPOSITE: emptying the array does not relax the filter, it closes it. ${hl} If you meant to offer alternatives, put the branches in the array. ${ml}`:`Put the condition you are negating inside \`$not\` (\`{ $not: { status: 'closed' } }\`). ${hl} ${ml}`;n.out.push({severity:`error`,rule:cl,where:n.where,path:t,message:`${i} A literal ${r} is not an authoring surface (#5330).`,hint:`${a} A PROGRAMMATIC producer that loops to zero operands keeps the runtime identity unchanged \u2014 this rule judges only what is written in the metadata.`})}function _l(e,t,n){if(e===`root`){n.out.push({severity:`error`,rule:ll,where:n.where,path:t,message:`An EMPTY filter node (\`{}\`) is authored here. Under the #5322 identity ruling an empty node is TRUE \u2014 it ${pl(fl.node)}, exactly as if the key were absent \u2014 so a filter is declared and enforces nothing.`,hint:`${hl} If you meant to constrain something, write the condition into the node. ${ml}`});return}if(e===`or-branch`){n.out.push({severity:`error`,rule:ll,where:n.where,path:t,message:`An EMPTY branch (\`{}\`) of a \`$or\`. An empty node is TRUE, and one TRUE disjunct ABSORBS the whole disjunction (\`{ $or: [{ status: 'open' }, {}] }\` ${pl(fl.orWithEmptyBranch)}), so every branch you wrote beside it is dead.`,hint:"Delete the empty branch — the `$or` then means what it looks like. If it was meant to carry a condition, write it. (A compiler that DROPPED the empty branch instead would silently NARROW the scope to the surviving branches, which is why the runtime absorbs rather than filters — #5297.)"});return}n.out.push({severity:`error`,rule:ll,where:n.where,path:t,message:"An EMPTY branch (`{}`) of a `$and`. An empty node is TRUE — the AND identity — so the branch contributes no condition and the conjunction means whatever its other branches mean.",hint:`Delete the empty branch, or write the condition it was meant to carry. A branch that constrains nothing is indistinguishable from one whose condition was lost in an edit.`})}function vl(e,t,n){for(let[r,i]of Object.entries(e)){if(r===`$and`||r===`$or`){if(!Array.isArray(i))continue;if(i.length===0){gl(r,`${t}.${r}`,n);continue}i.forEach((e,i)=>{yl(e,`${t}.${r}[${i}]`,r===`$and`?`and-branch`:`or-branch`,n)});continue}if(r===`$not`){if(!dl(i))continue;if(Object.keys(i).length===0){gl(`$not`,`${t}.$not`,n);continue}vl(i,`${t}.$not`,n);continue}}}function yl(e,t,n,r){if(dl(e)){if(Object.keys(e).length===0){_l(n,t,r);return}vl(e,t,r)}}function bl(e){if(!e||typeof e!=`object`)return[];let t=[];return Uc(e,ul,({value:e,path:n,where:r})=>{yl(e,n,`root`,{where:r,out:t})}),t}var xl=[...Ye],Sl=`object-reference-unknown`,Cl=`object-reference-unregistered-platform`;function wl(e){return Array.isArray(e)?e:e&&typeof e==`object`?Object.entries(e).map(([e,t])=>({name:e,...t})):[]}function R(e){return typeof e==`string`&&e.length>0?e:void 0}function Tl(e){if(e.includes("${"))return!0;let t=e.indexOf(`{`);return t!==-1&&e.indexOf(`}`,t+2)!==-1}function El(e,t){let n,r=1/0;for(let i of t){let t=Dl(e,i);t<r&&(r=t,n=i)}let i=Math.max(2,Math.floor(e.length/3));return n&&r<=i?` Did you mean "${n}"?`:``}function Dl(e,t){let n=e.length,r=t.length;if(n===0)return r;if(r===0)return n;let i=Array.from({length:r+1},(e,t)=>t);for(let a=1;a<=n;a++){let n=[a,...Array(r).fill(0)];for(let o=1;o<=r;o++){let r=e[a-1]===t[o-1]?0:1;n[o]=Math.min(n[o-1]+1,i[o]+1,i[o-1]+r)}i=n}return i[r]}function Ol(e){let t=[];if(!e||typeof e!=`object`)return t;let n=wl(e.objects),r=new Set;for(let e of n){let t=R(e.name);t&&r.add(t)}let i=(e,n,i,a,o)=>{let s=R(e);if(s&&!Tl(s)&&!r.has(s)&&!Ae(s)){if(Oe(s)){t.push({severity:`warning`,rule:Cl,where:n,path:i,message:`${a} "${s}" carries a platform namespace prefix, but no platform package, official plugin, or cloud runtime object registers that name \u2014 and this stack does not define it either. If nothing provides it at runtime the reference resolves to nothing and fails silently.`+El(s,xl),hint:`Check the spelling against the object the providing package actually registers (e.g. "sys_approval_request", not "sys_approval_process" \u2014 the process object was removed when approval became a flow node, ADR-0019). If a third-party package genuinely provides it, this warning is expected. ${o}`});return}t.push({severity:`error`,rule:Sl,where:n,path:i,message:`${a} "${s}" resolves to no object defined in this stack. The reference is inert at runtime \u2014 nothing reports the miss.`+El(s,r),hint:`Point it at one of this stack's objects, or at a platform object by its full name (the platform user object is "sys_user", not "user"). ${o}`+(r.size>0?` Defined objects: ${[...r].sort().join(`, `)}.`:``)})}},a=(e,t,n)=>{let r=wl(e.params);for(let e=0;e<r.length;e++){let a=r[e];if(!a||typeof a!=`object`)continue;let o=`${n} \xB7 param "${R(a.name)??R(a.field)??`#${e}`}"`;i(R(a.reference),o,`${t}.params[${e}].reference`,`record-picker target`,`Without a resolvable target the picker degrades to a raw record-id text input.`),i(R(a.objectOverride),o,`${t}.params[${e}].objectOverride`,`field-backed param object`,`The param inherits type/options from a field on this object, so an unknown object leaves it untyped.`)}},o=wl(e.actions);for(let e=0;e<o.length;e++){let t=o[e];!t||typeof t!=`object`||a(t,`actions[${e}]`,`action "${R(t.name)??`#${e}`}"`)}for(let e=0;e<n.length;e++){let t=n[e];if(!t||typeof t!=`object`)continue;let r=R(t.name)??`#${e}`,i=wl(t.actions);for(let t=0;t<i.length;t++){let n=i[t];!n||typeof n!=`object`||a(n,`objects[${e}].actions[${t}]`,`object "${r}" \xB7 action "${R(n.name)??`#${t}`}"`)}}let s=wl(e.dashboards);for(let e=0;e<s.length;e++){let t=s[e];if(!t||typeof t!=`object`)continue;let n=R(t.name)??`#${e}`,r=wl(t.globalFilters);for(let t=0;t<r.length;t++){let a=r[t];if(!a||typeof a!=`object`)continue;let o=a.optionsFrom;!o||typeof o!=`object`||i(R(o.object),`dashboard "${n}" \xB7 filter "${R(a.name)??`#${t}`}"`,`dashboards[${e}].globalFilters[${t}].optionsFrom.object`,`filter options source`,`The dropdown fetches its options from this object; an unknown one renders an always-empty filter.`)}}let c=wl(e.apps);for(let e=0;e<c.length;e++){let t=c[e];if(!t||typeof t!=`object`)continue;let n=R(t.name)??`#${e}`,r=(e,t)=>{let a=wl(e);for(let e=0;e<a.length;e++){let o=a[e];if(!o||typeof o!=`object`)continue;let s=R(o.id)??`#${e}`,c=`app "${n}" \xB7 nav "${s}"`,l=`${t}[${e}]`;i(R(o.requiresObject),c,`${l}.requiresObject`,`capability gate object`,`The entry is hidden unless this object is registered, so a typo hides it permanently — and it suppresses the nav cross-reference check that would have caught the target.`),o.requiresObject&&R(o.objectName)&&i(R(o.objectName),c,`${l}.objectName`,`navigation target`,"Declaring `requiresObject` exempts this target from the build-time check, so it is only verified here."),Array.isArray(o.children)&&r(o.children,`${l}.children`)}};r(t.navigation,`apps[${e}].navigation`);let a=wl(t.areas);for(let t=0;t<a.length;t++)r(a[t]?.navigation,`apps[${e}].areas[${t}].navigation`)}return t}var kl=`nav-target-unresolved`,Al=e=>!!e&&typeof e==`object`&&!Array.isArray(e);function jl(e){return Array.isArray(e)?e.filter(Al):Al(e)?Object.entries(e).map(([e,t])=>Al(t)?{name:e,...t}:{name:e}):[]}function Ml(e){return typeof e==`string`&&e.length>0?e:void 0}var Nl=e=>e.includes("${")||e.includes(`{`),Pl=[[`page`,`pageName`,`pages`,`page`],[`report`,`reportName`,`reports`,`report`],[`dashboard`,`dashboardName`,`dashboards`,`dashboard`]];function Fl(e){let t=new Set;for(let n of jl(e)){let e=Ml(n.name);e&&t.add(e)}return t}function Il(e){let t=[];if(!Al(e))return t;let n=jl(e.apps);if(n.length===0)return t;let r=new Map;for(let[,,t]of Pl)r.set(t,Fl(e[t]));for(let[e,i]of n.entries()){let n=Ml(i.name)??`#${e}`,a=(e,i)=>{if(Array.isArray(e))for(let[o,s]of e.entries()){if(!Al(s))continue;let e=s,c=`${i}[${o}]`;for(let[i,a,s,l]of Pl){if(e.type!==i)continue;let u=Ml(e[a]);if(!u||Nl(u))continue;let d=r.get(s);if(d.has(u))continue;let f=d.size===0;t.push({severity:`warning`,rule:kl,where:`app "${n}" \xB7 nav "${Ml(e.id)??Ml(e.label)??`#${o}`}"`,path:`${c}.${a}`,message:`Navigation targets ${l} '${u}', which this stack does not declare in \`${s}\`. `+(f?`The stack declares NO ${s} at all, so \`defineStack\`'s own cross-reference check skipped this entry entirely (it is gated on \`${s===`pages`?`pageNames`:s===`reports`?`reportNames`:`dashboardNames`}.size > 0\`) \u2014 nothing else will report it. `:``)+`The entry renders in the sidebar and resolves to nothing when clicked. If another package provides this ${l}, this is expected and advisory only.`,hint:`Declare the ${l} in \`${s}\`, correct the name, or remove the nav entry if the ${l} is gone.`})}Array.isArray(e.children)&&a(e.children,`${c}.children`)}};a(i.navigation,`apps[${e}].navigation`);for(let[t,n]of jl(i.areas).entries())a(n.items,`apps[${e}].areas[${t}].items`),a(n.navigation,`apps[${e}].areas[${t}].navigation`)}return t}var Ll=`nav-object-unservable`,Rl=e=>!!e&&typeof e==`object`&&!Array.isArray(e);function zl(e){return Array.isArray(e)?e.filter(Rl):Rl(e)?Object.entries(e).map(([e,t])=>Rl(t)?{name:e,...t}:{name:e}):[]}function Bl(e){return typeof e==`string`&&e.length>0?e:void 0}var Vl=e=>e.includes("${")||e.includes(`{`);function Hl(e){let t=[];if(!Rl(e))return t;let n=zl(e.apps);if(n.length===0)return t;let r=new Map,i=zl(e.objects);for(let[e,t]of i.entries()){let n=Bl(t.name);n&&r.set(n,{enable:t.enable,path:`objects[${e}].enable`})}if(r.size===0)return t;for(let[e,i]of n.entries()){let n=Bl(i.name)??`#${e}`,a=(e,i)=>{if(Array.isArray(e))for(let[o,s]of e.entries()){if(!Rl(s))continue;let e=s,c=`${i}[${o}]`;if(e.type===`object`){let i=Bl(e.objectName),a=i&&!Vl(i)?r.get(i):void 0;if(i&&a&&!Ze(a.enable,`list`)){let r=Rl(a.enable)?a.enable:{},s=r.apiEnabled===!1,l=s?"`enable.apiEnabled: false`":"`enable.apiMethods` does not grant `list`"+(Array.isArray(r.apiMethods)?` (declared: ${r.apiMethods.length===0?`[] — deny-all`:r.apiMethods.map(e=>`\`${String(e)}\``).join(`, `)})`:``),u=s?"404 `OBJECT_API_DISABLED`":"405 `OBJECT_API_METHOD_NOT_ALLOWED`",d=s?`${a.path}.apiEnabled`:`${a.path}.apiMethods`;t.push({severity:`error`,rule:Ll,where:`app "${n}" \xB7 nav "${Bl(e.id)??Bl(e.label)??`#${o}`}"`,path:`${c}.objectName`,message:`Navigation targets object "${i}", which cannot serve a list: ${l} (\`${d}\`), so the list request answers ${u} for EVERY user \u2014 platform administrators included, since that gate reads only the object's \`enable\` block and never the caller. The entry cannot be rescued with \`requiredPermissions\`: they are independent conditions. The server prunes this entry from the served \`/meta\` payload (#7912), so publishing it ships a menu row that silently is not there.`,hint:`Remove the nav entry, or make "${i}" listable by setting \`enable.apiEnabled: true\` and granting \`list\` in \`enable.apiMethods\`. \u26D4 Do NOT open the API on an object that is disabled on purpose \u2014 several platform objects hold credential material and are API-disabled deliberately; for those the entry is the mistake, not the \`enable\` block.`})}}Array.isArray(e.children)&&a(e.children,`${c}.children`)}};a(i.navigation,`apps[${e}].navigation`);for(let[t,n]of zl(i.areas).entries())a(n.items,`apps[${e}].areas[${t}].items`),a(n.navigation,`apps[${e}].areas[${t}].navigation`)}return t}var Ul=`sort-field-unknown`,Wl=`sort-field-unsortable`,Gl=`sort-field-unprovisioned`;function z(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function Kl(e){return typeof e==`string`&&e.length>0?e:void 0}function ql(e){let t=(e,t)=>{let n=e.trim();if(!n)return;let r=n.startsWith(`-`)?n.slice(1).trim():n.split(/\s+/)[0];return r?{field:r,at:t}:void 0};if(typeof e==`string`)return e.split(`,`).map((n,r)=>t(n,e.includes(`,`)?`[${r}]`:``)).filter(e=>!!e);if(Array.isArray(e)){let n=[];for(let r=0;r<e.length;r++){let i=e[r];if(typeof i==`string`){let e=t(i,`[${r}]`);e&&n.push(e);continue}if(!z(i))continue;let a=Kl(i.field);a&&n.push({field:a.trim(),at:`[${r}]`})}return n}return[]}function Jl(e,t){let n,r=1/0;for(let i of t){let t=Yl(e,i);t<r&&(r=t,n=i)}let i=Math.max(2,Math.floor(e.length/3));return n&&r<=i?` Did you mean "${n}"?`:``}function Yl(e,t){let n=e.length,r=t.length;if(n===0)return r;if(r===0)return n;let i=Array.from({length:r+1},(e,t)=>t);for(let a=1;a<=n;a++){let n=[a,...Array(r).fill(0)];for(let o=1;o<=r;o++){let r=e[a-1]===t[o-1]?0:1;n[o]=Math.min(n[o-1]+1,i[o]+1,i[o-1]+r)}i=n}return i[r]}function Xl(e,t,n,r,i,a,o){let s=[];if(e==null||!t||!n.has(t))return s;let c=n.get(t);if(!c)return s;let l=c.names,u=o?.get(t);for(let n of ql(e)){let e=n.field,o=e.split(`.`)[0];if(it.has(o)){!e.includes(`.`)&&u?.has(o)&&s.push({severity:`warning`,rule:Gl,where:r,path:`${i}${n.at}`,message:`${a} orders by "${e}", which resolves on object "${t}", but ${C(t,e)} \u2014 so the ORDER BY reaches the driver, finds no column, and is dropped. Measured on a federated object over a real remote table, 'asc' and 'desc' return BYTE-IDENTICAL row order under a 200 while the same query on a real column reverses. Unlike this rule's other two verdicts nothing refuses it: the REST ingress (#6994) and the engine (#7095) both judge only 'formula', so the view's FIRST fetch \u2014 and every fetch after it \u2014 silently answers in an arbitrary order, which 'limit'/'offset' then slice into an arbitrary page.`,hint:w(t,e)});continue}if(!l.has(o)){let c=e.includes(`.`);s.push({severity:`error`,rule:Ul,where:r,path:`${i}${n.at}`,message:`${a} orders by "${e}", which is not a field on object "${t}". The runtime refuses the sort rather than dropping it: every load of this view answers 400 INVALID_SORT (#6994), because a sort is the view's FIRST fetch and not an optional interaction.`+(c?``:Jl(o,l)),hint:(c?`'sort' reaches only whole columns of "${t}" itself, never a related record's column \u2014 denormalise the value onto "${t}" (a stored field, written when the source changes) and sort by that. `:`Fix the name, or add "${e}" to ${t}.fields. `)+(l.size>0?`Object fields: ${[...l].sort().join(`, `)}.`:``)});continue}let d=c.fields[e];if(g(d)){let o=d?.type;s.push({severity:`error`,rule:Wl,where:r,path:`${i}${n.at}`,message:`${a} orders by "${e}" on object "${t}", a virtual '${o}' field: its value is computed on read and never stored, so no driver materialises a column to ORDER BY. Measured, an unrefused sort on one returns 'asc' and 'desc' in byte-identical order \u2014 the rows carry the values they were asked to be ordered by, unordered, under a success.`,hint:`Denormalise the value onto "${t}" (a stored field, written when the source changes) and sort by that, or drop "${e}" from this sort. At runtime both doors now refuse it with 400 INVALID_SORT \u2014 the REST ingress (#6994) and the engine itself (#7095) \u2014 so the declaration breaks the view's first fetch, and every fetch after it.`})}}return s}function Zl(e){let t=[];if(!z(e))return t;let n=Array.isArray(e.objects)?e.objects:z(e.objects)?Object.entries(e.objects).map(([e,t])=>({name:e,...t})):[],r=Si(e),i=ct(e),a=(e,n,a,o,s)=>{t.push(...Xl(e,n,r,a,o,s,i))};for(let e=0;e<n.length;e++){let t=n[e];if(!z(t))continue;let r=Kl(t.name),i=r?`object "${r}"`:`objects[${e}]`;if(z(t.listViews))for(let[n,o]of Object.entries(t.listViews))z(o)&&a(o.sort,Ql(o)??r,`${i} \u203A listViews.${n}`,`objects[${e}].listViews.${n}.sort`,`list-view sort`)}let o=Array.isArray(e.views)?e.views:[];for(let e=0;e<o.length;e++){let t=o[e];if(!z(t))continue;let n=Kl(t.name)??Kl(t.objectName)??`#${e}`,r=Kl(t.objectName)??Kl(t.object);if(t.viewKind===`list`&&!z(t.config)&&a(t.sort,Ql(t)??r,`view "${n}" (flattened list overlay)`,`views[${e}].sort`,`list-view sort`),t.viewKind===`list`&&z(t.config)&&a(t.config.sort,Ql(t.config)??r,`view "${n}" (ViewItem record)`,`views[${e}].config.sort`,`list-view sort`),z(t.list)&&a(t.list.sort,Ql(t.list)??r,`view "${n}" \u203A list`,`views[${e}].list.sort`,`list-view sort`),z(t.listViews))for(let[i,o]of Object.entries(t.listViews))z(o)&&a(o.sort,Ql(o)??r,`view "${n}" \u203A listViews.${i}`,`views[${e}].listViews.${i}.sort`,`list-view sort`)}return t}function Ql(e){let t=e.data;return z(t)?Kl(t.object):void 0}var $l=`action-name-undefined`;function eu(e){return Array.isArray(e)?e:e&&typeof e==`object`?Object.entries(e).map(([e,t])=>({name:e,...t})):[]}function B(e){return typeof e==`string`&&e.length>0?e:void 0}function tu(e){return Array.isArray(e)?e.filter(e=>typeof e==`string`&&e.length>0):[]}function nu(e,t){let n=e.length,r=t.length;if(n===0)return r;if(r===0)return n;let i=Array.from({length:r+1},(e,t)=>t);for(let a=1;a<=n;a++){let n=[a,...Array(r).fill(0)];for(let o=1;o<=r;o++){let r=e[a-1]===t[o-1]?0:1;n[o]=Math.min(n[o-1]+1,i[o]+1,i[o-1]+r)}i=n}return i[r]}function ru(e,t){let n,r=1/0;for(let i of t){let t=nu(e,i);t<r&&(r=t,n=i)}let i=Math.max(2,Math.floor(e.length/3));return n&&r<=i?` Did you mean "${n}"?`:``}function iu(e){let t=new Set;for(let n of eu(e.actions)){let e=B(n?.name);e&&t.add(e)}for(let n of eu(e.objects))if(!(!n||typeof n!=`object`))for(let e of eu(n.actions)){let n=B(e?.name);n&&t.add(n)}return t}function au(e){let t=[];if(!e||typeof e!=`object`)return t;let n=iu(e),r=(e,r,i,a,o=`with the location this surface needs`)=>{n.has(e)||t.push({severity:`error`,rule:$l,where:r,path:i,message:`${a} names action "${e}", which is defined by no action in this stack (neither \`stack.actions\` nor any object's \`actions\`). The button renders and does nothing when clicked \u2014 a dead affordance the runtime cannot dispatch.`+ru(e,n),hint:`Define an action named "${e}" (in \`stack.actions\` or the object's \`actions\`) ${o}, remove the reference, or ignore this if the action is contributed by another installed package.`+(n.size>0?` Defined actions: ${[...n].sort().join(`, `)}.`:``)})},i="(no `locations` entry needed — the selection bar places it by name)",a=(e,t,n,a)=>{if(!e||typeof e!=`object`)return;let o=e;for(let e of[`rowActions`,`bulkActions`]){let s=tu(o[e]);for(let o=0;o<s.length;o++)r(s[o],`${t} \xB7 ${n} \xB7 ${e}`,`${a}.${e}[${o}]`,e===`bulkActions`?`Bulk-action menu`:`Row-action menu`,e===`bulkActions`?i:void 0)}let s=Array.isArray(o.bulkActionDefs)?o.bulkActionDefs:[];for(let e=0;e<s.length;e++){let o=s[e];if(!o||typeof o!=`object`||o.execution!==`aggregate`||o.actionDef!==void 0)continue;let c=B(o.name);c&&r(c,`${t} \xB7 ${n} \xB7 bulkActionDefs[${e}]`,`${a}.bulkActionDefs[${e}].name`,`Aggregate bulk action`,i)}},o=eu(e.views);for(let e=0;e<o.length;e++){let t=o[e];if(!t||typeof t!=`object`)continue;let n=`view "${B(t.name)??B(t.object)??`#${e}`}"`;a(t.list,n,`list`,`views[${e}].list`);let r=t.listViews;if(r&&typeof r==`object`&&!Array.isArray(r))for(let[t,i]of Object.entries(r))a(i,n,`listViews.${t}`,`views[${e}].listViews.${t}`)}let s=eu(e.objects);for(let e=0;e<s.length;e++){let t=s[e];if(!t||typeof t!=`object`)continue;let n=t.listViews;if(!n||typeof n!=`object`||Array.isArray(n))continue;let r=`object "${B(t.name)??`#${e}`}"`;for(let[t,i]of Object.entries(n))a(i,r,`listViews.${t}`,`objects[${e}].listViews.${t}`)}let c=eu(e.pages);for(let e=0;e<c.length;e++){let t=c[e];if(!t||typeof t!=`object`)continue;let n=B(t.name)??`#${e}`;for(let{component:i,path:a}of Ai(t,`pages[${e}]`)){let e=i.properties;if(!e||typeof e!=`object`)continue;let t=tu(e.actionNames);for(let e=0;e<t.length;e++)r(t[e],`page "${n}" \xB7 component "${B(i.type)??`?`}"`,`${a}.properties.actionNames[${e}]`,`Quick-actions bar`)}}let l=eu(e.apps);for(let e=0;e<l.length;e++){let t=l[e];if(!t||typeof t!=`object`)continue;let n=B(t.name)??`#${e}`,i=(e,t)=>{let a=eu(e);for(let e=0;e<a.length;e++){let o=a[e];if(!o||typeof o!=`object`)continue;let s=`${t}[${e}]`,c=o.actionDef,l=B(c?.actionName);o.type===`action`&&l&&r(l,`app "${n}" \xB7 nav "${B(o.id)??`#${e}`}"`,`${s}.actionDef.actionName`,`Navigation action item`);let u=B(o.runAction);o.type===`object`&&u&&r(u,`app "${n}" \xB7 nav "${B(o.id)??`#${e}`}"`,`${s}.runAction`,`Navigation deep-link auto-run`),Array.isArray(o.children)&&i(o.children,`${s}.children`)}};i(t.navigation,`apps[${e}].navigation`);let a=eu(t.areas);for(let t=0;t<a.length;t++)i(a[t]?.navigation,`apps[${e}].areas[${t}].navigation`)}return t}var ou=`action-no-placement`;function su(e){return Array.isArray(e)?e:e&&typeof e==`object`?Object.entries(e).map(([e,t])=>({name:e,...t})):[]}function cu(e){return typeof e==`string`&&e.length>0?e:void 0}function lu(e){return Array.isArray(e)?e.filter(e=>typeof e==`string`&&e.length>0):[]}function uu(e){let t=new Set,n=e=>{if(!e||typeof e!=`object`)return;let n=e;for(let e of[`rowActions`,`bulkActions`])for(let r of lu(n[e]))t.add(r);for(let e of su(n.bulkActionDefs)){let n=cu(e?.name);n&&t.add(n)}},r=e=>{if(!(!e||typeof e!=`object`||Array.isArray(e)))for(let t of Object.values(e))n(t)};for(let t of su(e.views))!t||typeof t!=`object`||(n(t.list),r(t.listViews));for(let t of su(e.objects))!t||typeof t!=`object`||r(t.listViews);return t}function du(e){let t=[];if(!e||typeof e!=`object`)return t;let n=uu(e),r=(e,r)=>{if(!e||typeof e!=`object`||`locations`in e)return;let i=cu(e.name);i&&(n.has(i)||t.push({severity:`warning`,rule:ou,where:`action "${i}"`,path:r,message:`Action "${i}" declares no \`locations\` and no view places it by name, so it renders on no surface \u2014 the button exists in metadata and nowhere in the UI.`,hint:"Add the surface it belongs on, e.g. `locations: ['record_header']` (or `list_item`, `list_toolbar`, `record_more`, `record_section`, `record_related`); or place it from a list view's `bulkActions` / `bulkActionDefs` if it acts on a selection. If it is meant to be callable over REST / MCP / AI with no UI surface, say so explicitly with `locations: []` — an empty array is the documented headless shape and is never flagged."}))},i=su(e.actions);for(let e=0;e<i.length;e++)r(i[e],`actions[${e}]`);let a=su(e.objects);for(let e=0;e<a.length;e++){let t=a[e];if(!t||typeof t!=`object`)continue;let n=su(t.actions);for(let t=0;t<n.length;t++)r(n[t],`objects[${e}].actions[${t}]`)}return t}var fu=`component-props-unknown-key`,pu=`component-props-invalid`;function mu(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function hu(e){return typeof e==`string`&&e.length>0?e:void 0}function gu(e){return Array.isArray(e)?e:e&&typeof e==`object`?Object.entries(e).map(([e,t])=>({name:e,...t})):[]}var _u=se,vu=`object`;function yu(e,t){return e.path.length!==1||e.path[0]!==vu?!1:hu((mu(t.dataSource)?t.dataSource:void 0)?.object)!==void 0}function bu(e){if(e.code!==`invalid_union`)return;let t=e.errors;if(!t||t.length===0)return;let n;for(let e of t){let t=e.filter(e=>e.code===`unrecognized_keys`);if(t.length!==0){if(t.length!==e.length||n)return;n=t[0]}}return n}function xu(e){let t=[];if(!mu(e))return t;let n=gu(e.pages);for(let e=0;e<n.length;e++){let r=n[e];if(!mu(r))continue;let i=hu(r.name)??`#${e}`;for(let{component:n,path:a}of Ai(r,`pages[${e}]`)){let e=hu(n.type);if(!e)continue;let r=_u[e];if(!r)continue;let o=mu(n.properties)?n.properties:void 0;if(!o)continue;let s=`page "${i}" \xB7 ${e}`,c=`${a}.properties`;for(let n of qe(r,o,e,c))t.push({severity:`warning`,rule:fu,where:s,path:n.path,message:`\`${n.key}\` is not a prop \`${e}\` declares (ComponentPropsMap, @objectstack/spec/ui), so nothing verifies it: \`properties\` is an untyped bag, the renderer spreads whatever it carries, and a key it does not read is ignored in silence.`+(n.suggestion?` Did you mean \`${n.suggestion}\`?`:``),hint:n.guidance??(n.suggestion?`Rename \`${n.key}\` \u2192 \`${n.suggestion}\`.`:`Remove \`${n.key}\`, or \u2014 if the component really does honour it \u2014 declare it on \`${e}\`'s props schema so the declaration and the renderer agree.`)});let l=r.safeParse(o);if(!l.success)for(let r of l.error?.issues??[]){if(yu(r,n))continue;let i=r.path.length?`${c}.${r.path.join(`.`)}`:c,a=bu(r);if(a){for(let n of a.keys??[])t.push({severity:`warning`,rule:fu,where:s,path:`${i}.${n}`,message:`\`${n}\` is not a prop \`${e}\` declares (ComponentPropsMap, @objectstack/spec/ui): ${a.message}`,hint:`Remove \`${n}\`, or declare it on \`${e}\`'s props schema if the component honours it.`});continue}if(r.code===`unrecognized_keys`){for(let n of r.keys??[])t.push({severity:`warning`,rule:fu,where:s,path:`${i}.${n}`,message:`\`${n}\` is not a prop \`${e}\` declares (ComponentPropsMap, @objectstack/spec/ui): ${r.message}`,hint:`Remove \`${n}\`, or declare it on \`${e}\`'s props schema if the component honours it.`});continue}t.push({severity:`warning`,rule:pu,where:s,path:i,message:`${i.slice(c.length+1)||`properties`}: ${Ki(r,o)}`,hint:`\`${e}\`'s props are declared by ComponentPropsMap (@objectstack/spec/ui) \u2014 the rejection above carries the fix. Advisory for now: the props bag is not parsed on the storage path either, so nothing rejects this today (objectstack#5068).`})}}}return t}var Su=`chart-dimension-unknown`,Cu=`chart-measure-unknown`,wu=`chart-dataset-unknown`,Tu=`chart-axis-not-selected`;function V(e){return Array.isArray(e)?e:e&&typeof e==`object`?Object.entries(e).map(([e,t])=>({name:e,...t})):[]}function H(e){return typeof e==`string`&&e.length>0?e:void 0}function Eu(e){return Array.isArray(e)?e.filter(e=>typeof e==`string`&&e.length>0):[]}function U(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function Du(e,t){let n=e.length,r=t.length;if(n===0)return r;if(r===0)return n;let i=Array.from({length:r+1},(e,t)=>t);for(let a=1;a<=n;a++){let n=[a,...Array(r).fill(0)];for(let o=1;o<=r;o++){let r=e[a-1]===t[o-1]?0:1;n[o]=Math.min(n[o-1]+1,i[o]+1,i[o-1]+r)}i=n}return i[r]}function Ou(e,t){let n,r=1/0;for(let i of t){let t=Du(e,i);t<r&&(r=t,n=i)}let i=Math.max(2,Math.floor(e.length/3));return n&&r<=i?` Did you mean "${n}"?`:``}function ku(e){let t=[...e].sort();return t.length?t.join(`, `):`(none)`}function Au(e){let t=new Map;for(let n of V(e.datasets)){let e=H(n.name);if(!e)continue;let r=new Set;for(let e of V(n.dimensions)){let t=H(e.name);t&&r.add(t)}let i=new Set;for(let e of V(n.measures)){let t=H(e.name);t&&i.add(t)}t.set(e,{dimensions:r,measures:i})}return t}function ju(e){let t=[];if(!e||typeof e!=`object`)return t;let n=Au(e);if(n.size===0&&!e.reports&&!e.views&&!e.pages)return t;let r=e=>{let r=e.dataset;if(!r)return;let i=n.get(r);if(!i){t.push({severity:`error`,rule:wu,where:e.where,path:`${e.path}.dataset`,message:`binds dataset "${r}", which resolves to no declared dataset \u2014 the chart has no data to render.`,hint:`Declared datasets: ${ku(n.keys())}.${Ou(r,n.keys())} Define it with defineDataset() or fix the reference (ADR-0021).`});return}let a=(n,a)=>{i.dimensions.has(n)||t.push({severity:`error`,rule:Su,where:e.where,path:a,message:`"${n}" is not a dimension declared by dataset "${r}". Post-ADR-0021 result rows are keyed by DIMENSION NAME, not the base field, so this axis renders with no categories.`,hint:`Dataset dimensions: ${ku(i.dimensions)}.${Ou(n,i.dimensions)} Declare the dimension on the dataset, or bind an existing one.`})},o=(n,a,o)=>{if(!i.measures.has(n)){t.push({severity:`error`,rule:Cu,where:e.where,path:a,message:`"${n}" is not a measure declared by dataset "${r}". Post-ADR-0021 result rows are keyed by MEASURE NAME (e.g. "sum_amount"), not the base field (e.g. "amount"), so this series comes back empty.`,hint:`Dataset measures: ${ku(i.measures)}.${Ou(n,i.measures)} Declare the measure on the dataset, or bind an existing one.`});return}o&&o.size>0&&!o.has(n)&&t.push({severity:`warning`,rule:Tu,where:e.where,path:a,message:`"${n}" is a declared measure of "${r}" but is not in this chart's selected values (${ku(o)}) \u2014 the query does not return it, so the series plots nothing.`,hint:`Add "${n}" to \`values\`, or point the axis at a selected measure.`})},s=e.dimensions;if(s)for(let e=0;e<s.names.length;e++)a(s.names[e],`${s.path}[${e}]`);let c=e.values,l=new Set(c?.names??[]);if(c)for(let e=0;e<c.names.length;e++)o(c.names[e],`${c.path}[${e}]`);e.xAxis&&a(e.xAxis.name,e.xAxis.path),e.yAxis&&o(e.yAxis.name,e.yAxis.path,l);for(let t of e.series??[])o(t.name,t.path,l)},i=V(e.reports);for(let e=0;e<i.length;e++){let t=i[e];if(!U(t))continue;let n=H(t.name)??`#${e}`,a=(e,t,n,i,a)=>{U(e)&&r({dataset:t,values:{names:n,path:`${a}.values`},xAxis:H(e.xAxis)?{name:H(e.xAxis),path:`${a}.chart.xAxis`}:void 0,yAxis:H(e.yAxis)?{name:H(e.yAxis),path:`${a}.chart.yAxis`}:void 0,series:V(e.series).map((e,t)=>({name:H(e.name),path:`${a}.chart.series[${t}].name`})).filter(e=>!!e.name),where:i,path:`${a}.chart`})};a(t.chart,H(t.dataset),Eu(t.values),`report "${n}" \xB7 chart`,`reports[${e}]`);let o=Array.isArray(t.blocks)?t.blocks:[];for(let t=0;t<o.length;t++){let r=o[t];U(r)&&a(r.chart,H(r.dataset),Eu(r.values),`report "${n}" \xB7 block "${H(r.name)??`#${t}`}" chart`,`reports[${e}].blocks[${t}]`)}}let a=(e,t,n)=>{if(!U(e))return;let i=e.chart;U(i)&&r({dataset:H(i.dataset),dimensions:{names:Eu(i.dimensions),path:`${n}.chart.dimensions`},values:{names:Eu(i.values),path:`${n}.chart.values`},where:t,path:`${n}.chart`})},o=V(e.views);for(let e=0;e<o.length;e++){let t=o[e];if(!U(t))continue;let n=H(t.name)??H(t.objectName)??`#${e}`;if(a(t.list,`view "${n}" \xB7 list chart`,`views[${e}].list`),U(t.listViews))for(let[r,i]of Object.entries(t.listViews))a(i,`view "${n}" \xB7 listViews.${r} chart`,`views[${e}].listViews.${r}`)}let s=V(e.objects);for(let e=0;e<s.length;e++){let t=s[e];if(!U(t)||!U(t.listViews))continue;let n=H(t.name)??`#${e}`;for(let[r,i]of Object.entries(t.listViews))a(i,`object "${n}" \xB7 listViews.${r} chart`,`objects[${e}].listViews.${r}`)}let c=V(e.pages);for(let e=0;e<c.length;e++){let t=c[e];if(!U(t))continue;let n=H(t.name)??`#${e}`;for(let{component:i,path:a}of Ai(t,`pages[${e}]`)){let e=U(i.properties)?i.properties:void 0;if(!e||!H(e.dataset))continue;let t=V(e.yAxis).map((e,t)=>({name:H(e.field),path:`${a}.properties.yAxis[${t}].field`})).filter(e=>!!e.name),o=V(e.series).map((e,t)=>({name:H(e.name),path:`${a}.properties.series[${t}].name`})).filter(e=>!!e.name);r({dataset:H(e.dataset),dimensions:{names:Eu(e.dimensions),path:`${a}.properties.dimensions`},values:{names:Eu(e.values),path:`${a}.properties.values`},series:[...t,...o],where:`page "${n}" \xB7 ${H(i.type)??`chart`}`,path:`${a}.properties`})}}return t}var Mu=`validation-rule-regex-uncompilable`,Nu=`validation-rule-json-schema-uncompilable`,Pu={allErrors:!0,strict:!1},Fu=e=>!!e&&typeof e==`object`&&!Array.isArray(e);function Iu(e){return Array.isArray(e)?e.filter(Fu):Fu(e)?Object.entries(e).filter(([,e])=>Fu(e)).map(([e,t])=>({name:e,...t})):[]}var Lu=null,Ru=null;function zu(){if(Lu)return Lu;let e=import.meta.url?import.meta.url:typeof __filename<`u`?__filename:process.cwd()+`/`,t;try{t=(0,S.createRequire)(e)(`ajv`)}catch(e){throw Error(`@objectstack/lint: checking a \`json_schema\` validation rule requires the "ajv" package, which could not be loaded (${e instanceof Error?e.message:String(e)}). It is a declared dependency of @objectstack/lint \u2014 if this deployment prunes packages, keep "ajv" in the image; it is only loaded when a stack declares a \`json_schema\` validation rule.`)}let n=Fu(t)&&`default`in t?t.default:t;return Lu=n,n}function Bu(){if(Ru)return Ru;let e=import.meta.url?import.meta.url:typeof __filename<`u`?__filename:process.cwd()+`/`,t;try{t=(0,S.createRequire)(e)(`ajv-formats`)}catch(e){throw Error(`@objectstack/lint: checking a \`json_schema\` validation rule requires the "ajv-formats" package, which could not be loaded (${e instanceof Error?e.message:String(e)}). It is a declared dependency of @objectstack/lint \u2014 if this deployment prunes packages, keep "ajv-formats" in the image; it is only loaded when a stack declares a \`json_schema\` validation rule. The runtime registers it too, and this gate must compile in the SAME environment or it starts disagreeing with the write path.`)}let n=Fu(t)&&`default`in t?t.default:t;return Ru=n,n}function Vu(){let e=new(zu())(Pu);return Bu()(e),e}function Hu(){let e=Object.keys(Vu().formats).sort();if(e.length===0)throw Error('@objectstack/lint: the runtime-parity ajv instance has no `format` registered. "ajv-formats" loaded but added nothing, so the set of legitimate format names is unknown — refusing to judge format names against an empty vocabulary, which would report every `format` in the stack as misspelled. Check that the installed "ajv-formats" is the real package and matches the version @objectstack/lint declares.');return e}function Uu(e){return e instanceof Error?e.message:String(e)}var Wu=16;function Gu(e,t,n,r=0){let i=typeof e.name==`string`&&e.name?e.name:`?`,a=t?`${t} \u2192 '${i}'`:`'${i}'`,o=n?`${n}.${i}`:i,s=[{rule:e,label:a,path:o}];if(r>=Wu)return s;for(let t of[`then`,`otherwise`]){let n=e[t];Fu(n)&&s.push(...Gu(n,a,`${o}.${t}`,r+1))}return s}function Ku(e){let t=[];if(!Fu(e))return t;for(let n of Iu(e.objects)){let e=typeof n.name==`string`?n.name:`(unnamed object)`,r=n.validations;for(let n of Iu(r))for(let{rule:r,label:i,path:a}of Gu(n,``,``))t.push({rule:r,objectName:e,label:i,where:`object '${e}' \xB7 validation ${i}`,basePath:`objects.${e}.validations.${a}`})}return t}function qu(e){let t=[];for(let{rule:n,objectName:r,label:i,where:a,basePath:o}of Ku(e)){if(n.type===`format`&&typeof n.regex==`string`&&n.regex!==``)try{new RegExp(n.regex)}catch(e){t.push({severity:`error`,rule:Mu,where:a,path:`${o}.regex`,message:`\`format\` validation ${i} on object '${r}' declares a \`regex\` that does not compile: ${Uu(e)}. The write path builds it with \`new RegExp(rule.regex)\` and SKIPS the rule when that throws (rule-validator.ts \`checkFormat\`), so the rule is declared, listed in the metadata, and enforces nothing on any record.`,hint:`Fix the pattern so \`new RegExp('${n.regex}')\` compiles \u2014 a literal \`(\`, \`[\` or \`\\\` must be escaped (\`\\\\(\`, \`\\\\[\`, \`\\\\\\\\\`), and the source is a STRING, so a backslash is written twice in TypeScript ('^\\\\d{2}-\\\\d{7}$'). Or drop \`regex\` and use a named \`format\` ('email' | 'url' | 'phone' | 'json').`})}if(n.type===`json_schema`&&Fu(n.schema))try{Vu().compile(n.schema)}catch(e){t.push({severity:`error`,rule:Nu,where:a,path:`${o}.schema`,message:`\`json_schema\` validation ${i} on object '${r}' declares a \`schema\` ajv cannot compile: ${Uu(e)}. The write path compiles it with the same ajv (\`new Ajv({ allErrors: true, strict: false })\` + \`ajv-formats\`) and SKIPS the rule when that throws (rule-validator.ts \`checkJsonSchema\`), so the rule is declared and enforces nothing on any record.`,hint:"Correct the schema so ajv compiles it — the message above names the offending keyword. `type` must be one of null|boolean|object|array|number|string|integer (or an array of those), `required` an array of strings, and every `$ref` must resolve. Vendor keywords are fine (the runtime runs `strict: false`); a MALFORMED standard keyword is not."})}}return t}var Ju=`validation-rule-json-schema-unknown-format`,Yu=e=>!!e&&typeof e==`object`&&!Array.isArray(e),Xu=[`additionalItems`,`additionalProperties`,`contains`,`propertyNames`,`if`,`then`,`else`,`not`,`unevaluatedItems`,`unevaluatedProperties`],Zu=[`allOf`,`anyOf`,`oneOf`,`prefixItems`],Qu=[`properties`,`patternProperties`,`$defs`,`definitions`,`dependentSchemas`],$u=32,ed=e=>e.replace(/~/g,`~0`).replace(/\//g,`~1`);function td(e,t,n,r){if(!Yu(e)||(typeof e.format==`string`&&n.push({pointer:`${t}/format`,name:e.format}),r>=32))return;for(let i of Xu)i in e&&td(e[i],`${t}/${ed(i)}`,n,r+1);for(let i of Zu){let a=e[i];Array.isArray(a)&&a.forEach((e,a)=>{td(e,`${t}/${ed(i)}/${a}`,n,r+1)})}for(let i of Qu){let a=e[i];if(Yu(a))for(let[e,o]of Object.entries(a))td(o,`${t}/${ed(i)}/${ed(e)}`,n,r+1)}let i=e.items;Array.isArray(i)?i.forEach((e,i)=>td(e,`${t}/items/${i}`,n,r+1)):Yu(i)&&td(i,`${t}/items`,n,r+1);let a=e.dependencies;if(Yu(a))for(let[e,i]of Object.entries(a))Yu(i)&&td(i,`${t}/dependencies/${ed(e)}`,n,r+1)}function nd(e,t){let n=Array.from({length:t.length+1},(e,t)=>t);for(let r=1;r<=e.length;r++){let i=[r];for(let a=1;a<=t.length;a++)i[a]=Math.min(n[a]+1,i[a-1]+1,n[a-1]+(e[r-1]===t[a-1]?0:1));n=i}return n[t.length]}function rd(e,t){let n=Math.min(3,Math.floor(e.length/2));if(n<1)return null;let r=e.toLowerCase(),i=null,a=1/0;for(let e of[...t].sort()){let t=nd(r,e);t<a&&(a=t,i=e)}return a<=n?i:null}function id(e){let t=[],n=[];for(let{rule:t,objectName:r,label:i,where:a,basePath:o}of Ku(e)){if(t.type!==`json_schema`||!Yu(t.schema))continue;let e=[];td(t.schema,``,e,0);for(let t of e)n.push({use:t,where:a,label:i,objectName:r,basePath:o})}if(n.length===0)return t;let r=Hu(),i=new Set(r);for(let{use:e,where:a,label:o,objectName:s,basePath:c}of n){if(i.has(e.name))continue;let n=rd(e.name,r),l=`#${e.pointer}`;t.push({severity:`error`,rule:Ju,where:a,path:`${c}.schema${l}`,message:`\`json_schema\` validation ${o} on object '${s}' names \`format: '${e.name}'\` at \`${l}\`, which is not a registered format. ajv logs \`unknown format "${e.name}" ignored\` once at compile time and DROPS the keyword \u2014 in the write path (rule-validator.ts, \`strict: false\`) and in the publish gate alike \u2014 so the schema compiles, the rule ships and runs on every write, its \`type\`/\`required\` keywords are enforced, and this constraint is enforced on no record, ever. The record is ACCEPTED, so nothing downstream reports the gap either.`,hint:(n?`Did you mean \`format: '${n}'\`? `:``)+`The registered names are: ${r.join(`, `)} \u2014 the default \`ajv-formats\` set, the one \`rule-validator.ts\` registers (#5029). Names are case-sensitive and hyphenated (\`date-time\`, not \`datetime\`). If you meant a constraint ajv has no format for, express it with \`pattern\` instead \u2014 a regex is enforced, an unknown format name is not.`})}return t}function ad(e){return Array.isArray(e)?e:e&&typeof e==`object`?Object.entries(e).map(([e,t])=>({name:e,...t})):[]}function od(e){let t=[];if(!e||typeof e!=`object`)return{version:1,entries:t};let n=new Map;for(let t of ad(e.objects)){let e=typeof t.name==`string`?t.name:``;if(!e)continue;let r=t.sharingModel??t.security?.sharingModel;typeof r==`string`&&n.set(e,r)}for(let r of ad(e.permissions)){let e=typeof r.name==`string`?r.name:``;if(!e)continue;let i=r.objects&&typeof r.objects==`object`?r.objects:{};for(let[r,a]of Object.entries(i)){let i=a??{},o={permissionSet:e,object:r,create:i.allowCreate===!0,read:i.allowRead===!0||i.viewAllRecords===!0||i.modifyAllRecords===!0,edit:i.allowEdit===!0||i.modifyAllRecords===!0,delete:i.allowDelete===!0||i.modifyAllRecords===!0,viewAllRecords:i.viewAllRecords===!0,modifyAllRecords:i.modifyAllRecords===!0};typeof i.readScope==`string`&&(o.readScope=i.readScope),typeof i.writeScope==`string`&&(o.writeScope=i.writeScope);let s=n.get(r);s&&(o.sharingModel=s),t.push(o)}}return t.sort((e,t)=>e.permissionSet===t.permissionSet?e.object.localeCompare(t.object):e.permissionSet.localeCompare(t.permissionSet)),{version:1,entries:t}}var sd=[[`create`,`create`],[`read`,`read`],[`edit`,`edit`],[`delete`,`delete`],[`viewAllRecords`,`View All Data`],[`modifyAllRecords`,`Modify All Data`]];function cd(e,t){let n=[],r=e=>`${e.permissionSet}\0${e.object}`,i=new Map((e?.entries??[]).map(e=>[r(e),e])),a=new Map((t?.entries??[]).map(e=>[r(e),e]));for(let[e,t]of i)a.has(e)||n.push(`'${t.permissionSet}' loses ALL access to '${t.object}' (entry removed)`);for(let[e,t]of a){let r=i.get(e);if(!r){let e=sd.filter(([e])=>t[e]===!0).map(([,e])=>e);n.push(`'${t.permissionSet}' gains access to '${t.object}' (${e.join(`, `)||`no bits set`})`);continue}for(let[e,i]of sd)r[e]!==t[e]&&n.push(`'${t.permissionSet}' ${t[e]?`gains`:`loses`} ${i} on '${t.object}'`);(r.readScope??`own`)!==(t.readScope??`own`)&&n.push(`'${t.permissionSet}' read depth on '${t.object}': ${r.readScope??`own`} \u2192 ${t.readScope??`own`}`),(r.writeScope??`own`)!==(t.writeScope??`own`)&&n.push(`'${t.permissionSet}' write depth on '${t.object}': ${r.writeScope??`own`} \u2192 ${t.writeScope??`own`}`),(r.sharingModel??``)!==(t.sharingModel??``)&&n.push(`'${t.object}' record baseline (OWD): ${r.sharingModel??`(unset)`} \u2192 ${t.sharingModel??`(unset)`} (affects every principal)`)}return n}var ld=`nav-object-ungranted`;function ud(e){return Array.isArray(e)?e:e&&typeof e==`object`?Object.entries(e).map(([e,t])=>({name:e,...t})):[]}function dd(e){return typeof e==`string`&&e.length>0?e:void 0}function fd(e){let t=[],n=ud(e.apps);for(let e=0;e<n.length;e++){let r=n[e];if(!r||typeof r!=`object`)continue;let i=dd(r.name)??`#${e}`,a=(e,n)=>{let r=ud(e);for(let e=0;e<r.length;e++){let o=r[e];if(!o||typeof o!=`object`)continue;let s=`${n}[${e}]`,c=dd(o.objectName);o.type===`object`&&c&&t.push({objectName:c,where:`app "${i}" \xB7 nav "${dd(o.id)??`#${e}`}"`,path:`${s}.objectName`}),Array.isArray(o.children)&&a(o.children,`${s}.children`)}};a(r.navigation,`apps[${e}].navigation`);let o=ud(r.areas);for(let t=0;t<o.length;t++)a(o[t]?.navigation,`apps[${e}].areas[${t}].navigation`)}return t}function pd(e){let t=[];if(!e||typeof e!=`object`||ud(e.permissions).length===0)return t;let n=fd(e);if(n.length===0)return t;let r=new Set;for(let t of ud(e.objects)){let e=dd(t.name);e&&r.add(e)}let i=new Set;for(let t of od(e).entries)t.read&&i.add(t.object);if(i.has(`*`))return t;let a=new Set;for(let e of n){let{objectName:n}=e;a.has(n)||Ae(n)||r.has(n)&&(i.has(n)||(a.add(n),t.push({severity:`warning`,rule:ld,where:e.where,path:e.path,message:`navigation exposes object "${n}", but no permission set this stack declares grants read on it \u2014 the entry renders, and opening it fails permission-denied for every principal except one holding the platform's built-in wildcard admin set. It works when you browse as an administrator and breaks for the users the app ships permission sets for.`,hint:`Add "${n}" to a permission set's \`objects\` with \`allowRead: true\` (or \`viewAllRecords\`), gate the entry with \`requiredPermissions\`/\`visible\` if it is meant for admins only, or drop it. Ignore this if a permission set from another installed package grants it.`})))}return t}var md=`translation-target-unknown`,hd=`translation-option-key-unknown`;function W(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function G(e){return Array.isArray(e)?e:W(e)?Object.entries(e).map(([e,t])=>({name:e,...W(t)?t:{}})):[]}function K(e){return typeof e==`string`&&e.length>0?e:void 0}function gd(e,t){let n=e.length,r=t.length;if(n===0)return r;if(r===0)return n;let i=Array.from({length:r+1},(e,t)=>t);for(let a=1;a<=n;a++){let n=[a,...Array(r).fill(0)];for(let o=1;o<=r;o++){let r=e[a-1]===t[o-1]?0:1;n[o]=Math.min(n[o-1]+1,i[o]+1,i[o-1]+r)}i=n}return i[r]}function q(e,t){let n=[...t],r=n.find(t=>t.endsWith(`_${e}`)||t.startsWith(`${e}_`));if(r)return` Did you mean "${r}"?`;let i,a=1/0;for(let t of n){let n=gd(e,t);n<a&&(a=n,i=t)}let o=Math.max(2,Math.floor(e.length/3));return i&&a<=o?` Did you mean "${i}"?`:``}function J(e,t=12){let n=[...e].sort();if(n.length===0)return``;let r=n.slice(0,t).join(`, `);return n.length>t?`${r}, \u2026 (${n.length} total)`:r}var _d=new Set([...it,`_id`,`name`,`space`]);function vd(){return{fields:new Map,views:new Set,actions:new Map,sections:new Set}}function yd(e,t){let n=Wa(e),r=e=>Wa(e)??n,i=(e,n)=>{e&&n&&t(e).views.add(n)},a=(e,n)=>{if(n)for(let r of G(e.sections)){let e=K(r.name);e&&t(n).sections.add(e)}},o=W(e.list)?r(e.list):void 0;W(e.list)&&i(o,bd(o,e)),i(n??o,K(e.name));let s=xd(e);for(let t of[`listViews`,`formViews`]){let n=e[t];if(!W(n))continue;let c=t===`listViews`?s.list:s.form,l=0;for(let e of Object.values(n)){if(!e||typeof e!=`object`)continue;let t=c[l++];if(!W(e))continue;let n=r(e)??o;i(n,t),a(e,n)}}W(e.form)&&a(e.form,r(e.form)??o),a(e,n??o)}function bd(e,t){if(!e||!W(t.list))return;let n=p(e,t).find(e=>e.viewKind===`list`&&e.isDefault);if(!n)return;let r=`${e}.`;return n.name.startsWith(r)?n.name.slice(r.length):n.name}function xd(e){let t=`probe`,n=`${t}.`,r=e=>e.startsWith(n)?e.slice(n.length):e,i=e=>W(e)?Object.values(e).filter(e=>!!e&&typeof e==`object`).length:0,a=i(e.listViews),o=i(e.formViews);if(!a&&!o)return{list:[],form:[]};let s=p(t,e),c=(e,t)=>s.filter(t=>t.viewKind===e).slice(0,t).map(e=>r(e.name));return{list:c(`list`,a),form:c(`form`,o)}}function Sd(e){let t=e.options,n=new Set,r=new Map;if(Array.isArray(t))for(let e of t){if(typeof e==`string`){n.add(e);continue}if(!W(e))continue;let t=K(e.value);if(!t)continue;n.add(t);let i=K(e.label);i&&r.set(i.toLowerCase(),t)}else if(W(t))for(let[e,i]of Object.entries(t))n.add(e),typeof i==`string`&&i.length>0&&r.set(i.toLowerCase(),e);else return;return n.size>0?{values:n,byLabel:r}:void 0}function Cd(e){let t=new Map,n=e=>{let n=t.get(e);return n||(n=vd(),t.set(e,n)),n};for(let t of G(e.objects)){let e=K(t.name);if(!e)continue;let r=n(e);for(let e of G(t.fields)){let t=K(e.name);t&&r.fields.set(t,e)}for(let e of G(t.actions)){let t=K(e.name);t&&r.actions.set(t,e)}for(let r of G(t.views))yd({...r,object:K(r.object)??e},n);yd({object:e,listViews:t.listViews},n);for(let e of G(t.fieldGroups)){let t=K(e.key)??K(e.name);t&&r.sections.add(t)}}for(let t of G(e.views))yd(t,n);let r=G(e.pages);for(let e=0;e<r.length;e++)for(let t of Ai(r[e],`pages[${e}]`)){if(!t.objectName)continue;let e=W(t.component.properties)?t.component.properties:void 0;if(e)for(let r of G(e.sections)){let e=K(r.name);e&&n(t.objectName).sections.add(e)}}let i=new Map,a=new Map;for(let t of G(e.actions)){let e=K(t.name);if(!e)continue;let r=K(t.objectName)??K(t.object);r?(n(r).actions.set(e,t),a.set(e,r)):i.set(e,t)}for(let[e,n]of t)for(let t of n.actions.keys())a.has(t)||a.set(t,e);let o=new Map;for(let t of G(e.apps)){let e=K(t.name);if(!e)continue;let n=o.get(e)??new Set,r=e=>{for(let t of G(e)){let e=K(t.id);e&&n.add(e),t.children&&r(t.children)}};r(t.navigation);for(let e of G(t.areas)){let t=K(e.id);t&&n.add(t),r(e.navigation)}o.set(e,n)}let s=new Map;for(let t of G(e.dashboards)){let e=K(t.name);if(!e)continue;let n=new Set;for(let e of G(t.widgets)){let t=K(e.id)??K(e.name);t&&n.add(t)}let r=new Set,i=[...G(W(t.header)?t.header.actions:void 0),...G(t.actions)];for(let e of i){let t=K(e.actionUrl)??K(e.url)??K(e.name);t&&r.add(t)}s.set(e,{widgets:n,actions:r})}return{objects:t,apps:o,dashboards:s,globalActions:i,actionOwners:a}}function wd(e,t){return/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(t)?`translations[${e}].${t}`:`translations[${e}]["${t}"]`}function Td(e){let t=[];if(!W(e))return t;let n=Array.isArray(e.translations)?e.translations:[];if(n.length===0)return t;let r=Cd(e),i=(e,n,r,i)=>{t.push({severity:`warning`,rule:md,where:e,path:n,message:r,hint:i})};for(let e=0;e<n.length;e++){let a=n[e];if(W(a))for(let[n,o]of Object.entries(a)){if(!W(o))continue;let a=wd(e,n),s=`locale "${n}"`;for(let[e,n]of Object.entries(Y(o.objects))){if(!W(n))continue;let o=`${a}.objects.${e}`,c=r.objects.get(e);if(!c){if(Ae(e))continue;i(`${s} \xB7 object "${e}"`,o,Oe(e)?`Translations are keyed to "${e}", which carries a platform namespace prefix but is registered by no platform package, official plugin, or cloud runtime object \u2014 and this stack does not define it either. Nothing resolves these keys.`+q(e,r.objects.keys()):`Translations are keyed to "${e}", which no object in this stack defines. The resolver looks up keys derived from the metadata, so this whole subtree is dead weight \u2014 every label it carries renders untranslated.`+q(e,r.objects.keys()),`Rename the key to the object it was written for, drop it, or ignore this if the object is contributed by another installed package.`+(r.objects.size>0?` Defined objects: ${J(r.objects.keys())}.`:``));continue}for(let[r,a]of Object.entries(Y(n.fields))){let n=`${o}.fields.${r}`,l=c.fields.get(r);if(!l){if(_d.has(r))continue;i(`${s} \xB7 object "${e}" \xB7 field "${r}"`,n,`Translations are keyed to field "${r}", which object "${e}" does not declare. The label renders untranslated in this locale \u2014 and because every neighbouring field DOES resolve, the hole reads as a styling quirk rather than a missing translation.`+q(r,c.fields.keys()),`Point the key at a declared field, or drop it if the field was removed or renamed.`+(c.fields.size>0?` Declared fields: ${J(c.fields.keys())}.`:``));continue}W(a)&&Ed(t,{optionMap:a.options,field:l,fieldName:r,objectName:e,path:`${n}.options`,where:`${s} \xB7 object "${e}" \xB7 field "${r}"`})}for(let t of Object.keys(Y(n._views)))c.views.has(t)||i(`${s} \xB7 object "${e}" \xB7 view "${t}"`,`${o}._views.${t}`,`Translations are keyed to view "${t}", which no view of object "${e}" declares. The view tab keeps its source-locale label.`+q(t,c.views),"Match the key to the view's `name` (not its label), or drop it."+(c.views.size>0?` Declared views: ${J(c.views)}.`:``));for(let t of Object.keys(Y(n._sections)))c.sections.has(t)||i(`${s} \xB7 object "${e}" \xB7 section "${t}"`,`${o}._sections.${t}`,`Translations are keyed to section "${t}", which nothing on object "${e}" declares \u2014 no \`fieldGroups[].key\`, no named form-view section, no named \`record:details\` section. The section heading stays in the source locale.`+q(t,c.sections),"Sections are translatable only through a STABLE NAME: give the group/section a `key`/`name` and use it here, or drop the translation."+(c.sections.size>0?` Declared sections: ${J(c.sections)}.`:` Object "${e}" declares no named section at all.`));for(let[r,a]of Object.entries(Y(n._actions))){let n=`${o}._actions.${r}`,l=c.actions.get(r);if(!l){i(`${s} \xB7 object "${e}" \xB7 action "${r}"`,n,`Translations are keyed to action "${r}", which is defined by neither object "${e}"'s \`actions\` nor a \`stack.actions\` entry bound to it. The button keeps its source-locale label.`+q(r,c.actions.keys()),`Match the key to a defined action name, move it under the object that owns the action, or drop it.`+(c.actions.size>0?` Actions on this object: ${J(c.actions.keys())}.`:``));continue}Dd(t,{rawAction:a,action:l,path:n,where:`${s} \xB7 object "${e}" \xB7 action "${r}"`,subject:`action "${r}"`})}}for(let[e,n]of Object.entries(Y(o.globalActions))){let o=`${a}.globalActions.${e}`,c=r.globalActions.get(e);if(!c){let t=r.actionOwners.get(e);i(`${s} \xB7 global action "${e}"`,o,t?`Action "${e}" is bound to object "${t}", so the resolver looks it up under \`objects.${t}._actions.${e}\` \u2014 never under \`globalActions\`, which is only consulted for object-less actions. This key is never read.`:`Translations are keyed to global action "${e}", which no object-less action in this stack defines. The button keeps its source-locale label.`+q(e,r.globalActions.keys()),t?`Move these keys under \`objects.${t}._actions.${e}\`.`:`Match the key to an object-less action's name, or drop it.`+(r.globalActions.size>0?` Object-less actions: ${J(r.globalActions.keys())}.`:``));continue}Dd(t,{rawAction:n,action:c,path:o,where:`${s} \xB7 global action "${e}"`,subject:`action "${e}"`})}for(let[e,t]of Object.entries(Y(o.apps))){let n=`${a}.apps.${e}`,o=r.apps.get(e);if(!o){i(`${s} \xB7 app "${e}"`,n,`Translations are keyed to app "${e}", which this stack does not define. The app launcher shows the source-locale label.`+q(e,r.apps.keys()),"Match the key to an app's `name`, or drop it."+(r.apps.size>0?` Defined apps: ${J(r.apps.keys())}.`:``));continue}if(W(t))for(let r of Object.keys(Y(t.navigation)))o.has(r)||i(`${s} \xB7 app "${e}" \xB7 navigation "${r}"`,`${n}.navigation.${r}`,`Translations are keyed to navigation item "${r}", which app "${e}" does not declare. The menu entry keeps its source-locale label.`+q(r,o),"Match the key to the navigation item's `id`, or drop it."+(o.size>0?` Declared navigation ids: ${J(o)}.`:``))}for(let[e,t]of Object.entries(Y(o.dashboards))){let n=`${a}.dashboards.${e}`,o=r.dashboards.get(e);if(!o){i(`${s} \xB7 dashboard "${e}"`,n,`Translations are keyed to dashboard "${e}", which this stack does not define. The dashboard title stays in the source locale.`+q(e,r.dashboards.keys()),"Match the key to a dashboard's `name`, or drop it."+(r.dashboards.size>0?` Defined dashboards: ${J(r.dashboards.keys())}.`:``));continue}if(W(t)){for(let r of Object.keys(Y(t.widgets)))o.widgets.has(r)||i(`${s} \xB7 dashboard "${e}" \xB7 widget "${r}"`,`${n}.widgets.${r}`,`Translations are keyed to widget "${r}", which dashboard "${e}" does not declare. The widget title stays in the source locale.`+q(r,o.widgets),"Match the key to the widget's `id`, or drop it."+(o.widgets.size>0?` Declared widget ids: ${J(o.widgets)}.`:``));for(let r of Object.keys(Y(t.actions)))o.actions.has(r)||i(`${s} \xB7 dashboard "${e}" \xB7 action "${r}"`,`${n}.actions.${r}`,`Translations are keyed to header action "${r}", which dashboard "${e}" does not declare. The button keeps its source-locale label.`+q(r,o.actions),"Header-action translations are keyed by the action's `actionUrl`, not its label."+(o.actions.size>0?` Declared header actions: ${J(o.actions)}.`:``))}}}}return t}function Y(e){return W(e)?e:{}}function Ed(e,t){let n=Object.keys(Y(t.optionMap));if(n.length===0)return;let r=Sd(t.field);if(!r){e.push({severity:`warning`,rule:hd,where:t.where,path:t.path,message:`Option translations are keyed under field "${t.fieldName}" of object "${t.objectName}", which declares no \`options\` at all (field type "${K(t.field.type)??`unknown`}"). Nothing reads this map.`,hint:`Declare the options on the field, move the translations to the field that owns them, or drop them.`});return}for(let i of n){if(r.values.has(i))continue;let n=r.byLabel.get(i.toLowerCase());e.push({severity:`warning`,rule:hd,where:t.where,path:`${t.path}.${i}`,message:n?`Option translation is keyed by the DISPLAY LABEL "${i}" instead of the stored value "${n}". The resolver looks the option up by value, so this entry is never found and the option renders with its source-locale label.`:`Option translation is keyed by "${i}", which is not one of the values declared by field "${t.objectName}.${t.fieldName}". The option renders untranslated.`+q(i,r.values),hint:n?`Rename the key to "${n}".`:`Option keys are the stored \`value\`, not the label and not a variant spelling (\`direct_mail\`, not \`direct-mail\`). Declared values: ${J(r.values)}.`})}}function Dd(e,t){let n=Object.keys(Y(W(t.rawAction)?t.rawAction.params:void 0));if(n.length===0)return;let r=new Set;for(let e of G(t.action.params)){let t=K(e.name)??K(e.field);t&&r.add(t)}for(let i of n)r.has(i)||e.push({severity:`warning`,rule:md,where:`${t.where} \xB7 param "${i}"`,path:`${t.path}.params.${i}`,message:`Translations are keyed to parameter "${i}", which ${t.subject} does not declare. The parameter's label and help text render untranslated in the action dialog.`+q(i,r),hint:"Match the key to a declared param `name`, or drop it."+(r.size>0?` Declared params: ${J(r)}.`:``)})}var Od=`translation-section-name-missing`;function kd(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function Ad(e){return typeof e==`string`&&e.length>0?e:void 0}function jd(e){let t=Ad(e.name);return t?`view "${t}"`:``}function Md(...e){return e.filter(e=>e.length>0).join(` · `)}function Nd(e,t,n,r){let i=Wa(e),a=kd(e.list)?Wa(e.list)??i:void 0;for(let o of Ga(e,t))r.push({path:`${o.path}.sections`,surface:Md(n,o.surface),objectName:Wa(o.view)??i??a,sections:o.view.sections})}function Pd(e){let t=new Set,n=Array.isArray(e.translations)?e.translations:[];for(let e of n)if(kd(e)){for(let n of Object.values(e))if(!(!kd(n)||!kd(n.objects)))for(let[e,r]of Object.entries(n.objects))kd(r)&&t.add(e)}return t}function Fd(e){let t=e.toLowerCase().replace(/&/g,` and `).replace(/[^a-z0-9]+/g,`_`).replace(/^_+|_+$/g,``);return t.length>0?t:void 0}function Id(e){let t=[];if(!kd(e))return t;let n=Pd(e);if(n.size===0)return t;let r=[];for(let{rec:t,path:n}of Va(e.objects,`objects`)){let e=Ad(t.name);if(e){for(let{rec:i,path:a}of Va(t.views,`${n}.views`))Nd({...i,object:Ad(i.object)??e},a,jd(i),r);kd(t.listViews)&&Nd({object:e,listViews:t.listViews},n,``,r)}}for(let{rec:t,path:n}of Va(e.views,`views`))Nd(t,n,jd(t),r);for(let{rec:t,path:n}of Va(e.pages,`pages`)){let e=Ad(t.name),i=e?`page "${e}"`:``;for(let e of Ai(t,n)){if(!e.objectName)continue;let t=kd(e.component.properties)?e.component.properties:void 0;if(!t)continue;let n=Ad(e.component.type)??`component`;r.push({path:`${e.path}.properties.sections`,surface:Md(i,n),objectName:e.objectName,sections:t.sections})}}for(let e of r){let r=e.objectName;if(!(!r||!n.has(r))&&Array.isArray(e.sections))for(let n=0;n<e.sections.length;n++){let i=e.sections[n];if(!kd(i)||Ad(i.name))continue;let a=Ad(i.label);if(!a)continue;let o=Fd(a);t.push({severity:`warning`,rule:Od,where:Md(`object "${r}"`,e.surface,`section "${a}"`),path:`${e.path}[${n}]`,message:`Section "${a}" declares a label but no \`name\`. Headings resolve through \`objects.${r}._sections.<name>.label\`, so a section with no name has no key a bundle can carry \u2014 this heading can never be translated and renders in the source locale in EVERY locale. Object "${r}" IS translated, which is what makes the hole invisible: every neighbouring label resolves and only the heading stays behind. The i18n coverage report cannot see it either \u2014 it walks \`sections[].name\`, and a nameless section contributes nothing to walk.`,hint:"Give the section a stable `name` (snake_case)"+(o?`, e.g. \`name: '${o}'\``:``)+`, then translate it as \`objects.${r}._sections.${o??`<name>`}.label\` in each locale bundle. The renderers look the heading up by name only \u2014 the name above is a suggestion to write down, never a key derived from the label, so renaming the heading later cannot break the lookup.`})}}return t}var Ld=`ai-skill-surface-mismatch`;function Rd(e){return Array.isArray(e)?e.filter(e=>!!e&&typeof e==`object`):e&&typeof e==`object`?Object.entries(e).map(([e,t])=>({name:e,...t})):[]}function zd(e){return typeof e==`string`&&e.length>0?e:void 0}function Bd(e){return typeof e==`string`&&e.length>0?e:`ask`}function Vd(e){let t=[];if(!e||typeof e!=`object`)return t;let n=new Map;for(let t of Rd(e.skills)){let e=zd(t.name);e&&n.set(e,t)}let r=Rd(e.agents);for(let e=0;e<r.length;e++){let i=r[e],a=zd(i.name)??`#${e}`,o=Bd(i.surface),s=Array.isArray(i.skills)?i.skills:[];for(let r=0;r<s.length;r++){let i=zd(s[r]);if(!i)continue;let c=n.get(i);if(!c)continue;let l=Bd(c.surface);l!==`both`&&l!==o&&t.push({severity:`error`,rule:Ld,where:`agent "${a}" \xB7 skills`,path:`agents[${e}].skills[${r}]`,message:`Agent "${a}" (surface: '${o}') references skill "${i}" (surface: '${l}') \u2014 incompatible affinity (ADR-0064 \xA73). The runtime refuses this binding with a load error, so chatting with this agent fails at request time even though the stack parses and validates cleanly.`,hint:`A skill may only attach to an agent whose surface it matches. Move "${i}" to a '${l}'-surface agent, change its \`surface\` to '${o}', or \u2014 only if it is a genuinely shared, read-only capability \u2014 declare \`surface: 'both'\`.`})}}return t}var Hd=`ai-skill-tool-unresolved`;function Ud(e){return Array.isArray(e)?e.filter(e=>!!e&&typeof e==`object`):e&&typeof e==`object`?Object.entries(e).map(([e,t])=>({name:e,...t})):[]}function Wd(e){return typeof e==`string`&&e.length>0?e:void 0}function Gd(e,t){let n=e.length,r=t.length;if(n===0)return r;if(r===0)return n;let i=Array.from({length:r+1},(e,t)=>t);for(let a=1;a<=n;a++){let n=[a,...Array(r).fill(0)];for(let o=1;o<=r;o++){let r=e[a-1]===t[o-1]?0:1;n[o]=Math.min(n[o-1]+1,i[o]+1,i[o-1]+r)}i=n}return i[r]}function Kd(e,t){for(let n of Ve)if(t.has(`${n}${e}`))return` Did you mean "${n}${e}"?`;let n,r=1/0;for(let i of t){let t=Gd(e,i);t<r&&(r=t,n=i)}let i=Math.max(2,Math.floor(e.length/3));return n&&r<=i?` Did you mean "${n}"?`:``}var qd=new Set([`script`,`api`,`flow`]);function Jd(e){let t=e.ai;if(!t||typeof t!=`object`)return!1;let n=t;if(n.exposed!==!0||!Wd(n.description))return!1;let r=Wd(e.type);return!r||!qd.has(r)?!1:r===`script`?!!(e.target||e.body):!!e.target}function Yd(e){let t=new Set(De);for(let n of Ud(e.tools)){let e=Wd(n.name);e&&t.add(e)}let n=e=>{for(let n of Ud(e)){let e=Wd(n.name);e&&Jd(n)&&t.add(`action_${e}`)}};n(e.actions);for(let t of Ud(e.objects))n(t.actions);return t}function Xd(e){let t=new Set,n=e=>{for(let n of Ud(e)){let e=Wd(n.name);e&&!Jd(n)&&t.add(e)}};n(e.actions);for(let t of Ud(e.objects))n(t.actions);return t}function Zd(e){let t=[];if(!e||typeof e!=`object`)return t;let n=Yd(e),r=Xd(e),i=e=>{if(e.endsWith(`*`)){let t=e.slice(0,-1);for(let e of n)if(e.startsWith(t))return!0;return!1}return n.has(e)},a=Ud(e.skills);for(let e=0;e<a.length;e++){let o=a[e],s=Wd(o.name)??`#${e}`,c=Array.isArray(o.tools)?o.tools:[];for(let a=0;a<c.length;a++){let o=Wd(c[a]);if(!o||i(o))continue;let l=o.endsWith(`*`),u=!l&&o.startsWith(`action_`)&&r.has(o.slice(7))?o.slice(7):void 0;t.push({severity:`warning`,rule:Hd,where:`skill "${s}" \xB7 tools`,path:`skills[${e}].tools[${a}]`,message:l?`Skill "${s}" subscribes to tool family "${o}", which matches nothing this stack can resolve (no declared tool, no platform tool, and no AI-exposed declarative action materialises into it). The subscription contributes zero tools at runtime.`:u?`Skill "${s}" references tool "${o}", but the action "${u}" does not become an AI tool: the runtime materialises \`action_<name>\` only for an action that opts in with \`ai.exposed: true\` + \`ai.description\` (ADR-0011) AND has a headless path (type \`script\`/\`api\`/\`flow\` with a target or body \u2014 \`url\`/\`modal\`/\`form\` are UI-only). The reference is dropped at runtime, so the skill promises a capability the agent cannot call.`:`Skill "${s}" references tool "${o}", which resolves to nothing this stack can see: not a \`stack.tools\` record, not a platform-registered tool, and not a materialised action tool (\`action_<name>\`). The runtime silently drops the reference, so the skill's instructions claim a capability the agent does not have \u2014 the assistant will improvise or fail when asked to use it.`+Kd(o,n),hint:u?`Either opt "${u}" in \u2014 set \`ai: { exposed: true, description: '\u2026' }\` (\u226540 chars, LLM-facing) and give it a headless type \u2014 or drop the reference and have the skill's instructions recommend the UI action instead. A \`modal\`/\`form\`/\`url\` action stays human-driven by design; that is a legitimate answer, not a gap.`:`Back "${o}" with a real executable: declare a declarative action (or flow), opt it in with \`ai.exposed: true\` + \`ai.description\`, and reference its materialised tool (\`action_<name>\` \u2014 the ADR-0109 default path, no tool record needed); or reference a platform tool by its registered name; or remove the reference and the instructions that mention it. Ignore this only if a runtime plugin outside the platform registry provides "${o}". Family prefixes materialised by the runtime: ${Ve.join(`, `)}.`})}}return t}var Qd=`agent-authoring-withdrawn`,$d=`default-agent-outside-roster`;function ef(e){return Array.isArray(e)?e.filter(e=>!!e&&typeof e==`object`):e&&typeof e==`object`?Object.entries(e).map(([e,t])=>({name:e,...t})):[]}function tf(e){return typeof e==`string`&&e.length>0?e:void 0}var nf=new Set([`ask`,`build`,`data_chat`,`metadata_assistant`]);function rf(e){let t=[];if(!e||typeof e!=`object`)return t;let n=ef(e.agents);for(let e=0;e<n.length;e++){let r=n[e],i=tf(r.name)??`#${e}`,a=nf.has(i),o=Array.isArray(r.skills)?r.skills.length:0;t.push({severity:`warning`,rule:Qd,where:`agent "${i}"`,path:`agents[${e}]`,message:a?`This stack declares an agent named "${i}", which is a PLATFORM agent id. The runtime serves its own record for that name and ignores this one \u2014 the declaration has no effect and will drift from the platform's definition.`:`This stack declares the agent "${i}", but tenant/app-package agents were withdrawn (ADR-0063 \xA72): the kernel ships exactly two agents (\`ask\`, \`build\`) and the surface the user is in binds one. The runtime filters this record out of the agent catalog and refuses to load it, so it never runs \u2014 it parses, validates, and ships as inert metadata.`,hint:a?`Remove the declaration; the platform owns "${i}". Extend it with skills instead.`:"Delete the agent and express its capability as skills. Everything an agent carried that a skill does not is persona text: move the useful parts of `instructions` into the skills' own instructions."+(o>0?` The ${o} skill${o===1?``:`s`} this agent references already carry the capability \u2014 they attach to the platform agent by \`surface\` affinity, so nothing is lost by dropping the persona.`:``)})}let r=[...nf].join(`, `),i=ef(e.apps);for(let e=0;e<i.length;e++){let n=i[e],a=tf(n.defaultAgent);if(!a||nf.has(a))continue;let o=tf(n.name)??`#${e}`;t.push({severity:`warning`,rule:$d,where:`app "${o}".defaultAgent`,path:`apps[${e}].defaultAgent`,message:`app "${o}" pins \`defaultAgent\` to "${a}", which is not in the platform agent roster (${r}). The kernel ships exactly two agents (ADR-0063 \xA72) and resolves this key against them and their legacy aliases only \u2014 an unrecognized name is not rejected, it silently falls back to the platform default at runtime, so the pin has no effect and the value drifts from what actually serves the app.`,hint:`Set \`defaultAgent\` to one of the platform agent names: ${r}. If the goal is a dedicated persona or capability, express it as skills instead \u2014 they attach to "ask" / "build" by surface affinity, not as a custom \`defaultAgent\` value.`})}return t}var af=null;function of(){if(af)return af;let e=import.meta.url?import.meta.url:typeof __filename<`u`?__filename:process.cwd()+`/`;try{af=(0,S.createRequire)(e)(`typescript`)}catch(e){throw Error(`@objectstack/lint: checking an L2 (language:'js') hook body requires the "typescript" package, which could not be loaded (${e instanceof Error?e.message:String(e)}). It is a declared dependency of @objectstack/lint \u2014 if this deployment prunes packages, keep "typescript" in the image; it is only loaded when a hook with a JS body is validated.`)}return af}var sf=`hook-body-write-unknown-field`,cf=`hook-body-source-unparseable`,lf=`hook-body-write-unprovisioned-anchor`,uf=[{id:`input-property-assign`,syntax:`ctx.input.<field> = … | ctx.input['<field>'] ⟨op⟩= …`,example:{source:`ctx.input.total = 0; ctx.input['status'] ??= 'open'; ctx.input.retries += 1;`,writes:[{field:`total`},{field:`status`},{field:`retries`}]}},{id:`input-object-assign`,syntax:`Object.assign(ctx.input, { <field>: … })`,example:{source:`Object.assign(ctx.input, { total: 5, 'status': 'open', discount });`,writes:[{field:`total`},{field:`status`},{field:`discount`}]}},{id:`record-property-assign`,syntax:`ctx.record.<field> = … | ctx.record['<field>'] ⟨op⟩= …`,example:{source:`ctx.record.stage = 'won'; ctx.record['amount'] += 1;`,writes:[{field:`stage`},{field:`amount`}]}},{id:`api-crud-literal`,syntax:`ctx.api.object('<object>').insert({…}) | .create({…}) | .update({…}) | .updateById(id, {…})`,example:{source:`await ctx.api.object('audit_log').insert({ event: 'won' }); await ctx.api.object('crm_deal').updateById(id, { stage: 'won' });`,writes:[{field:`event`,object:`audit_log`},{field:`stage`,object:`crm_deal`}]}}],df=[`input-property-assign`,`input-object-assign`,`api-crud-literal`],ff=[{id:`record-property-assign`,reason:"a hook sandbox context has no `ctx.record` at all — `buildSandboxContext` never sets it (a hook’s record IS `ctx.input`), so the expression throws at run time rather than silently no-op’ing. A loud failure the author sees on the first run is not this advisory rule’s business"}],pf=new Set(df),mf=new Map([[`insert`,0],[`create`,0],[`update`,0],[`updateById`,1]]),hf=new Set([`id`,`options`,`ast`,`data`]),gf=new Set([...it,`_id`,`name`,`space`,`owner`,`record_type`]);function _f(){return`so the value can never land: the anchor exists only in the registered schema, which is what carries it PAST the write-path validator that refuses an undeclared name outright (INVALID_FIELD). The remote database is what rejects it — on a SQL remote with an untyped driver error ('no such column') that aborts the whole statement, so the correctly named fields in the same payload never land either; on a schemaless remote the key is persisted into a column no read surface returns (#4271).`}var vf=e=>!!e&&typeof e==`object`&&!Array.isArray(e);function yf(e){return Array.isArray(e)?e.filter(e=>vf(e)):vf(e)?Object.entries(e).map(([e,t])=>({name:e,...vf(t)?t:{}})):[]}function bf(e){let t=new Map;for(let n of yf(e.objects)){let e=typeof n.name==`string`?n.name:void 0;if(!e)continue;let r=new Set;for(let e of yf(n.fields))typeof e.name==`string`&&e.name&&r.add(e.name);t.set(e,r)}return t}function xf(e,t){let n=e.get(t);if(!(!n||n.size===0))return n}function Sf(e){return Cf(e).writes}function Cf(e){if(!/\bctx\b/.test(e)&&!/\bObject\b/.test(e))return{writes:[],ctxRecordEscapes:!1};let t=of(),{sourceFile:n,failure:r}=un(t,`hook-body.ts`,`async function __body(ctx) {
4
- ${e}
5
- }`,{target:t.ScriptTarget.Latest,setParentNodes:!1,scriptKind:t.ScriptKind.TS,synthesizedLinesBefore:1}),i=[],a=[],o=new Set,s=(e,n)=>t.isPropertyAccessExpression(e)&&t.isIdentifier(e.expression)&&e.expression.text===`ctx`&&e.name.text===n,c=(e,n)=>{if(t.isPropertyAccessExpression(e)&&t.isIdentifier(e.name)&&s(e.expression,n))return e.name.text;if(t.isElementAccessExpression(e)&&s(e.expression,n)){let n=e.argumentExpression;if(t.isStringLiteral(n)||t.isNoSubstitutionTemplateLiteral(n))return n.text}},l=e=>{if(!t.isObjectLiteralExpression(e))return[];let n=[];for(let r of e.properties)t.isPropertyAssignment(r)?(t.isIdentifier(r.name)||t.isStringLiteral(r.name))&&n.push(r.name.text):t.isShorthandPropertyAssignment(r)&&n.push(r.name.text);return n},u=e=>{if(t.isBinaryExpression(e)&&e.operatorToken.kind>=t.SyntaxKind.FirstAssignment&&e.operatorToken.kind<=t.SyntaxKind.LastAssignment){let t=c(e.left,`input`);t!==void 0&&!hf.has(t)&&i.push({patternId:`input-property-assign`,field:t});let n=c(e.left,`record`);n!==void 0&&i.push({patternId:`record-property-assign`,field:n})}if((t.isPropertyAccessExpression(e)||t.isElementAccessExpression(e))&&s(e.expression,`record`)&&o.add(e.expression),t.isBinaryExpression(e)){let n=e.operatorToken.kind;(n===t.SyntaxKind.AmpersandAmpersandToken||n===t.SyntaxKind.BarBarToken||n===t.SyntaxKind.QuestionQuestionToken)&&s(e.left,`record`)&&o.add(e.left)}if(t.isPrefixUnaryExpression(e)&&e.operator===t.SyntaxKind.ExclamationToken&&s(e.operand,`record`)&&o.add(e.operand),t.isTypeOfExpression(e)&&s(e.expression,`record`)&&o.add(e.expression),(t.isIfStatement(e)||t.isWhileStatement(e)||t.isDoStatement(e))&&s(e.expression,`record`)&&o.add(e.expression),t.isConditionalExpression(e)&&s(e.condition,`record`)&&o.add(e.condition),s(e,`record`)&&a.push(e),t.isCallExpression(e)){let n=e.expression;if(t.isPropertyAccessExpression(n)&&t.isIdentifier(n.expression)&&n.expression.text===`Object`&&n.name.text===`assign`&&e.arguments.length>=2&&s(e.arguments[0],`input`))for(let t of e.arguments.slice(1))for(let e of l(t))hf.has(e)||i.push({patternId:`input-object-assign`,field:e});if(t.isPropertyAccessExpression(n)&&t.isIdentifier(n.name)){let r=mf.get(n.name.text),a=n.expression;if(r!==void 0&&t.isCallExpression(a)&&t.isPropertyAccessExpression(a.expression)&&a.expression.name.text===`object`&&s(a.expression.expression,`api`)&&a.arguments.length===1){let o=a.arguments[0],s=t.isStringLiteral(o)||t.isNoSubstitutionTemplateLiteral(o)?o.text:void 0,c=e.arguments[r];if(s&&c!==void 0)for(let e of l(c))i.push({patternId:`api-crud-literal`,object:s,method:n.name.text,field:e})}}}t.forEachChild(e,u)};return u(n),{writes:i,ctxRecordEscapes:a.some(e=>!o.has(e)),...r?{parseFailure:r}:{}}}function wf(e){let t=[],n=yf(e.hooks);if(n.length===0)return t;let r=null,i=null;return n.forEach((n,a)=>{let o=n.body;if(!vf(o)||o.language!==`js`)return;let s=o.source;if(typeof s!=`string`||s.trim()===``)return;let c=Cf(s),l=typeof n.name==`string`&&n.name?n.name:`#${a}`;c.parseFailure&&t.push({severity:`warning`,rule:cf,where:`hook "${l}" \u203A body`,path:`hooks[${a}].body.source`,message:`L2 body did not parse (${dn(c.parseFailure)}), so its write set was read from a partially recovered tree \u2014 an undeclared field write in the unread part is not reported.`,hint:fn});let u=c.writes.filter(e=>pf.has(e.patternId));if(u.length===0)return;r??=bf(e),i??=ct(e);let d=(Array.isArray(n.object)?n.object:[n.object]).filter(e=>typeof e==`string`&&e.trim()!==``),f=d.map(e=>xf(r,e)),p=d.length>0&&!d.includes(`*`)&&f.every(e=>e!==void 0),m=`hook "${l}" \u203A body`,h=`hooks[${a}].body.source`,g=new Set;for(let e of u){let n=`${e.object??``}\0${e.field}`;if(!g.has(n)){if(e.object===void 0){if(!p)continue;if(gf.has(e.field)){if(!d.every(t=>i.get(t)?.has(e.field)))continue;g.add(n);let r=d.length===1?d[0]:d.join(`, `);t.push({severity:`warning`,rule:lf,where:m,path:h,message:`body writes '${e.field}' to its input, and ${C(r,e.field)} \u2014 `+_f(),hint:w(r,e.field)});continue}if(f.some(t=>t.has(e.field)))continue;g.add(n);let r=d.length===1?`object '${d[0]}'`:`none of its target objects (${d.join(`, `)})`,a=d.length===1?`declares no such field`:`declare that field`;t.push({severity:`warning`,rule:sf,where:m,path:h,message:`body writes '${e.field}' to its input, but ${r} ${a}. The sandboxed script runs clean and the value is copied back onto the record payload unfiltered \u2014 on a SQL driver the stray column then fails the WHOLE write with a driver-level error far from here; on a schemaless driver (memory, MongoDB) it is persisted as an undeclared key (#4271).`,hint:Ef(e.field,Tf(f))})}else{let a=xf(r,e.object);if(!a||a.has(e.field))continue;if(gf.has(e.field)){if(!i.get(e.object)?.has(e.field))continue;g.add(n),t.push({severity:`warning`,rule:lf,where:m,path:h,message:`body calls ctx.api.object('${e.object}').${e.method??`update`}(\u2026) writing '${e.field}', and ${C(e.object,e.field)} \u2014 ${_f()}`,hint:w(e.object,e.field)});continue}g.add(n),t.push({severity:`warning`,rule:sf,where:m,path:h,message:`body calls ctx.api.object('${e.object}').${e.method??`update`}(\u2026) writing '${e.field}', but object '${e.object}' declares no such field. The write-path validator skips the unknown key \u2014 on a SQL driver the whole call then fails with a driver-level error far from here; on a schemaless driver (memory, MongoDB) the stray key is persisted (#4271).`,hint:Ef(e.field,[...a])})}}}}),t}function Tf(e){let t=new Set;for(let n of e)for(let e of n??[])t.add(e);return[...t]}function Ef(e,t){let n=te(Re(e,[...t,...gf]));return(n?`${n} `:``)+`Fix the field name, or declare '${e}' on the object. Only the literal write patterns in HOOK_BODY_WRITE_PATTERNS are checked \u2014 computed keys, spreads and aliased input are not \u2014 and this warning never blocks a build.`}var Df=`action-body-write-unknown-field`,Of=`action-record-write-discarded`,kf=`action-body-source-unparseable`,Af=`action-body-write-unprovisioned-anchor`,jf=[`api-crud-literal`],Mf=[`record-property-assign`],Nf=[{id:`input-property-assign`,reason:"an action's ctx.input is its params bag (`input: unwrapProxyToPlain(actionCtx?.params)`), not a record — `ctx.input.<name>` writes a declared PARAMETER, which object fields cannot judge"},{id:`input-object-assign`,reason:`same surface as input-property-assign — Object.assign(ctx.input, …) targets the params bag`}],Pf=uf.filter(e=>jf.includes(e.id)),Ff=uf.filter(e=>Mf.includes(e.id)),If=new Set(jf),Lf=new Set(Mf),Rf=e=>!!e&&typeof e==`object`&&!Array.isArray(e);function zf(e){return Array.isArray(e)?e.filter(e=>Rf(e)):Rf(e)?Object.entries(e).map(([e,t])=>({name:e,...Rf(t)?t:{}})):[]}function Bf(e,t){return typeof e.object==`string`&&e.object?e.object:typeof e.objectName==`string`&&e.objectName?e.objectName:t}function Vf(e){let t=[],n=new Set,r=(e,r,i)=>{zf(e).forEach((e,a)=>{if((typeof e.type==`string`?e.type:`script`)!==`script`)return;let o=e.body;if(!Rf(o)||o.language!==`js`)return;let s=o.source;if(typeof s!=`string`||s.trim()===``)return;let c=typeof e.name==`string`&&e.name?e.name:`#${a}`,l=`${Bf(e,i)??``}\0${c}\0${s}`;n.has(l)||(n.add(l),t.push({name:c,source:s,path:`${r}[${a}].body.source`}))})};return r(e.actions,`actions`),zf(e.objects).forEach((e,t)=>{let n=typeof e.name==`string`&&e.name?e.name:void 0;r(e.actions,`objects[${t}].actions`,n)}),t}function Hf(e){let t=[];if(!Rf(e))return t;let n=Vf(e);if(n.length===0)return t;let r=null,i=null;for(let a of n){if(!/\bapi\b/.test(a.source)&&!/\brecord\b/.test(a.source))continue;let{writes:n,ctxRecordEscapes:o,parseFailure:s}=Cf(a.source),c=n.filter(e=>If.has(e.patternId)),l=n.filter(e=>Lf.has(e.patternId)),u=`action "${a.name}" \u203A body`;if(s&&t.push({severity:`warning`,rule:kf,where:u,path:a.path,message:`L2 body did not parse (${dn(s)}), so its write set was read from a partially recovered tree \u2014 an undeclared field write in the unread part is not reported.`,hint:fn}),c.length===0&&l.length===0)continue;if(l.length>0&&!o){let e=new Set;for(let n of l)e.has(n.field)||(e.add(n.field),t.push({severity:`warning`,rule:Of,where:u,path:a.path,message:`body assigns ctx.record.${n.field}, but an action's ctx.record is a plain snapshot the runtime never writes back \u2014 the action returns success and the assignment is discarded, whether or not '${n.field}' is a declared field (#4345).`,hint:`To persist it, write through the API: ctx.api.object('<object>').updateById(ctx.recordId, { ${n.field}: \u2026 }). Reported only because ctx.record is never passed anywhere in this body \u2014 mutating the snapshot and then handing it to an API write is a live payload and is not flagged. This warning never blocks a build.`}))}if(c.length===0)continue;r??=bf(e),i??=ct(e);let d=new Set;for(let e of c){if(e.object===void 0)continue;let n=`${e.object}\0${e.field}`;if(d.has(n))continue;let o=xf(r,e.object);if(o&&!o.has(e.field)){if(gf.has(e.field)){if(!i.get(e.object)?.has(e.field))continue;d.add(n),t.push({severity:`warning`,rule:Af,where:u,path:a.path,message:`body calls ctx.api.object('${e.object}').${e.method??`update`}(\u2026) writing '${e.field}', and ${C(e.object,e.field)} \u2014 ${_f()}`,hint:w(e.object,e.field)});continue}d.add(n),t.push({severity:`warning`,rule:Df,where:u,path:a.path,message:`body calls ctx.api.object('${e.object}').${e.method??`update`}(\u2026) writing '${e.field}', but object '${e.object}' declares no such field. The write-path validator skips the unknown key \u2014 on a SQL driver the whole action then fails with a driver-level error far from here; on a schemaless driver (memory, MongoDB) the stray key is persisted (#4271).`,hint:Uf(e.field,[...o])})}}}return t}function Uf(e,t){let n=te(Re(e,[...t,...gf]));return(n?`${n} `:``)+`Fix the field name, or declare '${e}' on the object. Only the literal write patterns in ACTION_BODY_WRITE_PATTERNS are checked \u2014 an action's ctx.input is its params bag, so it is not a record-write surface and is never resolved against fields \u2014 and this warning never blocks a build.`}var Wf=`flow-node-write-unknown-field`,Gf=`flow-node-write-unprovisioned-anchor`,Kf=[`update_record`,`create_record`],qf=[],Jf=e=>!!e&&typeof e==`object`&&!Array.isArray(e);function Yf(e){return Array.isArray(e)?e.filter(e=>Jf(e)):Jf(e)?Object.entries(e).map(([e,t])=>({name:e,...Jf(t)?t:{}})):[]}function Xf(e){let t=e.objectName??e.object;if(!(typeof t!=`string`||t.includes(`{`)))return t||void 0}var Zf=new Set(Kf);function Qf(e){let t=[];if(!Jf(e))return t;let n=Yf(e.flows);if(n.length===0)return t;let r=null,i=null;return n.forEach((n,a)=>{let o=typeof n.name==`string`&&n.name?n.name:`#${a}`;gr(n,`flows[${a}]`).forEach(({node:n,path:a,regionTrail:s},c)=>{if(typeof n.type!=`string`||!Zf.has(n.type))return;let l=Jf(n.config)?n.config:void 0;if(!l)return;let u=l.fields;if(!Jf(u))return;let d=Object.keys(u);if(d.length===0)return;let f=Xf(l);if(!f)return;r??=bf(e),i??=ct(e);let p=xf(r,f);if(!p)return;let m=mr(n,c),h=s?`${s} \u203A node "${m}"`:`node "${m}"`;for(let e of d)if(!p.has(e)){if(gf.has(e)){if(!i.get(f)?.has(e))continue;t.push({severity:`warning`,rule:Gf,where:`flow "${o}" \u203A ${h}`,path:`${a}.config.fields.${e}`,message:`${n.type} writes '${e}', and ${C(f,e)} \u2014 `+_f(),hint:w(f,e)});continue}e.includes(`.`)||t.push({severity:`error`,rule:Wf,where:`flow "${o}" \u203A ${h}`,path:`${a}.config.fields.${e}`,message:`${n.type} writes '${e}', but object '${f}' declares no such field. Nothing between the node and storage removes the key: on a SQL datasource the driver rejects the whole statement ('no such column'), so the correctly named fields in this same payload never land either${n.type===`create_record`?` and the record is never created at all`:``}; on a schemaless one the stray key is persisted into a column no read surface returns.`,hint:$f(e,[...p])})}})}),t}function $f(e,t){let n=te(Re(e,[...t,...gf]));return(n?`${n} `:``)+`Fix the field name, or declare '${e}' on the object. This gates the build rather than warning: the key is literal and so is the object, so unlike the hook/action body rules there is nothing here that could have been mis-extracted.`}var ep=[`flow`],tp=[{name:`validateObjectReferences`,run:Ol},{name:`validateSearchableFields`,runtimeTypes:[`flow`,`view`],run:wi},{name:`validateSortableFields`,runtimeTypes:[`flow`,`view`],run:Zl},{name:`validateActionNameRefs`,run:au},{name:`validatePageFieldBindings`,run:Hi},{name:`validateChartBindings`,run:ju},{name:`validateNavAccess`,run:pd},{name:`validateNavTargetRefs`,run:Il},{name:`validateNavObjectServability`,run:Hl},{name:`validateTranslationReferences`,run:Td},{name:`validateTranslatableSections`,run:Id},{name:`validateFlowTemplatePaths`,run:Nr},{name:`validateAiSurfaceAffinity`,run:Vd},{name:`validateAiToolReferences`,run:Zd},{name:`validateAiAgentAuthoring`,run:rf},{name:`validateHookBodyWrites`,run:wf},{name:`validateActionBodyWrites`,run:Hf},{name:`validateFlowNodeWrites`,run:Qf},{name:`validateReadonlyFlowWrites`,run:zr},{name:`validateReactPageProps`,run:wa}];function np(e,t){let n=[],r=t?.runtimeWriteType;for(let t of tp)r!==void 0&&!(t.runtimeTypes??ep).includes(r)||n.push(...t.run(e));return n}function rp(e){return Array.isArray(e)?e:e&&typeof e==`object`?Object.entries(e).map(([e,t])=>({name:e,...t})):[]}function ip(e){return typeof e==`string`?e:e&&typeof e==`object`&&typeof e.source==`string`?e.source:``}var ap=`daysFromNow|daysAgo|today|now|date|datetime`,op=RegExp(`\\b(?:${ap})\\s*\\(`),sp=RegExp(`(?:(?:${ap})\\s*\\([^)]*\\)\\s*(?:==|!=))|(?:(?:==|!=)\\s*(?:${ap})\\s*\\()`),cp=`flow-time-relative-antipattern`,lp=`flow-date-equality-filter`,up=`flow-phantom-aggregation`,dp=`flow-double-brace-interpolation`,fp=`flow-bare-dollar-reference`,pp=`flow-approval-revise-dead-end`,mp=`flow-approval-revise-unmarked-backedge`,hp=`flow-approval-revise-disabled`,gp=`flow-approval-revise-target-not-service-owned`,_p=`flow-runas-unscoped`,vp=`flow-error-label-not-fault`,yp=`flow-branch-label-unmatched`,bp=`flow-decision-unconditional-branch`,xp=`flow-default-edge-with-condition`,Sp=`flow-multiple-default-edges`,Cp=`flow-inert-node-condition`,wp=`flow-multi-write-unfiltered`,Tp=new Set([`decision`,`assignment`,`loop`,`parallel`,`try_catch`,`create_record`,`update_record`,`delete_record`,`get_record`,`http`,`notify`,`script`,`screen`,`wait`,`subflow`,`map`,`connector_action`,`approval`,`end`]),Ep=new Set([`get_record`,`create_record`,`update_record`,`delete_record`]),Dp="`runAs:'user'` (the default when none is declared)";function Op(e,t){for(let n of o({nodes:e,edges:t}))for(let e of n.nodes)if(Ep.has(typeof e.type==`string`?e.type:``))return{node:e,scope:n.scope};return null}var kp=new Map([[`delete_record`,{verb:`deleted`,engineCall:`driver.deleteMany`,dispatchNote:"the engine's delete-dispatch case-set lists `multi with no predicate at all` as a legal `multi` call"}],[`update_record`,{verb:`overwritten`,engineCall:`driver.updateMany`,dispatchNote:"the engine takes its bulk branch on `options.multi` alone (`Update requires an ID or options.multi=true` is refused only when the declaration is absent)"}]]),Ap=new Set([`error`,`fault`,`failure`,`failed`,`catch`,`on_error`,`onerror`,`on error`]),jp=new Set([`decision`,`approval`,`screen`,`try_catch`]);function Mp(e,t){return e.type===`schedule`||typeof t.triggerType==`string`&&t.triggerType===`schedule`||t.schedule!=null}function Np(e,t){return Mp(e,t)?`schedule`:t.timeRelative!=null||typeof t.triggerType==`string`&&t.triggerType===`time_relative`?`time-relative`:e.type===`api`||typeof t.triggerType==`string`&&t.triggerType===`api`?`api`:null}var Pp=new Set([`aggregations`,`aggregate`,`groupBy`,`rollup`,`having`]);function Fp(e){if(e&&typeof e==`object`&&e.dialect===`cel`){let t=e.source;if(typeof t==`string`&&op.test(t))return t}return null}var Ip=new Set([`$gte`,`$gt`,`$lte`,`$lt`,`$ne`]);function Lp(e,t,n){if(!(!e||typeof e!=`object`||Array.isArray(e)))for(let[r,i]of Object.entries(e)){if(r===`$or`||r===`$and`){if(Array.isArray(i))for(let e of i)Lp(e,t,n);continue}let e=Fp(i),a=e?{op:`==`,src:e}:null;if(!a&&i&&typeof i==`object`&&i.dialect!==`cel`){for(let[e,t]of Object.entries(i))if(!Ip.has(e)){if(e===`$eq`){let e=Fp(t);if(e){a={op:`$eq`,src:e};break}}else if(e===`$in`&&Array.isArray(t)){for(let e of t){let t=Fp(e);if(t){a={op:`$in`,src:t};break}}if(a)break}}}a&&n.push({where:t,message:`filter matches \`${r}\` by ${a.op} against a time value (\`${a.src}\`) \u2014 a date field carries a time component, so exact equality against \`${a.src}\` (re-computed each run) silently matches nothing.`,hint:`Use a one-day window instead: \`${r}: { $gte: daysFromNow(N), $lt: daysFromNow(N+1) }\` (wrap multiple tiers in \`$or\`). The abutting windows tile the timeline so each row matches exactly once. (#1874)`,rule:lp})}}var Rp=/\{\{\s*[\w$][\w$.\s]*\}\}/,zp=/(?:^|[^{])\$[A-Za-z_]\w*\.[A-Za-z_]/,Bp=new Set([`condition`,`expression`,`conditions`]);function Vp(e,t,n){if(!(t&&Bp.has(t))){if(typeof e==`string`){n.push(e);return}if(Array.isArray(e)){for(let r of e)Vp(r,t,n);return}if(e&&typeof e==`object`)for(let[t,r]of Object.entries(e))Vp(r,t,n)}}function Hp(e){return typeof e.label==`string`?e.label.trim().toLowerCase():``}function Up(e,t,n,r){let i=new Map;for(let e of t)typeof e.id==`string`&&i.set(e.id,typeof e.type==`string`?e.type:``);for(let t of n){let n=typeof t.label==`string`?t.label.trim().toLowerCase():``;if(!Ap.has(n)||t.type===`fault`||t.condition)continue;let a=typeof t.source==`string`?t.source:``;jp.has(i.get(a)??``)||r.push({where:`${e} \xB7 edge '${a}' \u2192 '${String(t.target)}'`,message:`edge is labelled '${String(t.label)}' but its type is '${String(t.type??`default`)}', not 'fault' \u2014 so it is an ORDINARY out-edge. Unconditional out-edges all run in parallel, so '${String(t.target)}' executes on every SUCCESSFUL run of '${a}' and never on a failure. The error path the label describes does not exist, and the run still aborts when '${a}' fails.`,hint:"Add `type: 'fault'` to this edge. Only runtime failures route — a guard refusal (a filter token that resolved to nothing, a missing required config key, an unscoped run) stays fatal by design and must be fixed in the metadata, not handled. (#3863)",rule:vp})}}function Wp(e,t,n,r){let i=new Map;for(let e of n){if(e.type===`fault`)continue;let t=typeof e.source==`string`?e.source:``;t&&(i.has(t)||i.set(t,[]),i.get(t).push(e))}for(let[t,n]of i){for(let i of n)i.isDefault===!0&&i.condition&&r.push({where:`${e} \xB7 edge '${t}' \u2192 '${String(i.target)}'`,message:'edge sets `isDefault: true` AND a `condition` — contradictory. `isDefault` means "take this edge when NO sibling condition matched"; a condition makes it an ordinary guarded branch. The condition wins and the default marker routes nothing.',hint:'Drop one: keep `condition` for a guarded branch, or drop it and keep `isDefault: true` for the "otherwise" path. (#4414)',rule:xp,severity:`error`});let i=n.filter(e=>e.isDefault===!0&&!e.condition);i.length>1&&r.push({where:`${e} \xB7 node '${t}'`,message:`${i.length} out-edges are marked \`isDefault: true\` (${i.map(e=>`'${String(e.target)}'`).join(`, `)}) \u2014 a node has at most ONE default path. All of them are traversed together when no condition matches, which is a parallel fan-out, not an "otherwise".`,hint:"Keep `isDefault: true` on the single fallback edge and give the others a `condition` (or leave them unconditional if the fan-out really is intended). (#4414)",rule:Sp})}for(let n of t){let t=typeof n.type==`string`?n.type:``;if(!Tp.has(t))continue;let i=n.config??{};i.condition!=null&&ip(i.condition).trim()!==``&&r.push({where:`${e} \xB7 node '${String(n.id)}' (${t})`,message:"`config.condition` is set but nothing reads it — the key is the trigger gate on a `start` node and is ignored on every other node type, so this predicate never gates anything. (It is still parse-validated at registration, which is why a malformed one is caught and an inert one is not.)",hint:t===`decision`?"Branching lives on the OUT-EDGES: give each branch its own `condition` and mark the fallback `isDefault: true`. If the edges already carry the predicate, delete this copy. (#4414)":"Delete it, or move the predicate to the incoming edge's `condition` if this step was meant to be conditional. (#4414)",rule:Cp})}for(let n of t){if(n.type!==`decision`)continue;let t=typeof n.id==`string`?n.id:``;if(!t)continue;let a=i.get(t)??[];if(a.length===0)continue;let o=n.config??{},s=new Set((Array.isArray(o.conditions)?o.conditions:[]).map(e=>typeof e?.label==`string`?e.label.trim().toLowerCase():``).filter(Boolean)),c=new Set(a.map(Hp).filter(Boolean)),l=[...s].filter(e=>!c.has(e));if(l.length>0&&r.push({where:`${e} \xB7 decision '${t}'`,message:`declares branch label(s) ${l.map(e=>`'${e}'`).join(`, `)} that no out-edge carries \u2014 out-edge labels are [${[...c].map(e=>`'${e}'`).join(`, `)||`none`}]. Traversal cannot honour a label nothing claims, so it falls back to considering EVERY out-edge and the branch the decision computed is ignored.`,hint:"Make an out-edge's `label` match the declared branch exactly, or drop `config.conditions` and branch on the edges instead (`condition` per branch + `isDefault: true` on the fallback) — one mechanism per decision, never both. (#4414)",rule:yp,severity:`error`}),a.filter(e=>e.condition||e.isDefault===!0).length===0)continue;let u=a.filter(e=>!e.condition&&e.isDefault!==!0&&!s.has(Hp(e)));u.length>0&&r.push({where:`${e} \xB7 decision '${t}'`,message:`has guarded out-edge(s) alongside unconditional one(s) (${u.map(e=>`'${String(e.target)}'`).join(`, `)}) \u2014 an unconditional out-edge is traversed on EVERY pass, in parallel with whichever guarded branch matched, so the decision does not actually exclude it. A \`label\` alone does not select a path unless the decision declares a matching \`conditions[].label\`.`,hint:"Mark the fallback `isDefault: true` so it is taken only when no sibling condition matched (BPMN default flow), or give it its own `condition`. (#4414)",rule:bp})}}function Gp(e){return e==null?!0:typeof e!=`object`||Array.isArray(e)?!1:rt(e)===`true`}function Kp(e){return e==null?"no `filter` key":Object.keys(e).length===0?"an EMPTY `filter`":`a \`filter\` that REDUCES TO TRUE (\`${qp(e)}\`)`}function qp(e){try{let t=JSON.stringify(e);return typeof t==`string`?t.length>80?`${t.slice(0,77)}...`:t:typeof e}catch{return typeof e}}function Jp(e,t,n){for(let r of t){let t=typeof r.type==`string`?r.type:``,i=kp.get(t);if(!i)continue;let a=r.config??{};if(a.multi!==!0||!Gp(a.filter))continue;let o=typeof a.objectName==`string`&&a.objectName?a.objectName:`(unnamed object)`,s=Kp(a.filter);n.push({where:`${e} \xB7 node '${String(r.id)}' (${t})`,message:`declares \`multi: true\` with ${s} \u2014 this is a WHOLE-OBJECT write, by declaration: every row of '${o}' is ${i.verb} on every run. The executor forwards the filter as \`where\` (an absent key becomes \`{}\`) plus the bulk intent, ${i.dispatchNote}, and it lands on \`${i.engineCall}\` bounded by nothing \u2014 a filter that reduces to TRUE constrains no row. Nothing refuses it at run time, so the only feedback is the step's \`acted\` row count \u2014 reported AFTER the rows are gone.`,hint:`Write the constraint you mean into \`filter\` (e.g. \`{ status: 'closed' }\` \u2014 see examples/app-showcase \`showcase_inquiry_purge\`, bulk intent bounded by a predicate). If emptying '${o}' really is the intent, keep it: this is a warning, not a gate, and the run-time path stays open. Distinct from the #3810 erased-condition guard, which REFUSES this node at run time when a condition you WROTE interpolated to nothing \u2014 that guard is keyed on "a written condition is gone" and deliberately not on "the filter is empty", which is the fact this rule judges at authoring time. (#5482, #5393)`,rule:wp})}}function Yp(e,t,n,r){let i=t.filter(e=>e.type===Fe);if(i.length===0)return;let a=new Set(t.map(e=>typeof e.id==`string`?e.id:``).filter(Boolean)),o=new Map(t.filter(e=>typeof e.id==`string`).map(e=>[e.id,typeof e.type==`string`?e.type:``])),s=new Map;for(let e of n){let t=typeof e.source==`string`?e.source:``;t&&(s.has(t)||s.set(t,[]),s.get(t).push(e))}for(let t of i){let i=typeof t.id==`string`?t.id:``;if(!i)continue;let c=n.filter(e=>e.source===i&&Hp(e)===`revise`).map(e=>typeof e.target==`string`?e.target:``).filter(e=>e&&a.has(e));if(c.length===0)continue;let l=`${e} \xB7 approval '${i}'`;for(let e of c){let t=o.get(e)??``;t!==`approval_revise`&&r.push({where:l,severity:`error`,message:`has a 'revise' out-edge into node '${e}' of type '${t||`(untyped)`}' \u2014 the revise window must be an '${Ne}' node. Send-back parks the run there while the record is unlocked, and only the approvals service may continue it (submitter-only, audited, and refusing a colliding pending request); \`sendBack\` refuses any other target, so this flow's revise branch cannot run.`,hint:`Set node '${e}' to \`type: '${Ne}'\` (drop any \`waitEventConfig\` \u2014 the window is ended by POST /api/v1/approvals/requests/:id/resubmit, not by a signal). ADR-0044 D3 originally said 'wait' here; its 2026-07-28 amendment reversed that, because a 'wait' is resumable by anyone with the run id (#3823, #3801).`,rule:gp})}(t.config??{}).maxRevisions===0&&r.push({where:l,message:"declares a 'revise' out-edge but `maxRevisions: 0` disables send-back — every revise auto-rejects, so the revise branch never runs.",hint:"Set `maxRevisions` >= 1 to allow N send-backs before auto-reject, or drop the 'revise' edge if send-back isn't intended (ADR-0044).",rule:hp});let u=new Set(c),d=[...c],f=[];for(;d.length;){let e=d.shift();for(let t of s.get(e)??[]){t.target===i&&f.push(t);let e=typeof t.target==`string`?t.target:``;e&&a.has(e)&&!u.has(e)&&(u.add(e),d.push(e))}}f.length===0?r.push({where:l,message:`has a 'revise' out-edge but no path loops back to it — the submitter reworks the record with nowhere to resubmit, so the revise branch dead-ends. (registerFlow accepts this — it's a valid DAG.)`,hint:`Close the loop: the 'revise' edge should reach an '${Ne}' node whose resubmit edge returns to '${i}' marked \`type: 'back'\` (ADR-0044). See examples/app-showcase showcase_budget_approval.`,rule:pp}):f.some(e=>e.type===`back`)||r.push({where:l,message:"has a 'revise' loop that returns to it, but the closing edge isn't declared `type: 'back'` — registerFlow rejects this as an un-declared cycle.",hint:`Mark the resubmit edge (whose target is '${i}') \`type: 'back'\` so cycle validation skips it while it still traverses at runtime; \`maxRevisions\` guards the loop (ADR-0044).`,rule:mp})}}function Xp(e){let t=[];for(let n of rp(e.flows)){let e=typeof n.name==`string`?n.name:`(unnamed flow)`,r=Array.isArray(n.nodes)?n.nodes:[],i=Array.isArray(n.edges)?n.edges:[],a=r.find(e=>e.type===`start`)?.config??{};if((typeof a.triggerType==`string`?a.triggerType:``).startsWith(`record-`)){let n=ip(a.condition).trim();n&&sp.test(n)&&t.push({where:`flow '${e}' \xB7 start condition`,message:`record-change trigger uses a date-EQUALITY time condition (\`${n}\`) \u2014 it only fires if the record happens to be written on that exact day, so unattended "N days before" rules never run.`,hint:"Use a SCHEDULE trigger (daily cron) + a range query instead — e.g. a scheduled flow whose get_record filters `end_date` BETWEEN {TODAY()} and {TODAY()+N}. (#1874)",rule:cp})}let s=typeof n.runAs==`string`?n.runAs:`user`,c=Np(n,a);if(c&&s!==`system`){let n=Op(r,i);if(n){let r=n.scope?`, in ${n.scope},`:``;t.push({where:`flow '${e}' \xB7 runAs`,message:`${c}-triggered flow runs under ${Dp}, but a ${c} run has no trigger user \u2014 so its data node '${n.node.id}' (${n.node.type})${r} has no identity to scope to and will be REFUSED at run time.`,hint:`Declare \`runAs:'system'\` to make the elevation explicit and intended (the run reads/writes every record). A ${c} flow cannot scope to a user \u2014 there is none. (ADR-0049, ADR-0073 D5, #1888, #3760)`,rule:_p,severity:`error`})}}for(let n of o({nodes:r,edges:i})){let r=n.scope?`flow '${e}' \xB7 ${n.scope}`:`flow '${e}'`,i=n.nodes,a=n.edges;for(let e of i){let n=`${r} \xB7 node '${e.id}' (${e.type})`,i=e.config??{};i.filter&&Lp(i.filter,`${n} filter`,t);for(let e of Object.keys(i))Pp.has(e)&&t.push({where:n,message:`node config has \`${e}\` \u2014 the automation engine has no aggregate node, so \`${e}\` is silently ignored and this node computes nothing at runtime.`,hint:"Aggregation belongs in the data layer: use `Field.summary` for a cross-object rollup (sum/count of children), or `Field.formula` for a per-record computed value. (#1870)",rule:up});let a=[];Vp(hr(e.config),void 0,a);for(let e of a)Rp.test(e)&&t.push({where:n,message:`double-brace interpolation \`${e.trim().slice(0,80)}\` \u2014 flow node values use SINGLE braces.`,hint:"Use `{var}` (e.g. `{record.title}`). Double-brace `{{ }}` is the formula/template-field dialect, not flow node values. (#1315)",rule:dp}),zp.test(e)&&t.push({where:n,message:`\`${e.trim().slice(0,80)}\` looks like a reference written as a literal \u2014 a bare \`$ref.field\` is NOT interpolated.`,hint:"Wrap it and bind a variable: `{source.id}` (or `{$User.Id}` for the current user). (#1315)",rule:fp})}Yp(r,i,a,t),Up(r,i,a,t),Wp(r,i,a,t),Jp(r,i,t)}}return t}var Zp=`liveness-dead-property`,Qp=`liveness-experimental-property`;function $p(e){return Array.isArray(e)?e:e&&typeof e==`object`?Object.entries(e).map(([e,t])=>({name:e,...t})):[]}function em(){try{let e=(0,S.createRequire)(import.meta.url).resolve(`@objectstack/spec/package.json`),t=(0,S.join)((0,S.dirname)(e),`liveness`);return(0,S.existsSync)(t)?t:null}catch{return null}}function tm(e,t){let n=new Map,r=(0,S.join)(e,`${t}.json`);if(!(0,S.existsSync)(r))return n;let i;try{i=JSON.parse((0,S.readFileSync)(r,`utf8`))}catch{return n}let a=i.props||{};for(let[e,t]of Object.entries(a)){if(t?.children)for(let[r,i]of Object.entries(t.children))nm(i)&&n.set(`${e}.${r}`,i);nm(t)&&n.set(e,t)}return n}function nm(e){return e?e.authorWarn===!0||e.status===`experimental`:!1}function rm(e){return e==null?!1:typeof e!=`boolean`||e===!0}function im(e){return e.status===`experimental`?{kind:`is experimental — declared but NOT enforced at runtime`,rule:Qp}:{kind:`has no runtime effect (liveness: dead)`,rule:Zp}}function am(e,t,n,r,i){for(let[a,o]of r){let r=a.includes(`.`)?om(t,a):[t[a]];for(let t of r instanceof Array?r:[r]){if(!rm(t))continue;let{kind:r,rule:s}=im(o),c=o.authorHint??o.note??`Remove it — it is declared in the spec but not consumed at runtime.`;i.push({where:n,message:`sets \`${a}\` but this ${e} property ${r}.`,hint:c,rule:s});break}}}function om(e,t){let n=[e];for(let e of t.split(`.`)){let t=[];for(let r of n){if(typeof r!=`object`||!r)continue;let n=Array.isArray(r)?void 0:r[e];if(Array.isArray(r))for(let n of r)n&&typeof n==`object`&&t.push(n[e]);else t.push(n)}n=t}return n.flatMap(e=>Array.isArray(e)?e:[e])}var sm=[{type:`flow`,key:`flows`},{type:`action`,key:`actions`},{type:`agent`,key:`agents`},{type:`tool`,key:`tools`},{type:`skill`,key:`skills`},{type:`dataset`,key:`datasets`},{type:`permission`,key:`permissions`},{type:`hook`,key:`hooks`},{type:`page`,key:`pages`},{type:`view`,key:`views`},{type:`webhook`,key:`webhooks`},{type:`datasource`,key:`datasources`},{type:`app`,key:`apps`},{type:`book`,key:`books`},{type:`job`,key:`jobs`},{type:`email_template`,key:`emailTemplates`},{type:`mapping`,key:`mappings`},{type:`translation`,key:`translations`},{type:`dashboard`,key:`dashboards`}];function cm(e){let t=em();if(!t)return[];let n=[],r=tm(t,`object`),i=tm(t,`field`);for(let t of $p(e.objects)){let e=typeof t.name==`string`?t.name:`(unnamed object)`;if(r.size>0&&am(`object`,t,`object '${e}'`,r,n),i.size>0)for(let r of $p(t.fields))am(`field`,r,`object '${e}' \xB7 field '${typeof r.name==`string`?r.name:`(unnamed field)`}'`,i,n)}for(let{type:r,key:i}of sm){let a=tm(t,r);if(a.size!==0)for(let t of $p(e[i]))am(r,t,`${r} '${typeof t.name==`string`?t.name:typeof t.object==`string`?t.object:`(unnamed ${r})`}'`,a,n)}return n}var lm=`autonumber-references-unknown-field`,um=`autonumber-references-optional-field`,dm=`autonumber-references-self`,fm=`autonumber-unrecognized-token`;function pm(e){return Array.isArray(e)?e:e&&typeof e==`object`?Object.entries(e).map(([e,t])=>({name:e,...t})):[]}function mm(e){let t=[];for(let n of pm(e.objects)){let e=typeof n.name==`string`?n.name:`(unnamed object)`,r=pm(n.fields),a=new Map;for(let e of r)typeof e.name==`string`&&a.set(e.name,{required:e.required===!0});for(let n of r){if(n.type!==`autonumber`)continue;let r=typeof n.name==`string`?n.name:`(unnamed field)`,o=typeof n.autonumberFormat==`string`?n.autonumberFormat:typeof n.format==`string`?n.format:``;if(!o)continue;let s=le(o),c=i(s),l=`object '${e}' \xB7 field '${r}' (autonumber "${o}")`;for(let e of s){if(e.kind!==`literal`)continue;let n=e.text.match(/\{[^{}]*\}/g);if(n)for(let e of n){let n=e.slice(1,-1),r=/^0+$/.test(n);t.push({where:l,message:r?`format has a second sequence slot \`${e}\` \u2014 only the first \`{0..0}\` counts; this one renders literally as "${e}".`:`format has an unrecognized token \`${e}\` \u2014 it is not a counter/date/{field} token, so it renders literally as "${e}" in every record number.`,hint:r?"Use a single `{0000}` slot; fold any second number into a literal or a {field} token.":`Date tokens are case-sensitive and exact: {YYYY} {YY} {MM} {DD} {YYYYMMDD} (no spaces/punctuation inside). For a field value use {field_name}.`,rule:fm,severity:`warning`})}}for(let n of c){if(n===r){t.push({where:l,message:`format interpolates \`{${n}}\` \u2014 its own value, which does not exist yet when the number is generated.`,hint:"Reference a DIFFERENT field that is set before create (e.g. `{plan_no}{000}`), or drop the token.",rule:dm,severity:`error`});continue}let i=a.get(n);i?i.required||t.push({where:l,message:`format interpolates \`{${n}}\`, but '${n}' is optional \u2014 any record left blank fails autonumber generation at create time.`,hint:`Mark '${n}' as \`required: true\` so it is always set before the record number is rendered.`,rule:um,severity:`warning`}):t.push({where:l,message:`format interpolates \`{${n}}\`, but object '${e}' has no field named '${n}' \u2014 generation will always throw.`,hint:`Reference an existing field, or remove the \`{${n}}\` token from the format.`,rule:lm,severity:`error`})}}}return t}function hm(e){return Array.isArray(e)?e:e&&typeof e==`object`?Object.entries(e).map(([e,t])=>({name:e,...t})):[]}var gm=`view-key-collision`,_m=`view-ref-form-target-missing`,vm=`view-ref-form-target-kind`;function ym(e){return{list:e.list,form:e.form,listViews:e.listViews,formViews:e.formViews}}function bm(e){if(typeof e.name==`string`&&e.name)return e.name;if(typeof e.id==`string`&&e.id)return e.id;if(typeof e.object==`string`&&e.object)return e.object;if(typeof e.list?.data?.object==`string`)return e.list.data.object;if(typeof e.form?.data?.object==`string`)return e.form.data.object}function xm(e){let t=[],n=new Map,r=(e,t)=>{let r=n.get(e);r||n.set(e,r=new Set),r.add(t)},i=[];for(let t of hm(e.views)){if(t.viewKind){typeof t.name==`string`&&r(t.name,t.viewKind===`form`?`form`:`list`);continue}if(!b(t))continue;let e=bm(t);e&&i.push({object:e,container:t})}for(let t of hm(e.objects)){let e=typeof t.name==`string`?t.name:void 0;e&&(t.list||t.form||t.listViews||t.formViews)&&i.push({object:e,container:ym(t)})}for(let{object:e,container:n}of i){let{items:i,collisions:a}=de(e,n);for(let e of i)r(e.name,e.viewKind);for(let n of a)t.push({where:`object '${e}' \xB7 view key '${n.key}'`,message:`View key collision: the ${n.viewKind} view '${n.requested}' clashes with another view in the same container and was renamed to '${n.renamedTo}'. Anything referencing '${n.requested}' (a form action target, a navigation viewName) resolves to the OTHER view, not this one.`,hint:`Give the ${n.viewKind} view a unique key \u2014 the default list implicitly claims '<object>.default'. Renaming key '${n.key}' fixes both this collision and any reference that targets it.`,rule:gm,severity:`warning`})}let a=new Set,o=(e,r)=>{if(!e||e.type!==`form`)return;let i=e.target;if(typeof i!=`string`||!i||i.includes("${")||!i.includes(`.`))return;let o=typeof e.name==`string`?e.name:`(unnamed)`,s=`${o}\0${i}`;if(a.has(s))return;a.add(s);let c=r?`action '${o}' on object '${r}'`:`action '${o}'`,l=n.get(i);if(!l){t.push({where:c,message:`Form action target '${i}' does not resolve to any view. A type:'form' action must point at an existing form view; at runtime this opens a blank/broken form.`,hint:`Check for a typo, or a form view renamed by a key collision. Expected a form view named '<object>.<formViewKey>'.`,rule:_m,severity:`warning`});return}if(!l.has(`form`)){let e=[...l].join(`/`);t.push({where:c,message:`Form action target '${i}' resolves to a ${e} view, not a form view. Opening a ${e} view through a form action renders an empty form (and a submit can silently no-op) at runtime.`,hint:`Point target at a form view (viewKind 'form'). If the form view was renamed by a key collision, fix the colliding key so '${i}' names the form again.`,rule:vm,severity:`error`})}};for(let t of hm(e.objects)){let e=typeof t.name==`string`?t.name:void 0;for(let n of hm(t.actions))o(n,e)}for(let t of hm(e.actions))o(t);return t}function Sm(e){return`object "${e?.name}"`}function Cm(e,t,n,r){let i=(typeof t?.name==`string`&&t.name.trim()?`'${t.name.trim()}'`:``)||(r.length>0?`[${r.join(`, `)}]`:`#${n}`);return`${Sm(e)} \xB7 index ${i}`}function wm(e,t){return`${Sm(e)} \xB7 field '${t}'`}var Tm=new Set([`lookup`,`master_detail`]),Em=new Set([`number`,`currency`,`integer`,`decimal`,`percent`,`float`,`double`]),Dm=new Set([`select`,`multiselect`,`radio`,`enum`]),Om=[`name`,`title`,`subject`,`label`,`full_name`,`display_name`,`code`],km=/_(line|lines|line_item|line_items|item|items|detail|details|entry|entries)$/,Am=[`comment`,`attachment`,`note`,`log`,`audit`,`activity`,`activities`,`history`,`event`,`reaction`,`like`,`mention`,`notification`,`message`];function jm(e){return km.test(e)}function Mm(e){let t=e.toLowerCase();return Am.some(e=>t===e||t.endsWith(`_${e}`)||t.endsWith(`_${e}s`))}function Nm(e){return e?Array.isArray(e)?e.filter(e=>e&&e.name!=null).map(e=>({name:String(e.name),def:e})):Object.entries(e).map(([e,t])=>({name:e,def:t})):[]}function Pm(e){return e?.reference||e?.reference_to}var Fm=`unique/double-declaration`,Im=`unique/unscoped-declared-index`,Lm=`unique/legacy-organization-composite`;function Rm(e){let t=e?.tenancy?.tenantField;return typeof t==`string`&&t.trim()?t.trim():`organization_id`}function zm(e){return e===!0||e===`global`||e===`organization`}function Bm(e){return e===`global`?`global`:`organization`}function Vm(e){return e===`organization`?`organization`:`global`}function Hm(e){let t=[];if(!Array.isArray(e)||e.length===0)return t;for(let n=0;n<e.length;n++){let r=e[n];if(!r?.name)continue;let i=Array.isArray(r.indexes)?r.indexes:[];for(let e=0;e<i.length;e++){let a=i[e];if(a?.unique!==!0)continue;let o=Array.isArray(a?.fields)?a.fields.filter(e=>typeof e==`string`):[],s=o.join(`, `),c=typeof a?.name==`string`&&a.name.trim()?` '${a.name.trim()}'`:``;t.push({severity:`warning`,rule:Im,where:Cm(r,a,e,o),message:`"${r.name}" declares index${c} [${s}] with bare \`unique: true\` \u2014 a unique index whose scope is unstated (ADR-0120). Today the bare spelling materializes over exactly its \`fields\`, i.e. installation-wide; an author who meant "unique per organization" gets no per-organization constraint and no error. Protocol 18 rejects this spelling (#5082).`,path:`objects[${n}].indexes[${e}]`,fix:"State the scope: `unique: 'global'` (installation-wide — exactly today's behavior) or `unique: 'organization'` (one holder per organization — the driver prepends the NULL-safe organization key part at registration)."})}}return t}function Um(e){let t=[];if(!Array.isArray(e)||e.length===0)return t;for(let n=0;n<e.length;n++){let r=e[n];if(!r?.name)continue;let i=Array.isArray(r.indexes)?r.indexes:[];if(i.length===0)continue;let a=new Map;for(let e of i){if(!zm(e?.unique))continue;let t=Array.isArray(e?.fields)?e.fields.filter(e=>typeof e==`string`):[];t.length===1&&(a.has(t[0])||a.set(t[0],e))}if(a.size!==0)for(let{name:e,def:i}of Nm(r.fields)){if(!zm(i?.unique))continue;let o=a.get(e);if(!o)continue;let s=Bm(i.unique),c=Vm(o.unique),l=typeof o?.name==`string`&&o.name.trim()?` '${o.name.trim()}'`:``,u=`\`unique: ${typeof i.unique==`string`?`'${i.unique}'`:i.unique}\``,d=`\`unique: ${typeof o.unique==`string`?`'${o.unique}'`:o.unique}\``,f,p;if(s===c){let t=s===`global`?`installation-wide`:`per-organization`;f=`"${r.name}.${e}" declares field-level ${u} AND a single-column unique index${l} (${d}) on the same column. Both ask for the same ${t} boundary \u2014 the same unique index declared twice (ADR-0120 D5b). Redundant, not contradictory: drop one so the intent has a single home.`,p=s===`global`?`Keep ONE spelling of installation-wide uniqueness: \`unique: 'global'\` on '${e}', or the declared index \u2014 not both.`:`Keep ONE spelling of per-organization uniqueness: \`unique: 'organization'\` on '${e}' (preferred), or the declared \`'organization'\` index \u2014 not both.`}else{let t=s===`global`?`field-level ${u}`:`declared index${l} (${d})`,n=s===`global`?`declared index${l} (${d})`:`field-level ${u}`;f=`"${r.name}.${e}" declares an installation-wide unique (${t}) AND a per-organization unique (${n}) on the same column \u2014 the two scopes CONTRADICT (ADR-0120 D5b). The installation-wide index is physically stricter and wins; the per-organization constraint can never be tripped, so one of the two intents you wrote is silently dead.`,p=`Pick ONE scope and say it once: for installation-wide uniqueness keep \`unique: 'global'\` and drop the per-organization declaration; for per-organization uniqueness set \`unique: 'organization'\` (field-level on '${e}', or on the declared index) and drop the installation-wide one.`}t.push({severity:`warning`,rule:Fm,where:wm(r,e),message:f,path:`objects[${n}]`,fix:p})}}return t}function Wm(e){let t=[];if(!Array.isArray(e)||e.length===0)return t;for(let n=0;n<e.length;n++){let r=e[n];if(!r?.name)continue;let i=Rm(r),a=Array.isArray(r.indexes)?r.indexes:[];for(let e=0;e<a.length;e++){let o=a[e];if(!zm(o?.unique)||o.unique===`organization`)continue;let s=Array.isArray(o?.fields)?o.fields.filter(e=>typeof e==`string`):[];if(s.length<2||!s.includes(i))continue;let c=typeof o?.name==`string`&&o.name.trim()?` '${o.name.trim()}'`:``,l=`\`unique: ${typeof o.unique==`string`?`'${o.unique}'`:o.unique}\``,u=s.filter(e=>e!==i);t.push({severity:`warning`,rule:Lm,where:Cm(r,o,e,s),message:`"${r.name}" declares index${c} [${s.join(`, `)}] with ${l} and lists the organization column '${i}' itself \u2014 the hand-written per-organization composite that predates the scope vocabulary (ADR-0120 S6). It reads as "unique per organization" but materializes as a plain composite, and SQL UNIQUE is NULL-distinct: on every row whose '${i}' is NULL it enforces nothing (#5030) \u2014 which on a single-organization deployment is every row.`,path:`objects[${n}].indexes[${e}]`,fix:`State the scope instead: \`unique: 'organization'\` on this index (keep \`fields\` exactly as they are \u2014 the driver makes the listed '${i}' NULL-safe in place rather than prepending a second organization key part). ${u.length>0?`The constraint then really is "one ${u.join(` + `)} per organization". `:``}Opting in is a physical tightening: it surfaces as a \`recreate_index\` drift op gated by the duplicate pre-flight probe (ADR-0120 D4), so pre-existing duplicate NULL-organization rows block it with a report rather than failing a boot. Leaving it as-is stays valid indefinitely and forces no drift.`})}}return t}function Gm(e){let t=[...Hm(e),...Um(e),...Wm(e)];if(!Array.isArray(e)||e.length===0)return t;let n={};for(let t of e)if(t?.name)for(let{name:e,def:r}of Nm(t.fields)){if(!Tm.has(r?.type))continue;let i=Pm(r);i&&(n[i]||(n[i]=[])).push({child:t,fieldName:e,def:r})}for(let r=0;r<e.length;r++){let i=e[r];if(!i?.name)continue;let a=`objects[${r}]`,o=Nm(i.fields),s=!!i.nameField||o.some(e=>Om.includes(e.name));o.length>0&&!s&&t.push({severity:`suggestion`,rule:`object/missing-name-field`,message:`Object "${i.name}" has no nameField and no name-like field \u2014 records will display as raw IDs`,path:`${a}.fields`,fix:"Set `nameField: '<field>'` — ADR-0079's canonical primary-title pointer — to a stored text/autonumber field, or to a formula field with `returnType: 'text'` for a composite title. A `titleFormat` template does NOT count: it is retired (ADR-0079) and render-only, so the server can neither return nor query the title it renders."});for(let{name:e,def:n}of o){if(!n||typeof n!=`object`)continue;let r=`${a}.fields.${e}`,o=n.type;if(Dm.has(o)&&(Array.isArray(n.options)&&n.options.length>0||n.optionsFrom||n.dataSource||n.reference||t.push({severity:`warning`,rule:`field/select-missing-options`,message:`${o} field "${i.name}.${e}" has no options`,path:`${r}.options`})),!Tm.has(o))continue;let s=Pm(n);if(!s){t.push({severity:`error`,rule:`relationship/missing-reference`,message:`${o} field "${i.name}.${e}" is missing a reference target`,path:`${r}.reference`});continue}o===`master_detail`&&(n.required!==!0&&t.push({severity:`warning`,rule:`relationship/master-detail-required`,message:`master_detail "${i.name}.${e}" \u2192 ${s} should be required (a detail record cannot exist without its master)`,path:`${r}.required`,fix:`required: true`}),n.deleteBehavior===void 0&&t.push({severity:`suggestion`,rule:`relationship/delete-behavior`,message:`master_detail "${i.name}.${e}" \u2192 ${s} should declare deleteBehavior (cascade/restrict/set_null)`,path:`${r}.deleteBehavior`,fix:`deleteBehavior: 'cascade'`}),jm(i.name)&&n.inlineEdit!==!0&&t.push({severity:`suggestion`,rule:`relationship/line-items-inline-edit`,message:`"${i.name}" looks like line items of ${s}; consider inlineEdit: true on "${e}" so it is entered inline within the ${s} form`,path:`${r}.inlineEdit`,fix:`inlineEdit: true`})),o===`lookup`&&jm(i.name)&&t.push({severity:`suggestion`,rule:`relationship/line-item-should-be-master-detail`,message:`"${i.name}" looks like line items of ${s} but uses lookup; master_detail gives ownership + cascade + roll-ups`,path:`${r}.type`,fix:`type: 'master_detail'`}),n.inlineEdit===!0&&Mm(i.name)&&t.push({severity:`warning`,rule:`relationship/association-inline-edit`,message:`"${i.name}" is an association (comments/audit/activity), not line items \u2014 inlineEdit clutters the ${s} entry form; surface it as a detail-page related list instead`,path:`${r}.inlineEdit`,fix:`remove inlineEdit (use relatedList on the detail page)`})}let c=n[i.name]||[],l=new Set(o.filter(e=>e.def?.type===`summary`).map(e=>e.def?.summaryOperations?.object||e.def?.reference).filter(Boolean)),u=new Set;for(let{child:e,def:n}of c){if(n?.type!==`master_detail`||!e?.name||u.has(e.name)||l.has(e.name))continue;let r=Nm(e.fields).find(e=>Em.has(e.def?.type));r&&(u.add(e.name),t.push({severity:`suggestion`,rule:`rollup/missing-summary`,message:`"${i.name}" owns "${e.name}" (master_detail) with numeric field "${r.name}" but has no roll-up summary; consider a summary field (count/sum) on ${i.name}`,path:`${a}.fields`,fix:`summary field aggregating ${e.name}.${r.name}`}))}}return t}var Km=[`validate`,`build`,`lint`],qm=[`cli`,`runtime-publish`],X=Km,Z=[`cli`],Q=[`cli`,`runtime-publish`],$=`P2 (#4463): reads a stack-wide collection the per-write snapshot does not carry, so running it now would report the rest of the tenant's metadata as missing rather than judging this write.`,Jm=`Not runtime-safe: parses authored source through typescript/sucrase, the two dependencies the kernel boot path must never load (lazy-deps.test.ts). Studio compiles page source on its own path.`,Ym=`Advisory-tier object rule: it cannot refuse a write, and it is held off the runtime door for advisory VOLUME (~8 findings per object write measured on unswept metadata, rendered in Studio since #4717), not refusal risk. Crossing it is a UX decision with its own card (#4716).`,Xm=`expression-invalid`,Zm=[{name:`validateStackExpressions`,tier:`gating`,input:`parsed`,commands:X,source:`packages/lint/src/validate-expressions.ts`,surfaces:Q,runtimeTypes:[`flow`],run:e=>ln(e).map(e=>({severity:e.severity??`error`,rule:Xm,where:e.where,path:e.where,message:e.message,hint:`source: \`${e.source}\``}))},{name:`validateListViewMode`,tier:`gating`,input:`normalized`,commands:X,source:`packages/lint/src/validate-list-view-mode.ts`,surfaces:Z,surfaceReason:$,run:e=>Hn(e)},{name:`validateFunctionalCompleteness`,tier:`gating`,input:`normalized`,commands:X,source:`packages/lint/src/validate-functional-completeness.ts`,surfaces:Q,runtimeTypes:[`object`],run:e=>Kn(e)},{name:`validateManagedApiMethods`,tier:`gating`,input:`normalized`,commands:X,source:`packages/lint/src/validate-managed-api-methods.ts`,surfaces:Q,runtimeTypes:[`object`],run:e=>Xn(e)},{name:`validateViewContainers`,tier:`gating`,input:`normalized`,commands:X,source:`packages/lint/src/validate-view-containers.ts`,surfaces:Z,surfaceReason:$,run:e=>Wr(e)},{name:`validateWidgetBindings`,tier:`gating`,input:`parsed`,commands:X,source:`packages/lint/src/validate-widget-bindings.ts`,surfaces:Q,runtimeTypes:[`dashboard`],run:e=>Mt(e)},{name:`validateDashboardActionRefs`,tier:`gating`,input:`parsed`,commands:X,source:`packages/lint/src/validate-dashboard-action-refs.ts`,surfaces:Z,surfaceReason:$,run:e=>Rc(e)},{name:`validateFilterTokens`,tier:`gating`,input:`parsed`,commands:X,source:`packages/lint/src/validate-filter-tokens.ts`,surfaces:Z,surfaceReason:$,run:e=>Jc(e)},{name:`validatePresetComparands`,tier:`gating`,input:`parsed`,commands:X,source:`packages/lint/src/validate-preset-comparands.ts`,surfaces:Q,runtimeTypes:[`dashboard`,`view`,`object`,`page`,`flow`],run:e=>sl(e)},{name:`validateEmptyCombinators`,tier:`gating`,input:`parsed`,commands:X,source:`packages/lint/src/validate-empty-combinators.ts`,surfaces:Q,runtimeTypes:[`flow`],run:e=>bl(e)},{name:`validateReferenceIntegrity`,tier:`gating`,input:`parsed`,commands:X,source:`packages/lint/src/reference-integrity-suite.ts`,surfaces:Q,runtimeTypes:[`flow`,`view`],run:(e,t)=>np(e,t)},{name:`validateComponentProps`,tier:`advisory`,input:`normalized`,commands:X,source:`packages/lint/src/validate-component-props.ts`,surfaces:Z,surfaceReason:$,run:e=>xu(e)},{name:`validateResponsiveStyles`,tier:`gating`,input:`parsed`,commands:X,source:`packages/lint/src/validate-responsive-styles.ts`,surfaces:Z,surfaceReason:$,run:e=>si(e)},{name:`validateJsxPages`,tier:`gating`,input:`parsed`,commands:X,source:`packages/lint/src/validate-jsx-pages.ts`,surfaces:Z,surfaceReason:Jm,run:(e,t)=>li(e,t.sduiManifest?{manifest:t.sduiManifest}:{})},{name:`validateReactPages`,tier:`gating`,input:`parsed`,commands:X,source:`packages/lint/src/validate-react-pages.ts`,surfaces:Z,surfaceReason:Jm,run:e=>pi(e)},{name:`validatePageSourceStyling`,tier:`advisory`,input:`parsed`,commands:X,source:`packages/lint/src/validate-page-source-styling.ts`,surfaces:Z,surfaceReason:$,run:e=>Oa(e)},{name:`validateCapabilityReferences`,tier:`advisory`,input:`parsed`,commands:X,source:`packages/lint/src/validate-capability-references.ts`,surfaces:Z,surfaceReason:`P2 (#4463): the ONE rule the runtime universe makes strictly stronger — the advisory hedge ("another installed package may provide it") is decidable against the live capability registry, so it graduates from advisory to gating there rather than merely being ported. That promotion is a severity change on a published rule id and belongs in its own PR, not riding a wiring change.`,run:e=>es(e)},{name:`validateFlowTriggerReadiness`,tier:`gating`,input:`normalized`,commands:X,source:`packages/lint/src/validate-flow-trigger-readiness.ts`,surfaces:Q,runtimeTypes:[`flow`],run:e=>cr(e)},{name:`validateApprovalApprovers`,tier:`gating`,input:`parsed`,commands:X,source:`packages/lint/src/validate-approval-approvers.ts`,surfaces:Q,runtimeTypes:[`flow`],run:e=>vs(e)},{name:`validateRecordTitle`,tier:`advisory`,input:`parsed`,commands:X,source:`packages/lint/src/validate-record-title.ts`,surfaces:Z,surfaceReason:Ym,run:e=>Ma(e)},{name:`validateSemanticRoles`,tier:`advisory`,input:`parsed`,commands:X,source:`packages/lint/src/validate-semantic-roles.ts`,surfaces:Z,surfaceReason:Ym,run:e=>za(e)},{name:`validateFormLayout`,tier:`advisory`,input:`parsed`,commands:X,source:`packages/lint/src/validate-form-layout.ts`,surfaces:Z,surfaceReason:$,run:e=>$a(e)},{name:`validateActionLocations`,tier:`advisory`,input:`parsed`,commands:X,source:`packages/lint/src/validate-action-locations.ts`,surfaces:Z,surfaceReason:$,run:e=>du(e)},{name:`validateSeedReplaySafety`,tier:`advisory`,input:`parsed`,commands:X,source:`packages/lint/src/validate-seed-replay-safety.ts`,surfaces:Z,surfaceReason:$,run:e=>bs(e)},{name:`validateSeedStateMachine`,tier:`advisory`,input:`parsed`,commands:X,source:`packages/lint/src/validate-seed-state-machine.ts`,surfaces:Z,surfaceReason:$,run:e=>ws(e)},{name:`validateVisibilityPredicates`,tier:`gating`,input:`normalized`,commands:X,source:`packages/lint/src/validate-visibility-predicates.ts`,surfaces:Q,runtimeTypes:[`view`],run:e=>Oo(e)},{name:`validatePredicatePathRefs`,tier:`gating`,input:`normalized`,commands:X,source:`packages/lint/src/validate-predicate-path-refs.ts`,surfaces:Q,runtimeTypes:[`view`],run:e=>Yo(e)},{name:`lintFlowPatterns`,tier:`gating`,input:`parsed`,commands:X,source:`packages/lint/src/lint-flow-patterns.ts`,surfaces:Q,runtimeTypes:[`flow`],run:e=>Xp(e).map(e=>({severity:e.severity??`warning`,rule:e.rule,where:e.where,path:e.where,message:e.message,hint:e.hint}))},{name:`lintLivenessProperties`,tier:`advisory`,input:`parsed`,commands:X,source:`packages/lint/src/lint-liveness-properties.ts`,surfaces:Z,surfaceReason:Ym,run:e=>cm(e).map(e=>({severity:`warning`,rule:e.rule,where:e.where,path:e.where,message:e.message,hint:e.hint}))},{name:`lintAutonumberFormats`,tier:`gating`,input:`parsed`,commands:X,source:`packages/lint/src/lint-autonumber-formats.ts`,surfaces:Q,runtimeTypes:[`object`],run:e=>mm(e).map(e=>({severity:e.severity,rule:e.rule,where:e.where,path:e.where,message:e.message,hint:e.hint}))},{name:`lintViewRefs`,tier:`gating`,input:`parsed`,commands:X,source:`packages/lint/src/lint-view-refs.ts`,surfaces:Z,surfaceReason:$,run:e=>xm(e).map(e=>({severity:e.severity,rule:e.rule,where:e.where,path:e.where,message:e.message,hint:e.hint}))},{name:`lintUnscopedDeclaredIndexes`,tier:`advisory`,input:`parsed`,commands:[`validate`,`build`],source:`packages/lint/src/data-model-rules.ts`,surfaces:Z,surfaceReason:Ym,scopeReason:"`os lint` already reports this rule through `lintDataModel`, which calls it directly ahead of R10 in its best-practice sweep — registering it for `lint` as well would report every finding twice. This is coverage recorded, not coverage missing: all three commands report the rule.",run:e=>Hm(Array.isArray(e.objects)?e.objects:[]).map(e=>({severity:e.severity===`suggestion`?`info`:e.severity,rule:e.rule,where:e.where,path:e.path,message:e.message,hint:e.fix??``}))},{name:`lintUniqueDeclarations`,tier:`advisory`,input:`parsed`,commands:[`validate`,`build`],source:`packages/lint/src/data-model-rules.ts`,surfaces:Z,surfaceReason:Ym,scopeReason:"`os lint` already reports this rule through `lintDataModel`, which calls it directly as R10 of its best-practice sweep — registering it for `lint` as well would report every finding twice. This is coverage recorded, not coverage missing: all three commands report the rule.",run:e=>Um(Array.isArray(e.objects)?e.objects:[]).map(e=>({severity:e.severity===`suggestion`?`info`:e.severity,rule:e.rule,where:e.where,path:e.path,message:e.message,hint:e.fix??``}))},{name:`lintLegacyOrganizationComposites`,tier:`advisory`,input:`parsed`,commands:[`validate`,`build`],source:`packages/lint/src/data-model-rules.ts`,surfaces:Z,surfaceReason:Ym,scopeReason:"`os lint` already reports this rule through `lintDataModel`, which calls it directly alongside R10/R11 in its best-practice sweep — registering it for `lint` as well would report every finding twice. This is coverage recorded, not coverage missing: all three commands report the rule.",run:e=>Wm(Array.isArray(e.objects)?e.objects:[]).map(e=>({severity:e.severity===`suggestion`?`info`:e.severity,rule:e.rule,where:e.where,path:e.path,message:e.message,hint:e.fix??``}))},{name:`validateSecurityPosture`,tier:`gating`,input:`parsed`,commands:X,source:`packages/lint/src/validate-security-posture.ts`,surfaces:Q,runtimeTypes:[`seed`,`permission`,`book`,`object`],run:e=>Ys(e)},{name:`validateSecurityRoleWord`,tier:`gating`,input:`parsed`,commands:X,source:`packages/lint/src/validate-security-posture.ts`,surfaces:Z,surfaceReason:`P2 (#4463)/#8310: judges six collections (objects, fields, actions, permission sets, positions, apps — plus books), and the per-write snapshot neither carries nor maps positions/apps. Wiring it for the mapped types alone would enforce one rule id for three of its six collections — the #7220 split (an object named sales_role refused while a position named sales_role walks through). It crosses whole — positions/apps carried, mapped and declared — or stays behind; it stays behind until that wiring exists.`,run:e=>Xs(e)},{name:`validateOrgAxisRedLines`,tier:`gating`,input:`parsed`,commands:X,source:`packages/lint/src/validate-org-axis-red-lines.ts`,surfaces:Z,surfaceReason:$,run:e=>oc(e)},{name:`validateSharingRuleEnforceability`,tier:`gating`,input:`parsed`,commands:X,source:`packages/lint/src/validate-sharing-rule-enforceability.ts`,surfaces:Z,surfaceReason:"P2 (#4463): a sharing rule is not a `flow`, and P1 gates `flow` alone. This entry used to add that the rule reads ONLY `stack.sharingRules[].condition` and needs no other collection, so crossing was a lone `runtimeTypes` edit. #9698 FALSIFIED that: the anchor arm resolves `sharingRules[].object` against `stack.objects` to read the anchor's OWD, so the rule is now cross-collection. `objects` IS carried by the per-write snapshot (`CONTEXT_STACK_KEYS`, #8309), so the remaining gap is unchanged in SHAPE — the gate must accept a `sharing_rule` type and the snapshot must carry `sharingRules`, which it does not — but it is now TWO collections, not one. Crossing with `sharingRules` uncarried would enforce this id for zero of its inputs while the entry claimed the door (#7220). Recorded as pending rather than done, because a rule that has never run at a door should not claim it.",run:e=>yc(e)},{name:`validateRlsPredicateEnforceability`,tier:`gating`,input:`parsed`,commands:X,source:`packages/lint/src/validate-rls-predicate-enforceability.ts`,surfaces:Z,surfaceReason:"The rule reads `stack.permissions[]`, which the per-write snapshot DOES carry since #8309 — the remaining gap is only the declaration: no `runtimeTypes` names `permission` here, and that flip is a rollout decision on #8310's axis, not a wiring fix. Recorded as pending rather than done, because a rule that has never run at a door should not claim it.",run:e=>kc(e)},{name:`validateRuleCompilability`,tier:`gating`,input:`parsed`,commands:X,source:`packages/lint/src/validate-rule-compilability.ts`,surfaces:Q,runtimeTypes:[`object`],run:e=>qu(e)},{name:`validateRuleSchemaFormats`,tier:`gating`,input:`parsed`,commands:X,source:`packages/lint/src/validate-rule-schema-formats.ts`,surfaces:Q,runtimeTypes:[`object`],run:e=>id(e)}];function Qm(e){return Zm.filter(t=>t.commands.includes(e))}function $m(e,t){let n=[],r={sduiManifest:t.sduiManifest};for(let i of Qm(e)){let e=i.input===`normalized`?t.normalized:t.parsed??t.normalized;n.push(...i.run(e,r))}return n}function eh(e){return{errors:e.filter(e=>e.severity===`error`),advisories:e.filter(e=>e.severity!==`error`)}}var th={flow:`flows`,object:`objects`,view:`views`,action:`actions`,page:`pages`,dashboard:`dashboards`,agent:`agents`,hook:`hooks`,seed:`data`,permission:`permissions`,book:`books`};function nh(e,t){if(!t||typeof t.packageId!=`string`||t.packageId===``)return e;let n=new Set([t.packageId,...t.dependencies]);return e.filter(e=>{if(!e||typeof e!=`object`)return!0;let t=e[rh];return typeof t!=`string`||t===``||t===ih||n.has(t)?!0:Hs(e)})}var rh=`_packageId`,ih=`sys_metadata`,ah=[`objects`,`permissions`,`books`,`datasets`];function oh(e){return Zm.filter(t=>t.surfaces.includes(`runtime-publish`)&&(t.runtimeTypes??[]).includes(e))}function sh(){let e=new Set;for(let t of Zm)if(t.surfaces.includes(`runtime-publish`))for(let n of t.runtimeTypes??[])e.add(n);return[...e].sort()}function ch(e){return th[e]??null}var lh=e=>`${e.rule}\0${e.where}\0${e.path}\0${e.message}`;function uh(e){let t=ch(e.type);if(!t||!e.item||typeof e.item!=`object`)return null;let n=e.item,r=typeof n.name==`string`?n.name:void 0,i={};for(let n of ah){let a=e.context?.[n]??[],o=n===`objects`?nh(a,e.packageScope):a;i[n]=n===t?o.filter(e=>!r||e?.name!==r):o}return{baseline:i,candidate:{...i,[t]:[...i[t]??[],n]}}}var dh=[`objects`,`permissions`,`books`],fh=/^[A-Za-z_][A-Za-z0-9_]*$/,ph=/^(objects|permissions|books)\[(\d+)\](.*)$/;function mh(e,t){let n=ph.exec(e);if(!n)return e;let[,r,i,a]=n;if(!dh.includes(r))return e;let o=t[r]?.[Number(i)],s=o&&typeof o==`object`?o.name:void 0;return typeof s!=`string`||!fh.test(s)?e:`${r}.${s}${a}`}function hh(e,t,n){let r=[];for(let i of e)try{r.push(...i.run(t,n))}catch(e){r.push({severity:`warning`,rule:`authoring-rule-threw`,where:i.name,path:i.source,message:`rule ${i.name} threw while judging this write: ${e instanceof Error?e.message:String(e)}`,hint:`This is a bug in the rule, not in the metadata — the write was not blocked by it. Please report it with the body that triggered it.`})}return r}function gh(e){let t=oh(e.type),n={errors:[],advisories:[],rulesRun:[]};if(t.length===0)return n;let r=uh({type:e.type,item:e.item,...e.context===void 0?{}:{context:e.context},...e.packageScope===void 0?{}:{packageScope:e.packageScope}});if(!r)return n;let i={sduiManifest:e.sduiManifest,runtimeWriteType:e.type},a=new Set(hh(t,r.baseline,i).map(lh)),o=hh(t,r.candidate,i).filter(e=>!a.has(lh(e))).map(e=>{let t=mh(e.path,r.candidate);return t===e.path?e:{...e,path:t}});return{errors:o.filter(e=>e.severity===`error`),advisories:o.filter(e=>e.severity!==`error`),rulesRun:t.map(e=>e.name)}}export{kf as ACTION_BODY_SOURCE_UNPARSEABLE,Nf as ACTION_BODY_WRITE_EXCLUSIONS,Pf as ACTION_BODY_WRITE_PATTERNS,jf as ACTION_BODY_WRITE_PATTERN_IDS,Df as ACTION_BODY_WRITE_UNKNOWN_FIELD,Af as ACTION_BODY_WRITE_UNPROVISIONED_ANCHOR,$l as ACTION_NAME_UNDEFINED,ou as ACTION_NO_PLACEMENT,Of as ACTION_RECORD_WRITE_DISCARDED,Ff as ACTION_RECORD_WRITE_PATTERNS,Mf as ACTION_RECORD_WRITE_PATTERN_IDS,Qd as AGENT_AUTHORING_WITHDRAWN,Ld as AI_SKILL_SURFACE_MISMATCH,Hd as AI_SKILL_TOOL_UNRESOLVED,os as APPROVAL_APPROVERS_MAY_RESOLVE_EMPTY,us as APPROVAL_APPROVER_CROSS_ORG_UNSUPPORTED,ts as APPROVAL_APPROVER_NOT_MEMBERSHIP_TIER,ns as APPROVAL_APPROVER_TYPE_DEPRECATED,rs as APPROVAL_APPROVER_TYPE_UNKNOWN,is as APPROVAL_APPROVER_TYPE_UNSUPPORTED,ls as APPROVAL_DECISION_OUTPUTS_RESERVED,as as APPROVAL_ESCALATION_REASSIGN_NO_TARGET,ss as APPROVAL_EXPRESSION_INVALID,cs as APPROVAL_EXPRESSION_NO_EMPTY_POLICY,Km as AUTHORING_COMMANDS,Zm as AUTHORING_RULES,qm as AUTHORING_SURFACES,fm as AUTONUMBER_LITERAL_TOKEN,um as AUTONUMBER_OPTIONAL_FIELD,dm as AUTONUMBER_SELF_REFERENCE,lm as AUTONUMBER_UNKNOWN_FIELD,Xo as CAPABILITY_REFERENCE_UNKNOWN,Tu as CHART_AXIS_NOT_SELECTED,pt as CHART_CONFIG_MISSING,wu as CHART_DATASET_UNKNOWN,Su as CHART_DIMENSION_UNKNOWN,ft as CHART_FIELD_UNKNOWN,Cu as CHART_MEASURE_UNKNOWN,pu as COMPONENT_PROPS_INVALID,fu as COMPONENT_PROPS_UNKNOWN_KEY,jc as DASHBOARD_ACTION_ROUTE_UNRESOLVED,Ac as DASHBOARD_ACTION_TARGET_UNDEFINED,vt as DASHBOARD_FILTER_FIELD_UNKNOWN,yt as DASHBOARD_FILTER_FIELD_UNPROVISIONED,$d as DEFAULT_AGENT_OUTSIDE_ROSTER,Xm as EXPRESSION_INVALID,Pa as FIELD_GROUP_EMPTY,Fa as FIELD_GROUP_SHADOWED,Na as FIELD_GROUP_UNDECLARED,cl as FILTER_EMPTY_COMBINATOR,ll as FILTER_EMPTY_NODE,Yc as FILTER_PRESET_COMPARAND,Wc as FILTER_TOKEN_UNKNOWN,pp as FLOW_APPROVAL_REVISE_DEAD_END,hp as FLOW_APPROVAL_REVISE_DISABLED,gp as FLOW_APPROVAL_REVISE_TARGET_NOT_SERVICE_OWNED,mp as FLOW_APPROVAL_REVISE_UNMARKED_BACKEDGE,fp as FLOW_BARE_DOLLAR_REF,yp as FLOW_BRANCH_LABEL_UNMATCHED,lp as FLOW_DATE_EQUALITY_FILTER,bp as FLOW_DECISION_UNCONDITIONAL_BRANCH,xp as FLOW_DEFAULT_EDGE_WITH_CONDITION,dp as FLOW_DOUBLE_BRACE_INTERP,Qn as FLOW_DRAFT_STATUS_AMBIGUOUS,vp as FLOW_ERROR_LABEL_NOT_FAULT,Cp as FLOW_INERT_NODE_CONDITION,Sp as FLOW_MULTIPLE_DEFAULT_EDGES,wp as FLOW_MULTI_WRITE_UNFILTERED,Wf as FLOW_NODE_WRITE_UNKNOWN_FIELD,Gf as FLOW_NODE_WRITE_UNPROVISIONED_ANCHOR,up as FLOW_PHANTOM_AGGREGATION,_p as FLOW_RUNAS_UNSCOPED,br as FLOW_TEMPLATE_FIELD_UNPROVISIONED,yr as FLOW_TEMPLATE_LOOKUP_TRAVERSAL,vr as FLOW_TEMPLATE_UNKNOWN_FIELD,cp as FLOW_TIME_RELATIVE_ANTIPATTERN,er as FLOW_TIME_RELATIVE_DESCRIPTOR_INVALID,tr as FLOW_TIME_RELATIVE_DESCRIPTOR_UNROUTABLE,$n as FLOW_TRIGGER_UNKNOWN_EVENT,Zn as FLOW_TRIGGER_UNKNOWN_OBJECT,nr as FLOW_TRIGGER_UNROUTABLE,Pr as FLOW_UPDATE_READONLY_FIELD,Fr as FLOW_UPDATE_READONLY_WHEN_FIELD,Kf as FLOW_WRITE_NODE_TYPES,qf as FLOW_WRITE_NODE_TYPES_DEFERRED,Ja as FORM_COLSPAN_ABSOLUTE,qa as FORM_FIELD_UNKNOWN,cf as HOOK_BODY_SOURCE_UNPARSEABLE,ff as HOOK_BODY_WRITE_EXCLUSIONS,uf as HOOK_BODY_WRITE_PATTERNS,df as HOOK_BODY_WRITE_PATTERN_IDS,sf as HOOK_BODY_WRITE_UNKNOWN_FIELD,lf as HOOK_BODY_WRITE_UNPROVISIONED_ANCHOR,Rn as LIST_VIEW_FILTERS_IN_VIEWS_MODE,Zp as LIVENESS_DEAD_PROPERTY,Qp as LIVENESS_EXPERIMENTAL_PROPERTY,qn as MANAGED_API_METHOD_UNAFFORDABLE,$u as MAX_SCHEMA_WALK_DEPTH,ht as MEASURE_AGGREGATE_INCOHERENT,ld as NAV_OBJECT_UNGRANTED,Ll as NAV_OBJECT_UNSERVABLE,kl as NAV_TARGET_UNRESOLVED,Nt as NULL_GUARD_HINT,Sl as OBJECT_REFERENCE_UNKNOWN,Cl as OBJECT_REFERENCE_UNREGISTERED_PLATFORM,vn as OPEN_VOCABULARY_PROBES,Qs as ORG_AXIS_CROSS_ORG_BU_GRANT,Zs as ORG_AXIS_PERMISSION_INHERITANCE,ji as PAGE_FIELD_UNKNOWN,Mi as PAGE_FIELD_UNPROVISIONED,Ta as PAGE_SOURCE_CLASSNAME,fn as PARSE_FAILURE_HINT,ko as PREDICATE_PATH_UNRESOLVED,Ao as PREDICATE_PATH_UNROOTED,jo as PREDICATE_RHS_PATH_SHAPED,yn as PRE_SEAL_PHASES,ba as REACT_BLOCK_NEEDS_RECORD_CONTEXT,aa as REACT_CHART_AGGREGATE_INVALID,oa as REACT_CHART_AXIS_UNKNOWN,sa as REACT_CHART_DRILLDOWN_INVALID,ra as REACT_CHART_FIELD_UNKNOWN,ia as REACT_CHART_FIELD_UNPROVISIONED,na as REACT_PAGE_SOURCE_UNPARSEABLE,tp as REFERENCE_INTEGRITY_RULES,Sc as RLS_PREDICATE_OVER_BUDGET,bc as RLS_PREDICATE_UNENFORCEABLE,xc as RLS_PREDICATE_UNPARSEABLE,Pu as RUNTIME_AJV_OPTIONS,bn as SEAL_MARKERS,mi as SEARCHABLE_FIELD_UNKNOWN,gi as SEARCHABLE_FIELD_UNPROVISIONED,hi as SEARCHABLE_FIELD_UNSEARCHABLE,ks as SECURITY_ANCHOR_HIGH_PRIVILEGE,js as SECURITY_BOOK_AUDIENCE_UNKNOWN_SET,Ls as SECURITY_CBP_NO_RELATION,Is as SECURITY_DELEGATION_MISSING_REASON,Ds as SECURITY_EXTERNAL_WIDER,Ps as SECURITY_FLS_UNQUALIFIED_KEY,Fs as SECURITY_GRANT_EXPIRED_AT_AUTHORING,Ns as SECURITY_MASTER_DETAIL_UNGRANTED,Es as SECURITY_OWD_ALIAS,Ts as SECURITY_OWD_UNSET,Ms as SECURITY_PRIVATE_NO_READSCOPE,As as SECURITY_ROLE_WORD,Os as SECURITY_WILDCARD_VAMA,ys as SEED_INSERT_MODE_DUPLICATES_ON_REPLAY,xs as SEED_VALUE_OUTSIDE_STATE_MACHINE,Ia as SEMANTIC_ROLE_FIELD_UNKNOWN,La as SEMANTIC_ROLE_FIELD_UNPROVISIONED,uc as SHARING_RULE_OBJECT_CONTROLLED_BY_PARENT,lc as SHARING_RULE_OBJECT_NOT_SHAREABLE,cc as SHARING_RULE_RUNTIME_VARIABLE_CONDITION,sc as SHARING_RULE_UNLOWERABLE_CONDITION,Ul as SORT_FIELD_UNKNOWN,Gl as SORT_FIELD_UNPROVISIONED,Wl as SORT_FIELD_UNSORTABLE,hn as STARTUP_OPEN_VOCABULARY_VERDICT,_n as STARTUP_SOURCE_UNPARSEABLE,gn as STARTUP_VERDICT_ASSERTIVE_WORDING,En as STARTUP_VERDICT_HINT,Kr as STYLE_CLASSNAME_TAILWIND,Gr as STYLE_NODE_MISSING_ID,qr as STYLE_RESPONSIVE_NO_BASE,Jr as STYLE_UNKNOWN_CSS_PROPERTY,Yr as STYLE_UNKNOWN_TOKEN,mt as TABLE_COUNT_ONLY,ka as TITLE_FORMAT_RETIRED,Aa as TITLE_UNRESOLVABLE,hd as TRANSLATION_OPTION_KEY_UNKNOWN,Od as TRANSLATION_SECTION_NAME_MISSING,md as TRANSLATION_TARGET_UNKNOWN,Fm as UNIQUE_DOUBLE_DECLARATION,Lm as UNIQUE_LEGACY_ORGANIZATION_COMPOSITE,Im as UNIQUE_UNSCOPED_DECLARED_INDEX,Mu as VALIDATION_RULE_REGEX_UNCOMPILABLE,Nu as VALIDATION_RULE_SCHEMA_UNCOMPILABLE,Ju as VALIDATION_RULE_SCHEMA_UNKNOWN_FORMAT,Br as VIEW_CONTAINER_SHAPE,gm as VIEW_KEY_COLLISION,vm as VIEW_REF_FORM_TARGET_KIND,_m as VIEW_REF_FORM_TARGET_MISSING,co as VISIBILITY_BARE_IDENTIFIER,uo as VISIBILITY_PREDICATE_OVER_BUDGET,lo as VISIBILITY_PREDICATE_SYNTAX,so as VISIBILITY_ROOT_MISLAYERED,lt as WIDGET_DATASET_UNKNOWN,ut as WIDGET_DIMENSION_UNKNOWN,gt as WIDGET_LEGACY_ANALYTICS_SHAPE,_t as WIDGET_LEGACY_ANALYTICS_UNRENDERABLE,dt as WIDGET_MEASURE_UNKNOWN,Qm as authoringRulesFor,od as buildAccessMatrix,uh as buildRuntimeWriteSnapshots,Xl as checkSortDeclaration,dn as describeParseFailure,cd as diffAccessMatrix,Cf as extractHookBodyWriteSet,Sf as extractHookBodyWrites,Ln as findStartupRegistryVerdicts,Kt as findUnguardedNullableOperands,ki as isSourceAuthoredPage,mm as lintAutonumberFormats,Gm as lintDataModel,Xp as lintFlowPatterns,Wm as lintLegacyOrganizationComposites,cm as lintLivenessProperties,Um as lintUniqueDeclarations,Hm as lintUnscopedDeclaredIndexes,xm as lintViewRefs,nh as narrowObjectsToPackageClosure,rd as nearestRegisteredFormat,Jt as nullGuardMessage,$m as runAuthoringRules,gh as runRuntimeAuthoringRules,oh as runtimeAuthoringRulesFor,sh as runtimeGatedTypes,eh as splitBySeverity,ch as stackKeyForType,Hf as validateActionBodyWrites,du as validateActionLocations,au as validateActionNameRefs,rf as validateAiAgentAuthoring,Vd as validateAiSurfaceAffinity,Zd as validateAiToolReferences,vs as validateApprovalApprovers,es as validateCapabilityReferences,ju as validateChartBindings,xu as validateComponentProps,Rc as validateDashboardActionRefs,bl as validateEmptyCombinators,Jc as validateFilterTokens,Qf as validateFlowNodeWrites,Nr as validateFlowTemplatePaths,cr as validateFlowTriggerReadiness,$a as validateFormLayout,Kn as validateFunctionalCompleteness,wf as validateHookBodyWrites,li as validateJsxPages,Hn as validateListViewMode,Xn as validateManagedApiMethods,pd as validateNavAccess,Hl as validateNavObjectServability,Il as validateNavTargetRefs,Ol as validateObjectReferences,oc as validateOrgAxisRedLines,Hi as validatePageFieldBindings,Oa as validatePageSourceStyling,Yo as validatePredicatePathRefs,sl as validatePresetComparands,wa as validateReactPageProps,pi as validateReactPages,zr as validateReadonlyFlowWrites,Ma as validateRecordTitle,np as validateReferenceIntegrity,si as validateResponsiveStyles,kc as validateRlsPredicateEnforceability,qu as validateRuleCompilability,id as validateRuleSchemaFormats,wi as validateSearchableFields,Ys as validateSecurityPosture,Xs as validateSecurityRoleWord,bs as validateSeedReplaySafety,ws as validateSeedStateMachine,za as validateSemanticRoles,yc as validateSharingRuleEnforceability,Zl as validateSortableFields,ln as validateStackExpressions,Id as validateTranslatableSections,Td as validateTranslationReferences,Wr as validateViewContainers,Oo as validateVisibilityPredicates,Mt as validateWidgetBindings,Ai as walkPageComponents};