@hotmeshio/long-tail 0.24.1 → 0.25.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 (294) hide show
  1. package/build/api/escalations/accumulate.js +8 -4
  2. package/build/api/escalations/metadata.js +4 -3
  3. package/build/api/escalations/related.d.ts +1 -1
  4. package/build/api/escalations/related.js +28 -18
  5. package/build/lib/db/schemas/040_oauth_client_consent.sql +15 -0
  6. package/build/modules/config.d.ts +4 -0
  7. package/build/modules/config.js +4 -0
  8. package/build/modules/maintenance.d.ts +1 -1
  9. package/build/modules/maintenance.js +1 -1
  10. package/build/services/auth/oauth-server/index.d.ts +1 -1
  11. package/build/services/auth/oauth-server/index.js +2 -1
  12. package/build/services/auth/oauth-server/sql.d.ts +7 -4
  13. package/build/services/auth/oauth-server/sql.js +10 -4
  14. package/build/services/auth/oauth-server/store.d.ts +8 -1
  15. package/build/services/auth/oauth-server/store.js +31 -2
  16. package/build/services/escalation/accumulate.d.ts +3 -1
  17. package/build/services/escalation/facet-sql.js +4 -2
  18. package/build/services/escalation/index.d.ts +1 -0
  19. package/build/services/escalation/index.js +4 -1
  20. package/build/services/escalation/related-extremes.d.ts +17 -0
  21. package/build/services/escalation/related-extremes.js +65 -0
  22. package/build/services/escalation/related.d.ts +4 -0
  23. package/build/services/escalation/related.js +2 -0
  24. package/build/services/escalation/resolver-validation.js +7 -0
  25. package/build/services/escalation/roster.d.ts +13 -0
  26. package/build/services/escalation/roster.js +37 -0
  27. package/build/services/escalation/submit-guard.d.ts +3 -0
  28. package/build/services/escalation/submit-guard.js +21 -2
  29. package/build/services/maintenance/index.js +1 -1
  30. package/build/services/mcp/server-tools.js +1 -1
  31. package/build/shared/form-validation/display-only-widgets.d.ts +1 -0
  32. package/build/shared/form-validation/display-only-widgets.js +1 -0
  33. package/build/shared/form-validation/index.d.ts +1 -0
  34. package/build/shared/form-validation/index.js +1 -0
  35. package/build/shared/form-validation/validate-resolver-payload.d.ts +1 -0
  36. package/build/shared/form-validation/validate-resolver-payload.js +2 -1
  37. package/build/shared/form-validation/x-lt-help.d.ts +1 -1
  38. package/build/shared/form-validation/x-lt-help.js +2 -1
  39. package/build/shared/form-validation/x-lt-roster.d.ts +92 -0
  40. package/build/shared/form-validation/x-lt-roster.js +234 -0
  41. package/build/shared/form-validation/x-lt-show-if.d.ts +8 -0
  42. package/build/shared/form-validation/x-lt-show-if.js +13 -0
  43. package/build/shared/form-validation/x-lt-submit-guard.d.ts +14 -1
  44. package/build/shared/form-validation/x-lt-submit-guard.js +4 -1
  45. package/build/shared/list-schema/aggregate.d.ts +19 -0
  46. package/build/shared/list-schema/aggregate.js +66 -0
  47. package/build/shared/list-schema/index.d.ts +2 -0
  48. package/build/shared/list-schema/index.js +7 -1
  49. package/build/shared/list-schema/types.d.ts +15 -2
  50. package/build/shared/list-schema/types.js +6 -1
  51. package/build/shared/list-schema/validate.js +28 -2
  52. package/build/tsconfig.tsbuildinfo +1 -1
  53. package/dashboard/dist/assets/{AdminDashboard-B3mkMIOT.js → AdminDashboard-DWVRAu63.js} +2 -2
  54. package/dashboard/dist/assets/{AdminDashboard-B3mkMIOT.js.map → AdminDashboard-DWVRAu63.js.map} +1 -1
  55. package/dashboard/dist/assets/{AgentConfigPage-CQj2B678.js → AgentConfigPage-Exjtjbvp.js} +6 -6
  56. package/dashboard/dist/assets/{AgentConfigPage-CQj2B678.js.map → AgentConfigPage-Exjtjbvp.js.map} +1 -1
  57. package/dashboard/dist/assets/{AgentDetailPage-CzrD8JJI.js → AgentDetailPage-nDbZo6RB.js} +3 -3
  58. package/dashboard/dist/assets/{AgentDetailPage-CzrD8JJI.js.map → AgentDetailPage-nDbZo6RB.js.map} +1 -1
  59. package/dashboard/dist/assets/{AgentsPage-jg2OFwyW.js → AgentsPage-Dsk9iHps.js} +2 -2
  60. package/dashboard/dist/assets/{AgentsPage-jg2OFwyW.js.map → AgentsPage-Dsk9iHps.js.map} +1 -1
  61. package/dashboard/dist/assets/AvailableEscalationsPage-D1mCqj8Z.js +2 -0
  62. package/dashboard/dist/assets/{AvailableEscalationsPage-IS28XBRe.js.map → AvailableEscalationsPage-D1mCqj8Z.js.map} +1 -1
  63. package/dashboard/dist/assets/{BotPicker-DvEJFpwS.js → BotPicker-u5760MWZ.js} +2 -2
  64. package/dashboard/dist/assets/{BotPicker-DvEJFpwS.js.map → BotPicker-u5760MWZ.js.map} +1 -1
  65. package/dashboard/dist/assets/{BulkAssignModal-BoQCi-YC.js → BulkAssignModal-CtISXXmW.js} +2 -2
  66. package/dashboard/dist/assets/{BulkAssignModal-BoQCi-YC.js.map → BulkAssignModal-CtISXXmW.js.map} +1 -1
  67. package/dashboard/dist/assets/{CapabilitiesPage-kwlrcb_t.js → CapabilitiesPage-BKIlrQfU.js} +2 -2
  68. package/dashboard/dist/assets/{CapabilitiesPage-kwlrcb_t.js.map → CapabilitiesPage-BKIlrQfU.js.map} +1 -1
  69. package/dashboard/dist/assets/{CollapsibleSection-UMIV4KIj.js → CollapsibleSection-DlBVTFqc.js} +2 -2
  70. package/dashboard/dist/assets/{CollapsibleSection-UMIV4KIj.js.map → CollapsibleSection-DlBVTFqc.js.map} +1 -1
  71. package/dashboard/dist/assets/{ConfirmDeleteModal-C5puwMg7.js → ConfirmDeleteModal-Pabkchg_.js} +2 -2
  72. package/dashboard/dist/assets/{ConfirmDeleteModal-C5puwMg7.js.map → ConfirmDeleteModal-Pabkchg_.js.map} +1 -1
  73. package/dashboard/dist/assets/{ConnectedAppsPage-drZa65kP.js → ConnectedAppsPage-DG2YZGN3.js} +2 -2
  74. package/dashboard/dist/assets/{ConnectedAppsPage-drZa65kP.js.map → ConnectedAppsPage-DG2YZGN3.js.map} +1 -1
  75. package/dashboard/dist/assets/CountdownTimer-5t8S2qMi.js +2 -0
  76. package/dashboard/dist/assets/CountdownTimer-5t8S2qMi.js.map +1 -0
  77. package/dashboard/dist/assets/{CredentialsPage-CaFQ6vLb.js → CredentialsPage-CPVbYQow.js} +2 -2
  78. package/dashboard/dist/assets/{CredentialsPage-CaFQ6vLb.js.map → CredentialsPage-CPVbYQow.js.map} +1 -1
  79. package/dashboard/dist/assets/{CronLabel-Co5j7tzW.js → CronLabel-C7UbTrO-.js} +2 -2
  80. package/dashboard/dist/assets/{CronLabel-Co5j7tzW.js.map → CronLabel-C7UbTrO-.js.map} +1 -1
  81. package/dashboard/dist/assets/{DropZone-B1Tdfddc.js → DropZone-DCZpORx-.js} +2 -2
  82. package/dashboard/dist/assets/{DropZone-B1Tdfddc.js.map → DropZone-DCZpORx-.js.map} +1 -1
  83. package/dashboard/dist/assets/{ElapsedCell-WJyE9G0T.js → ElapsedCell-Yz7-LbtE.js} +2 -2
  84. package/dashboard/dist/assets/{ElapsedCell-WJyE9G0T.js.map → ElapsedCell-Yz7-LbtE.js.map} +1 -1
  85. package/dashboard/dist/assets/{EntityTimelinePanel-CDFFfX9d.js → EntityTimelinePanel-xgPRdKEq.js} +2 -2
  86. package/dashboard/dist/assets/{EntityTimelinePanel-CDFFfX9d.js.map → EntityTimelinePanel-xgPRdKEq.js.map} +1 -1
  87. package/dashboard/dist/assets/{EscalationListSchemaPage-CMrUlaKI.js → EscalationListSchemaPage-CqCd-y6B.js} +3 -3
  88. package/dashboard/dist/assets/{EscalationListSchemaPage-CMrUlaKI.js.map → EscalationListSchemaPage-CqCd-y6B.js.map} +1 -1
  89. package/dashboard/dist/assets/{EscalationSchemaPage-Dx2Lyfrz.js → EscalationSchemaPage-D8YVQNph.js} +3 -3
  90. package/dashboard/dist/assets/{EscalationSchemaPage-Dx2Lyfrz.js.map → EscalationSchemaPage-D8YVQNph.js.map} +1 -1
  91. package/dashboard/dist/assets/EscalationTimeline-D6jrDcBb.js +2 -0
  92. package/dashboard/dist/assets/{EscalationTimeline-d3nvshOk.js.map → EscalationTimeline-D6jrDcBb.js.map} +1 -1
  93. package/dashboard/dist/assets/{EscalationTitleSelect-DWQieOM9.js → EscalationTitleSelect-CGGT-QTu.js} +2 -2
  94. package/dashboard/dist/assets/{EscalationTitleSelect-DWQieOM9.js.map → EscalationTitleSelect-CGGT-QTu.js.map} +1 -1
  95. package/dashboard/dist/assets/{EscalationsOverview-BX8Cpi0X.js → EscalationsOverview-B7O4ttP4.js} +2 -2
  96. package/dashboard/dist/assets/{EscalationsOverview-BX8Cpi0X.js.map → EscalationsOverview-B7O4ttP4.js.map} +1 -1
  97. package/dashboard/dist/assets/{EventTable-D1-ITVXS.js → EventTable-DJniXnhe.js} +2 -2
  98. package/dashboard/dist/assets/{EventTable-D1-ITVXS.js.map → EventTable-DJniXnhe.js.map} +1 -1
  99. package/dashboard/dist/assets/{FilterBar-ABC9ctin.js → FilterBar-f-LEKcHI.js} +2 -2
  100. package/dashboard/dist/assets/{FilterBar-ABC9ctin.js.map → FilterBar-f-LEKcHI.js.map} +1 -1
  101. package/dashboard/dist/assets/{FormattedValue-k27T4bG7.js → FormattedValue-CUtv1g3k.js} +2 -2
  102. package/dashboard/dist/assets/{FormattedValue-k27T4bG7.js.map → FormattedValue-CUtv1g3k.js.map} +1 -1
  103. package/dashboard/dist/assets/{GraphInvokePage-DKUErxWc.js → GraphInvokePage-CR0MtYv8.js} +2 -2
  104. package/dashboard/dist/assets/{GraphInvokePage-DKUErxWc.js.map → GraphInvokePage-CR0MtYv8.js.map} +1 -1
  105. package/dashboard/dist/assets/{HomePage-C6u9dIpR.js → HomePage-HVw7T5ER.js} +2 -2
  106. package/dashboard/dist/assets/{HomePage-C6u9dIpR.js.map → HomePage-HVw7T5ER.js.map} +1 -1
  107. package/dashboard/dist/assets/{ListToolbar-gA5rFzkz.js → ListToolbar-CTGK5BXW.js} +2 -2
  108. package/dashboard/dist/assets/{ListToolbar-gA5rFzkz.js.map → ListToolbar-CTGK5BXW.js.map} +1 -1
  109. package/dashboard/dist/assets/{McpOverview-BOPo3J_i.js → McpOverview-B2bbKKu2.js} +2 -2
  110. package/dashboard/dist/assets/{McpOverview-BOPo3J_i.js.map → McpOverview-B2bbKKu2.js.map} +1 -1
  111. package/dashboard/dist/assets/{McpQueryDetailPage-BRVVi0Zh.js → McpQueryDetailPage-DgLxwwJy.js} +2 -2
  112. package/dashboard/dist/assets/{McpQueryDetailPage-BRVVi0Zh.js.map → McpQueryDetailPage-DgLxwwJy.js.map} +1 -1
  113. package/dashboard/dist/assets/{McpQueryPage-Dmbb6SAc.js → McpQueryPage-CSkczeJP.js} +2 -2
  114. package/dashboard/dist/assets/{McpQueryPage-Dmbb6SAc.js.map → McpQueryPage-CSkczeJP.js.map} +1 -1
  115. package/dashboard/dist/assets/McpRunDetailPage-CrUsDPRD.js +2 -0
  116. package/dashboard/dist/assets/{McpRunDetailPage-bMXNO-6V.js.map → McpRunDetailPage-CrUsDPRD.js.map} +1 -1
  117. package/dashboard/dist/assets/{McpRunsPage-Bi9AMWja.js → McpRunsPage-twxFdTtJ.js} +2 -2
  118. package/dashboard/dist/assets/{McpRunsPage-Bi9AMWja.js.map → McpRunsPage-twxFdTtJ.js.map} +1 -1
  119. package/dashboard/dist/assets/{NamespacePill-DwM5pNA4.js → NamespacePill-CSZT2fA4.js} +2 -2
  120. package/dashboard/dist/assets/{NamespacePill-DwM5pNA4.js.map → NamespacePill-CSZT2fA4.js.map} +1 -1
  121. package/dashboard/dist/assets/{OperationsPage-CvR74ZUJ.js → OperationsPage-gOVMrL_a.js} +3 -3
  122. package/dashboard/dist/assets/{OperationsPage-CvR74ZUJ.js.map → OperationsPage-gOVMrL_a.js.map} +1 -1
  123. package/dashboard/dist/assets/OperatorDashboard-BoeZIyup.js +2 -0
  124. package/dashboard/dist/assets/{OperatorDashboard-DctmZw10.js.map → OperatorDashboard-BoeZIyup.js.map} +1 -1
  125. package/dashboard/dist/assets/{PageHeader-CMd3f4bz.js → PageHeader-C4z1ExF7.js} +2 -2
  126. package/dashboard/dist/assets/{PageHeader-CMd3f4bz.js.map → PageHeader-C4z1ExF7.js.map} +1 -1
  127. package/dashboard/dist/assets/{PageHeaderWithStats-DHj8Mqox.js → PageHeaderWithStats-B_f_Sz_Q.js} +2 -2
  128. package/dashboard/dist/assets/{PageHeaderWithStats-DHj8Mqox.js.map → PageHeaderWithStats-B_f_Sz_Q.js.map} +1 -1
  129. package/dashboard/dist/assets/{PersonaDetailPage-Ubqm2rQH.js → PersonaDetailPage-CDktk1mi.js} +2 -2
  130. package/dashboard/dist/assets/{PersonaDetailPage-Ubqm2rQH.js.map → PersonaDetailPage-CDktk1mi.js.map} +1 -1
  131. package/dashboard/dist/assets/{PersonasPage-BpFL2rpo.js → PersonasPage-Bs097x07.js} +2 -2
  132. package/dashboard/dist/assets/{PersonasPage-BpFL2rpo.js.map → PersonasPage-Bs097x07.js.map} +1 -1
  133. package/dashboard/dist/assets/PortalPage-DjfjerpF.js +2 -0
  134. package/dashboard/dist/assets/{PortalPage-Dfc_Q02R.js.map → PortalPage-DjfjerpF.js.map} +1 -1
  135. package/dashboard/dist/assets/{ProcessDetailPage-liJspvQh.js → ProcessDetailPage-B30RatjD.js} +2 -2
  136. package/dashboard/dist/assets/{ProcessDetailPage-liJspvQh.js.map → ProcessDetailPage-B30RatjD.js.map} +1 -1
  137. package/dashboard/dist/assets/{ProcessesListPage-C3OM5ZUy.js → ProcessesListPage-DrvjzgWT.js} +2 -2
  138. package/dashboard/dist/assets/{ProcessesListPage-C3OM5ZUy.js.map → ProcessesListPage-DrvjzgWT.js.map} +1 -1
  139. package/dashboard/dist/assets/ResolverForm-Bl8Pibyz.js +8 -0
  140. package/dashboard/dist/assets/ResolverForm-Bl8Pibyz.js.map +1 -0
  141. package/dashboard/dist/assets/{RoleDetailPage-CrlYCh-R.js → RoleDetailPage-ClYgn-3d.js} +3 -3
  142. package/dashboard/dist/assets/{RoleDetailPage-CrlYCh-R.js.map → RoleDetailPage-ClYgn-3d.js.map} +1 -1
  143. package/dashboard/dist/assets/{RolePill-Di2CAHuD.js → RolePill-Bw_n7EpR.js} +2 -2
  144. package/dashboard/dist/assets/{RolePill-Di2CAHuD.js.map → RolePill-Bw_n7EpR.js.map} +1 -1
  145. package/dashboard/dist/assets/{RolesPage-BaazL_pt.js → RolesPage-B_3qWsvQ.js} +2 -2
  146. package/dashboard/dist/assets/{RolesPage-BaazL_pt.js.map → RolesPage-B_3qWsvQ.js.map} +1 -1
  147. package/dashboard/dist/assets/{RunAsSelector-DxuV0fa1.js → RunAsSelector-CbJT50Hp.js} +2 -2
  148. package/dashboard/dist/assets/{RunAsSelector-DxuV0fa1.js.map → RunAsSelector-CbJT50Hp.js.map} +1 -1
  149. package/dashboard/dist/assets/{ScanCodesPage-C0mvmYTq.js → ScanCodesPage-CIIDuh8w.js} +2 -2
  150. package/dashboard/dist/assets/{ScanCodesPage-C0mvmYTq.js.map → ScanCodesPage-CIIDuh8w.js.map} +1 -1
  151. package/dashboard/dist/assets/{ScanSchemeDetailPage-CiJgt5dZ.js → ScanSchemeDetailPage-Bd3P3eyh.js} +2 -2
  152. package/dashboard/dist/assets/{ScanSchemeDetailPage-CiJgt5dZ.js.map → ScanSchemeDetailPage-Bd3P3eyh.js.map} +1 -1
  153. package/dashboard/dist/assets/ScanStationPage-BiO34nov.js +2 -0
  154. package/dashboard/dist/assets/ScanStationPage-BiO34nov.js.map +1 -0
  155. package/dashboard/dist/assets/{ScopeBadge-CSItPVOH.js → ScopeBadge-CKgfwTy3.js} +2 -2
  156. package/dashboard/dist/assets/{ScopeBadge-CSItPVOH.js.map → ScopeBadge-CKgfwTy3.js.map} +1 -1
  157. package/dashboard/dist/assets/{StickyPagination-CqbjVY6T.js → StickyPagination-BNOuYZ1m.js} +2 -2
  158. package/dashboard/dist/assets/{StickyPagination-CqbjVY6T.js.map → StickyPagination-BNOuYZ1m.js.map} +1 -1
  159. package/dashboard/dist/assets/{StreamMessageDetail-wX3i0aqs.js → StreamMessageDetail-ALVUnfF1.js} +2 -2
  160. package/dashboard/dist/assets/{StreamMessageDetail-wX3i0aqs.js.map → StreamMessageDetail-ALVUnfF1.js.map} +1 -1
  161. package/dashboard/dist/assets/{SwimlaneTimeline-C50PsFoV.js → SwimlaneTimeline-B5b8-xqI.js} +2 -2
  162. package/dashboard/dist/assets/{SwimlaneTimeline-C50PsFoV.js.map → SwimlaneTimeline-B5b8-xqI.js.map} +1 -1
  163. package/dashboard/dist/assets/{TagInput-CAgdLN_b.js → TagInput-B6fMAqxd.js} +2 -2
  164. package/dashboard/dist/assets/{TagInput-CAgdLN_b.js.map → TagInput-B6fMAqxd.js.map} +1 -1
  165. package/dashboard/dist/assets/{TaskDetailPage-bbNSv4Ae.js → TaskDetailPage-CoV3WcTA.js} +2 -2
  166. package/dashboard/dist/assets/{TaskDetailPage-bbNSv4Ae.js.map → TaskDetailPage-CoV3WcTA.js.map} +1 -1
  167. package/dashboard/dist/assets/{TaskQueuePill-h0oorVMe.js → TaskQueuePill-BnDp_DE6.js} +2 -2
  168. package/dashboard/dist/assets/{TaskQueuePill-h0oorVMe.js.map → TaskQueuePill-BnDp_DE6.js.map} +1 -1
  169. package/dashboard/dist/assets/{TasksListPage-CDWnm_d9.js → TasksListPage-CkMmOYOE.js} +2 -2
  170. package/dashboard/dist/assets/{TasksListPage-CDWnm_d9.js.map → TasksListPage-CkMmOYOE.js.map} +1 -1
  171. package/dashboard/dist/assets/{TimeAgo-BLjqlfoX.js → TimeAgo-DVkFgECX.js} +2 -2
  172. package/dashboard/dist/assets/{TimeAgo-BLjqlfoX.js.map → TimeAgo-DVkFgECX.js.map} +1 -1
  173. package/dashboard/dist/assets/{TimestampCell-CnW0ENb5.js → TimestampCell-CfTc6Txy.js} +2 -2
  174. package/dashboard/dist/assets/{TimestampCell-CnW0ENb5.js.map → TimestampCell-CfTc6Txy.js.map} +1 -1
  175. package/dashboard/dist/assets/{ToolPill-CQCsVdzD.js → ToolPill-BRZWo4l8.js} +2 -2
  176. package/dashboard/dist/assets/{ToolPill-CQCsVdzD.js.map → ToolPill-BRZWo4l8.js.map} +1 -1
  177. package/dashboard/dist/assets/{ToolTestPanel-DkMgCB-k.js → ToolTestPanel-kvqZqM0A.js} +2 -2
  178. package/dashboard/dist/assets/{ToolTestPanel-DkMgCB-k.js.map → ToolTestPanel-kvqZqM0A.js.map} +1 -1
  179. package/dashboard/dist/assets/{TopicDetailPage-g3pljKKX.js → TopicDetailPage-CjkAAyy8.js} +4 -4
  180. package/dashboard/dist/assets/{TopicDetailPage-g3pljKKX.js.map → TopicDetailPage-CjkAAyy8.js.map} +1 -1
  181. package/dashboard/dist/assets/{TopicsPage-CVcCYdy-.js → TopicsPage-CJZnv50y.js} +2 -2
  182. package/dashboard/dist/assets/{TopicsPage-CVcCYdy-.js.map → TopicsPage-CJZnv50y.js.map} +1 -1
  183. package/dashboard/dist/assets/{UserName-D6zGIK2i.js → UserName-CPJPZnN1.js} +2 -2
  184. package/dashboard/dist/assets/{UserName-D6zGIK2i.js.map → UserName-CPJPZnN1.js.map} +1 -1
  185. package/dashboard/dist/assets/WorkflowExecutionPage-46UV5pJd.js +2 -0
  186. package/dashboard/dist/assets/{WorkflowExecutionPage-B8g81FCJ.js.map → WorkflowExecutionPage-46UV5pJd.js.map} +1 -1
  187. package/dashboard/dist/assets/{WorkflowPill-Dg7BDTyM.js → WorkflowPill-Cly9Ln_3.js} +2 -2
  188. package/dashboard/dist/assets/{WorkflowPill-Dg7BDTyM.js.map → WorkflowPill-Cly9Ln_3.js.map} +1 -1
  189. package/dashboard/dist/assets/{WorkflowsDashboard-nxT3bv6W.js → WorkflowsDashboard-DtxYdQbQ.js} +2 -2
  190. package/dashboard/dist/assets/{WorkflowsDashboard-nxT3bv6W.js.map → WorkflowsDashboard-DtxYdQbQ.js.map} +1 -1
  191. package/dashboard/dist/assets/{WorkflowsOverview-grI-KAI2.js → WorkflowsOverview-Cg4LSfck.js} +2 -2
  192. package/dashboard/dist/assets/{WorkflowsOverview-grI-KAI2.js.map → WorkflowsOverview-Cg4LSfck.js.map} +1 -1
  193. package/dashboard/dist/assets/{YamlWorkflowDetailPage-BoZ-hfBE.js → YamlWorkflowDetailPage-Del-RCgi.js} +12 -12
  194. package/dashboard/dist/assets/{YamlWorkflowDetailPage-BoZ-hfBE.js.map → YamlWorkflowDetailPage-Del-RCgi.js.map} +1 -1
  195. package/dashboard/dist/assets/{YamlWorkflowsPage-Bf04rwRv.js → YamlWorkflowsPage-BF6Jtx24.js} +2 -2
  196. package/dashboard/dist/assets/{YamlWorkflowsPage-Bf04rwRv.js.map → YamlWorkflowsPage-BF6Jtx24.js.map} +1 -1
  197. package/dashboard/dist/assets/{agents-Dphpdi8l.js → agents-wL-3dMOX.js} +2 -2
  198. package/dashboard/dist/assets/{agents-Dphpdi8l.js.map → agents-wL-3dMOX.js.map} +1 -1
  199. package/dashboard/dist/assets/{bots-DIFE298x.js → bots-D72EsztP.js} +2 -2
  200. package/dashboard/dist/assets/{bots-DIFE298x.js.map → bots-D72EsztP.js.map} +1 -1
  201. package/dashboard/dist/assets/{capabilities-D7Y7LClY.js → capabilities-DXFo6bRb.js} +2 -2
  202. package/dashboard/dist/assets/{capabilities-D7Y7LClY.js.map → capabilities-DXFo6bRb.js.map} +1 -1
  203. package/dashboard/dist/assets/{controlplane-D1TGcYsS.js → controlplane-gQdOgVtH.js} +2 -2
  204. package/dashboard/dist/assets/{controlplane-D1TGcYsS.js.map → controlplane-gQdOgVtH.js.map} +1 -1
  205. package/dashboard/dist/assets/escalation-columns-CSE5wfWQ.js +2 -0
  206. package/dashboard/dist/assets/escalation-columns-CSE5wfWQ.js.map +1 -0
  207. package/dashboard/dist/assets/escalation-items-BIgBWbaw.js +2 -0
  208. package/dashboard/dist/assets/escalation-items-BIgBWbaw.js.map +1 -0
  209. package/dashboard/dist/assets/{index-CeCtqujG.js → index-BaCDL5fh.js} +38 -38
  210. package/dashboard/dist/assets/index-BaCDL5fh.js.map +1 -0
  211. package/dashboard/dist/assets/{index-Dl_8hbYI.js → index-Btm8FtTQ.js} +2 -2
  212. package/dashboard/dist/assets/{index-Dl_8hbYI.js.map → index-Btm8FtTQ.js.map} +1 -1
  213. package/dashboard/dist/assets/index-BvH8T-jb.js +2 -0
  214. package/dashboard/dist/assets/{index-CxdjT1Yk.js.map → index-BvH8T-jb.js.map} +1 -1
  215. package/dashboard/dist/assets/{index-HLu98Sqh.js → index-C-QQ5rKF.js} +2 -2
  216. package/dashboard/dist/assets/{index-HLu98Sqh.js.map → index-C-QQ5rKF.js.map} +1 -1
  217. package/dashboard/dist/assets/{index-DpKOr311.js → index-C1iuZ4Q5.js} +2 -2
  218. package/dashboard/dist/assets/{index-DpKOr311.js.map → index-C1iuZ4Q5.js.map} +1 -1
  219. package/dashboard/dist/assets/{index-ChV7pBjM.js → index-CDxOQ84B.js} +2 -2
  220. package/dashboard/dist/assets/{index-ChV7pBjM.js.map → index-CDxOQ84B.js.map} +1 -1
  221. package/dashboard/dist/assets/index-CED9cLE2.js +3 -0
  222. package/dashboard/dist/assets/index-CED9cLE2.js.map +1 -0
  223. package/dashboard/dist/assets/index-CnU7Jjz3.css +1 -0
  224. package/dashboard/dist/assets/{index-DAvi5_2T.js → index-CptTEhWp.js} +2 -2
  225. package/dashboard/dist/assets/{index-DAvi5_2T.js.map → index-CptTEhWp.js.map} +1 -1
  226. package/dashboard/dist/assets/{index-ag2pCAPu.js → index-Cu0xdX2t.js} +2 -2
  227. package/dashboard/dist/assets/{index-ag2pCAPu.js.map → index-Cu0xdX2t.js.map} +1 -1
  228. package/dashboard/dist/assets/index-D1lfq5iZ.js +13 -0
  229. package/dashboard/dist/assets/{index-gkxPN7Vx.js.map → index-D1lfq5iZ.js.map} +1 -1
  230. package/dashboard/dist/assets/{index-Dy1wWu2e.js → index-czgLyfSo.js} +2 -2
  231. package/dashboard/dist/assets/{index-Dy1wWu2e.js.map → index-czgLyfSo.js.map} +1 -1
  232. package/dashboard/dist/assets/{index-DN-kX7hL.js → index-h1Useskt.js} +2 -2
  233. package/dashboard/dist/assets/{index-DN-kX7hL.js.map → index-h1Useskt.js.map} +1 -1
  234. package/dashboard/dist/assets/{index-BzYcUPdD.js → index-ujGmmwl6.js} +2 -2
  235. package/dashboard/dist/assets/{index-BzYcUPdD.js.map → index-ujGmmwl6.js.map} +1 -1
  236. package/dashboard/dist/assets/{knowledge-DnMs-SOJ.js → knowledge-150lsM68.js} +2 -2
  237. package/dashboard/dist/assets/{knowledge-DnMs-SOJ.js.map → knowledge-150lsM68.js.map} +1 -1
  238. package/dashboard/dist/assets/{mcp-CwW-K3r4.js → mcp-CRtY4v5W.js} +2 -2
  239. package/dashboard/dist/assets/{mcp-CwW-K3r4.js.map → mcp-CRtY4v5W.js.map} +1 -1
  240. package/dashboard/dist/assets/{mcp-query-BZt5e8_Q.js → mcp-query-CDsSMaYq.js} +2 -2
  241. package/dashboard/dist/assets/{mcp-query-BZt5e8_Q.js.map → mcp-query-CDsSMaYq.js.map} +1 -1
  242. package/dashboard/dist/assets/{personas-UA-Xn60f.js → personas-C2Wm4ng1.js} +2 -2
  243. package/dashboard/dist/assets/{personas-UA-Xn60f.js.map → personas-C2Wm4ng1.js.map} +1 -1
  244. package/dashboard/dist/assets/{pipelines-Cu3PARum.js → pipelines-BH0F9-jf.js} +2 -2
  245. package/dashboard/dist/assets/{pipelines-Cu3PARum.js.map → pipelines-BH0F9-jf.js.map} +1 -1
  246. package/dashboard/dist/assets/{tasks-BO6h8GJE.js → tasks-BkUVpaOa.js} +2 -2
  247. package/dashboard/dist/assets/{tasks-BO6h8GJE.js.map → tasks-BkUVpaOa.js.map} +1 -1
  248. package/dashboard/dist/assets/{topics-CWjCR-17.js → topics-Crl8HKHq.js} +2 -2
  249. package/dashboard/dist/assets/{topics-CWjCR-17.js.map → topics-Crl8HKHq.js.map} +1 -1
  250. package/dashboard/dist/assets/{useDebouncedValue-6t0jx1RB.js → useDebouncedValue-Dk3r5xo-.js} +2 -2
  251. package/dashboard/dist/assets/{useDebouncedValue-6t0jx1RB.js.map → useDebouncedValue-Dk3r5xo-.js.map} +1 -1
  252. package/dashboard/dist/assets/{useNamespace-CqpoQx6D.js → useNamespace-BXuyHKAs.js} +2 -2
  253. package/dashboard/dist/assets/{useNamespace-CqpoQx6D.js.map → useNamespace-BXuyHKAs.js.map} +1 -1
  254. package/dashboard/dist/assets/{useYamlActivityEvents-hmCQQwzB.js → useYamlActivityEvents-DSlkjQfb.js} +2 -2
  255. package/dashboard/dist/assets/{useYamlActivityEvents-hmCQQwzB.js.map → useYamlActivityEvents-DSlkjQfb.js.map} +1 -1
  256. package/dashboard/dist/assets/{vendor-icons-CeVtUKyP.js → vendor-icons-C_DQEeBy.js} +2 -2
  257. package/dashboard/dist/assets/{vendor-icons-CeVtUKyP.js.map → vendor-icons-C_DQEeBy.js.map} +1 -1
  258. package/dashboard/dist/assets/{yaml-workflows-ziUdZhKY.js → yaml-workflows-B230v5Za.js} +2 -2
  259. package/dashboard/dist/assets/{yaml-workflows-ziUdZhKY.js.map → yaml-workflows-B230v5Za.js.map} +1 -1
  260. package/dashboard/dist/index.html +3 -3
  261. package/docs/faceted-routing.md +14 -1
  262. package/docs/hitl/x-lt-embed.md +4 -1
  263. package/docs/hitl/x-lt-list-schema.md +19 -2
  264. package/docs/hitl/x-lt-roster.md +112 -0
  265. package/docs/hitl/x-lt-show-if.md +15 -0
  266. package/docs/hitl/x-lt-widget.md +1 -0
  267. package/docs/hitl-guide.md +3 -1
  268. package/docs/maintenance.md +3 -3
  269. package/docs/mcp.md +2 -0
  270. package/docs/scan-codes.md +4 -0
  271. package/docs/schema-enforcement.md +5 -0
  272. package/package.json +2 -2
  273. package/dashboard/dist/assets/AvailableEscalationsPage-IS28XBRe.js +0 -2
  274. package/dashboard/dist/assets/CountdownTimer-LG03dVgR.js +0 -2
  275. package/dashboard/dist/assets/CountdownTimer-LG03dVgR.js.map +0 -1
  276. package/dashboard/dist/assets/EscalationTimeline-d3nvshOk.js +0 -2
  277. package/dashboard/dist/assets/McpRunDetailPage-bMXNO-6V.js +0 -2
  278. package/dashboard/dist/assets/OperatorDashboard-DctmZw10.js +0 -2
  279. package/dashboard/dist/assets/PortalPage-Dfc_Q02R.js +0 -2
  280. package/dashboard/dist/assets/ResolverForm-B1_x8Blv.js +0 -8
  281. package/dashboard/dist/assets/ResolverForm-B1_x8Blv.js.map +0 -1
  282. package/dashboard/dist/assets/ScanStationPage-DzGaXc40.js +0 -2
  283. package/dashboard/dist/assets/ScanStationPage-DzGaXc40.js.map +0 -1
  284. package/dashboard/dist/assets/WorkflowExecutionPage-B8g81FCJ.js +0 -2
  285. package/dashboard/dist/assets/escalation-columns-cwZE6xyo.js +0 -2
  286. package/dashboard/dist/assets/escalation-columns-cwZE6xyo.js.map +0 -1
  287. package/dashboard/dist/assets/index-CeCtqujG.js.map +0 -1
  288. package/dashboard/dist/assets/index-CniRa65p.js +0 -3
  289. package/dashboard/dist/assets/index-CniRa65p.js.map +0 -1
  290. package/dashboard/dist/assets/index-CxdjT1Yk.js +0 -2
  291. package/dashboard/dist/assets/index-gkxPN7Vx.js +0 -13
  292. package/dashboard/dist/assets/index-m9A3UYst.css +0 -1
  293. package/dashboard/dist/assets/validate-BIRn4a6d.js +0 -2
  294. package/dashboard/dist/assets/validate-BIRn4a6d.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"escalation-columns-CSE5wfWQ.js","sources":["../../src/lib/type-color.ts","../../src/components/escalation/RefineDialog.tsx","../../src/api/escalation-related.ts","../../../shared/list-schema/template.ts","../../src/components/escalation/list-view/RelatedCell.tsx","../../src/components/escalation/list-view/RowDetail.tsx","../../src/components/escalation/list-view/group-rows.ts","../../src/components/escalation/list-view/FacetTable.tsx","../../src/components/escalation/EscalationListView.tsx","../../src/pages/operator/escalation-columns.tsx"],"sourcesContent":["/**\n * Deterministic color assignment for workflow type names.\n *\n * Maps any string to a consistent color from a curated 24-color palette.\n * The same type name always produces the same color across the entire UI.\n * Uses a simple hash to distribute names evenly across the palette.\n *\n * Each entry provides:\n * text — icon and text color (Tailwind class)\n * bg — subtle background tint (Tailwind class)\n */\n\nconst PALETTE: Array<{ text: string; bg: string }> = [\n { text: 'text-rose-400', bg: 'bg-rose-400/[0.08]' },\n { text: 'text-pink-400', bg: 'bg-pink-400/[0.08]' },\n { text: 'text-fuchsia-400', bg: 'bg-fuchsia-400/[0.08]' },\n { text: 'text-purple-400', bg: 'bg-purple-400/[0.08]' },\n { text: 'text-violet-400', bg: 'bg-violet-400/[0.08]' },\n { text: 'text-indigo-400', bg: 'bg-indigo-400/[0.08]' },\n { text: 'text-blue-400', bg: 'bg-blue-400/[0.08]' },\n { text: 'text-sky-400', bg: 'bg-sky-400/[0.08]' },\n { text: 'text-cyan-400', bg: 'bg-cyan-400/[0.08]' },\n { text: 'text-teal-400', bg: 'bg-teal-400/[0.08]' },\n { text: 'text-emerald-400', bg: 'bg-emerald-400/[0.08]' },\n { text: 'text-green-400', bg: 'bg-green-400/[0.08]' },\n { text: 'text-lime-400', bg: 'bg-lime-400/[0.08]' },\n { text: 'text-yellow-400', bg: 'bg-yellow-400/[0.08]' },\n { text: 'text-amber-400', bg: 'bg-amber-400/[0.08]' },\n { text: 'text-orange-400', bg: 'bg-orange-400/[0.08]' },\n { text: 'text-red-400', bg: 'bg-red-400/[0.08]' },\n { text: 'text-stone-400', bg: 'bg-stone-400/[0.08]' },\n { text: 'text-rose-300', bg: 'bg-rose-300/[0.08]' },\n { text: 'text-violet-300', bg: 'bg-violet-300/[0.08]' },\n { text: 'text-sky-300', bg: 'bg-sky-300/[0.08]' },\n { text: 'text-teal-300', bg: 'bg-teal-300/[0.08]' },\n { text: 'text-amber-300', bg: 'bg-amber-300/[0.08]' },\n { text: 'text-pink-300', bg: 'bg-pink-300/[0.08]' },\n];\n\nfunction hash(str: string): number {\n let h = 0;\n for (let i = 0; i < str.length; i++) {\n h = ((h << 5) - h + str.charCodeAt(i)) | 0;\n }\n return Math.abs(h);\n}\n\nexport function typeColor(typeName: string): { text: string; bg: string } {\n return PALETTE[hash(typeName) % PALETTE.length];\n}\n","import { useState } from 'react';\nimport { Check, Search } from 'lucide-react';\nimport { Modal } from '../common/modal/Modal';\nimport { metadataFacetsUrl } from '../../lib/facet-url';\n\n/** One refinable fact from a row: a metadata key with its authored label and value. */\nexport interface RefinePair {\n key: string;\n label: string;\n value: unknown;\n /** The author put this fact in the row's columns; a lone bound fact arrives preselected. */\n bound?: boolean;\n}\n\n/**\n * The row-level refine gesture for authored lists (facet-table rows, board\n * cards): the row's metadata-bound facts as full-width touch rows, each a\n * toggle. Pick one or several (multi-select ANDs the facets) and drill —\n * filter this role's queue, search every role, or merge into the live filter\n * set. One dialog replaces per-cell icon pairs, so table cells spend their\n * width on data and the affordance stays tappable on the iPad floor. The\n * list is the row's whole metadata; past a handful of facts a find box\n * narrows it by label, key, or value.\n */\nconst FIND_THRESHOLD = 6;\nexport function RefineDialog({ open, onClose, role, pairs, onNavigate, onAddFacet }: {\n open: boolean;\n onClose: () => void;\n role: string;\n pairs: RefinePair[];\n /** Receives the facet deep-link. Hosts navigate (or open a panel). */\n onNavigate: (url: string) => void;\n /** When provided, \"Add to filters\" merges the selection into the live set. */\n onAddFacet?: (key: string, value: unknown) => void;\n}) {\n // A single fact, or a single column-bound fact, arrives selected — the\n // one-glance, two-tap path — while the rest of the record waits below.\n const [selected, setSelected] = useState<Set<string>>(new Set());\n const [find, setFind] = useState('');\n const [prevOpen, setPrevOpen] = useState(open);\n if (open !== prevOpen) {\n setPrevOpen(open);\n if (open) {\n const bound = pairs.filter((p) => p.bound);\n const preset = bound.length === 1 ? [bound[0].key] : pairs.length === 1 ? [pairs[0].key] : [];\n setSelected(new Set(preset));\n setFind('');\n }\n }\n const needle = find.trim().toLowerCase();\n const visible = needle\n ? pairs.filter((p) => [p.label, p.key, String(p.value)].some((t) => t.toLowerCase().includes(needle)))\n : pairs;\n\n const toggle = (key: string) => {\n setSelected((prev) => {\n const next = new Set(prev);\n if (next.has(key)) next.delete(key); else next.add(key);\n return next;\n });\n };\n\n const chosen = pairs.filter((p) => selected.has(p.key));\n const facets = Object.fromEntries(chosen.map((p) => [p.key, p.value]));\n const none = chosen.length === 0;\n\n const go = (url: string) => {\n onClose();\n onNavigate(url);\n };\n\n return (\n <Modal open={open} onClose={onClose} title=\"Refine\">\n <div className=\"space-y-4\">\n <p className=\"text-2xs text-text-tertiary\">\n Pick the facts to match — several combine into one narrower query.\n </p>\n\n {pairs.length > FIND_THRESHOLD && (\n <label className=\"flex items-center gap-2 input text-xs py-1.5\">\n <Search className=\"w-3.5 h-3.5 shrink-0 text-text-quaternary\" strokeWidth={1.5} />\n <input\n type=\"text\"\n value={find}\n onChange={(e) => setFind(e.target.value)}\n placeholder=\"Find a fact…\"\n className=\"flex-1 min-w-0 bg-transparent outline-none placeholder:text-text-quaternary\"\n aria-label=\"Find a fact\"\n data-testid=\"refine-find\"\n />\n <span className=\"text-2xs tabular-nums text-text-quaternary\">{visible.length}/{pairs.length}</span>\n </label>\n )}\n\n <div className=\"divide-y divide-surface-border/40 -mx-1 max-h-[50vh] overflow-y-auto\">\n {visible.map((p) => {\n const on = selected.has(p.key);\n return (\n <button\n key={p.key}\n type=\"button\"\n onClick={() => toggle(p.key)}\n aria-pressed={on}\n className=\"w-full flex items-center gap-3 px-1 py-2.5 text-left group min-w-0\"\n data-testid=\"refine-pair\"\n >\n <span\n className={`w-4 h-4 rounded-[3px] border flex items-center justify-center shrink-0 transition-colors ${\n on ? 'bg-accent border-accent' : 'border-surface-border group-hover:border-accent/50'\n }`}\n aria-hidden\n >\n {on && <Check className=\"w-3 h-3 text-text-inverse\" strokeWidth={3} />}\n </span>\n <span className=\"text-2xs font-semibold uppercase tracking-widest text-text-tertiary w-28 shrink-0 truncate\" title={p.key}>\n {p.label}\n </span>\n <span className=\"text-xs text-text-primary truncate flex-1 min-w-0\" title={String(p.value)}>\n {String(p.value)}\n </span>\n </button>\n );\n })}\n </div>\n\n <div className=\"flex items-center justify-end gap-3 pt-2 flex-wrap\">\n {onAddFacet && (\n <button\n onClick={() => {\n chosen.forEach((p) => onAddFacet(p.key, p.value));\n onClose();\n }}\n disabled={none}\n className=\"text-xs text-text-secondary hover:text-accent transition-colors disabled:opacity-40 disabled:cursor-not-allowed mr-auto\"\n data-testid=\"refine-add-filters\"\n >\n Add to filters\n </button>\n )}\n <button\n onClick={() => go(metadataFacetsUrl(facets))}\n disabled={none}\n className=\"btn-secondary text-xs disabled:opacity-40 disabled:cursor-not-allowed\"\n data-testid=\"refine-search-all\"\n >\n Search everywhere\n </button>\n <button\n onClick={() => go(metadataFacetsUrl(facets, role))}\n disabled={none}\n className=\"btn-primary text-xs disabled:opacity-40 disabled:cursor-not-allowed\"\n data-testid=\"refine-filter-role\"\n >\n Filter {role}\n </button>\n </div>\n </div>\n </Modal>\n );\n}\n","import { useQuery } from '@tanstack/react-query';\nimport { apiFetch } from './client';\nimport type { RelatedAggregatesResponse, RelatedRowsResponse } from '../lib/list-schema';\n\n/**\n * Every related set a role's list schema declares, aggregated for one page\n * of host rows. Keyed under `escalations`, so the list's live invalidation\n * refreshes it with the rows.\n */\nexport function useRelatedAggregates(role: string, ids: string[], version: number | null | undefined, enabled = true) {\n const sorted = [...ids].sort();\n return useQuery<RelatedAggregatesResponse>({\n queryKey: ['escalations', 'related', role, version ?? 'latest', sorted],\n queryFn: () =>\n apiFetch('/escalations/related', {\n method: 'POST',\n body: JSON.stringify({ role, ids: sorted, ...(version != null ? { version } : {}) }),\n }),\n enabled: enabled && !!role && sorted.length > 0,\n placeholderData: (prev) => prev,\n });\n}\n\n/** One host row's rows in one related set, loaded when its detail opens. */\nexport function useRelatedRows(\n role: string,\n id: string,\n set: string,\n version: number | null | undefined,\n limit?: number,\n enabled = true,\n) {\n return useQuery<RelatedRowsResponse>({\n queryKey: ['escalations', 'related-rows', role, version ?? 'latest', id, set, limit ?? null],\n queryFn: () =>\n apiFetch('/escalations/related/rows', {\n method: 'POST',\n body: JSON.stringify({ role, id, set, ...(version != null ? { version } : {}), ...(limit ? { limit } : {}) }),\n }),\n enabled: enabled && !!role && !!id && !!set,\n });\n}\n","import { getDeep } from '../form-validation/x-lt-bind';\nimport { HELP_DOMAINS, interpolateHelp, type HelpDomain, type HelpTokenContext } from '../form-validation/x-lt-help';\n\nconst SINGLE_TOKEN = /^\\{\\{\\s*([^{}]+?)\\s*\\}\\}$/;\nconst ANY_TOKEN = /\\{\\{\\s*[^{}]+?\\s*\\}\\}/;\nconst MISSING_VALUE = '—';\n\nfunction parseJsonObject(value: unknown): Record<string, unknown> | null {\n if (value && typeof value === 'object') return value as Record<string, unknown>;\n if (typeof value !== 'string' || !value) return null;\n try {\n const parsed = JSON.parse(value);\n return parsed && typeof parsed === 'object' ? parsed : null;\n } catch {\n return null;\n }\n}\n\n/** The template domains of one escalation row, JSON-string columns parsed. */\nexport function rowTemplateContext(row: Record<string, unknown>): HelpTokenContext {\n return {\n escalation: row,\n metadata: (row.metadata as Record<string, unknown> | null) ?? {},\n envelope: parseJsonObject(row.envelope) ?? {},\n payload: parseJsonObject(row.escalation_payload) ?? {},\n resolver: parseJsonObject(row.resolver_payload) ?? {},\n };\n}\n\nfunction readToken(path: string, ctx: HelpTokenContext): unknown {\n const dot = path.indexOf('.');\n const domain = (dot === -1 ? path : path.slice(0, dot)) as HelpDomain;\n if (!HELP_DOMAINS.includes(domain)) return undefined;\n const root = ctx[domain];\n if (dot === -1) return root ?? undefined;\n try {\n return getDeep(root, path.slice(dot + 1));\n } catch {\n return undefined;\n }\n}\n\n/**\n * Resolve one facet value. A lone `{{token}}` keeps the value's own JSON type\n * (a numeric facet matches a numeric facet); a mixed template interpolates to\n * a string; a literal passes through. Undefined when a token is missing.\n */\nexport function resolveTemplateValue(value: unknown, ctx: HelpTokenContext): unknown {\n if (typeof value !== 'string') return value;\n const single = value.match(SINGLE_TOKEN);\n if (single) {\n const raw = readToken(single[1], ctx);\n return raw === null || raw === '' ? undefined : raw;\n }\n if (!ANY_TOKEN.test(value)) return value;\n const text = interpolateHelp(value, ctx);\n return text.includes(MISSING_VALUE) ? undefined : text;\n}\n\n/**\n * Resolve a related query's match against a host row: every required facet\n * (null when any is missing), plus each `narrow` facet the row resolves.\n */\nexport function resolveRelatedFacets(\n facets: Record<string, unknown>,\n ctx: HelpTokenContext,\n narrow?: Record<string, unknown>,\n): Record<string, unknown> | null {\n const out: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(facets)) {\n const resolved = resolveTemplateValue(value, ctx);\n if (resolved === undefined) return null;\n out[key] = resolved;\n }\n for (const [key, value] of Object.entries(narrow ?? {})) {\n const resolved = resolveTemplateValue(value, ctx);\n if (resolved !== undefined) out[key] = resolved;\n }\n return out;\n}\n","import { Link } from 'react-router-dom';\nimport { EM_DASH, FormattedValue } from '../../common/display/FormattedValue';\nimport {\n SPLIT_PATHS,\n isExtremeAggregate,\n relatedCountText,\n type RelatedColumnDecl,\n type RelatedHostAggregate,\n type RelatedSetResult,\n} from '../../../lib/list-schema';\n\n/** A split value's display text: the declared label, a role title, or the value. */\nexport function splitLabel(value: string, col: RelatedColumnDecl, set?: RelatedSetResult): string {\n if (col.labels?.[value]) return col.labels[value];\n if (col.splitBy === SPLIT_PATHS.ROLE && set?.roleLabels?.[value]) return set.roleLabels[value];\n return value === '' ? 'None' : value;\n}\n\n/**\n * A related column cell: the count (or its `display` text), then each split\n * value as a chip in declaration order (role order for a role split), largest\n * first otherwise. A min or max column shows its value. Splits the viewer\n * cannot read show as a muted note, never a wrong split.\n */\nexport function RelatedCell({ col, set, agg, drillUrl }: {\n col: RelatedColumnDecl;\n set?: RelatedSetResult;\n agg?: RelatedHostAggregate;\n /** Query role splits: where a chip leads (the role list with the host's facets). */\n drillUrl?: (role: string) => string | null;\n}) {\n if (!agg || agg.unresolved) return <span className=\"text-text-quaternary\">{EM_DASH}</span>;\n if (isExtremeAggregate(col.aggregate)) {\n if (agg.value === undefined) return <span className=\"text-text-quaternary\">{EM_DASH}</span>;\n return (\n <span className=\"tabular-nums text-text-primary\" data-testid=\"related-cell\">\n <FormattedValue raw={String(agg.value)} format={col.format} />\n </span>\n );\n }\n const countText = relatedCountText(col.display, agg.count);\n const order = col.splitBy === SPLIT_PATHS.ROLE && set?.roles ? set.roles : null;\n const splits = Object.entries(agg.splits ?? {})\n .filter(([, n]) => n > 0)\n .sort(([a, x], [b, y]) => (order ? order.indexOf(a) - order.indexOf(b) : y - x));\n const restricted = col.splitBy === SPLIT_PATHS.ROLE ? (set?.restricted ?? []) : [];\n const title = [\n countText !== null ? String(agg.count) : '',\n agg.hidden ? `${agg.hidden} not readable by you` : '',\n restricted.length ? `Not counted (outside your view): ${restricted.map((r) => set?.roleLabels?.[r] ?? r).join(', ')}` : '',\n ].filter(Boolean).join(' · ');\n\n return (\n <span className=\"inline-flex flex-wrap items-center gap-1 min-w-0\" title={title || undefined} data-testid=\"related-cell\">\n <span className=\"tabular-nums font-medium text-text-primary\" data-testid=\"related-count\">{countText ?? agg.count}</span>\n {splits.map(([value, n]) => {\n const text = `${splitLabel(value, col, set)} ${n}`;\n const href = order && drillUrl ? drillUrl(value) : null;\n const chip = 'px-1.5 py-0.5 rounded bg-surface-sunken text-2xs text-text-secondary whitespace-nowrap tabular-nums';\n return href ? (\n <Link key={value} to={href} onClick={(e) => e.stopPropagation()} className={`${chip} hover:text-accent`} data-testid=\"related-chip\">\n {text}\n </Link>\n ) : (\n <span key={value} className={chip} data-testid=\"related-chip\">{text}</span>\n );\n })}\n {(agg.hidden || restricted.length > 0) && (\n <span className=\"text-2xs text-text-quaternary italic\" data-testid=\"related-restricted\">\n {agg.hidden && !splits.length ? 'split restricted' : 'partial'}\n </span>\n )}\n </span>\n );\n}\n","import { useNavigate } from 'react-router-dom';\nimport { DataTable, type Column } from '../../common/data/DataTable';\nimport { FormattedValue, EM_DASH } from '../../common/display/FormattedValue';\nimport { useRelatedRows } from '../../../api/escalation-related';\nimport { interpolateItemTemplate, type EscalationItem } from '../../../lib/escalation-items';\nimport { displayRoleTitle } from '../../../lib/role-display';\nimport type { RelatedRow, RowDetailSectionDecl } from '../../../lib/list-schema';\nimport { rowContext } from './row-parts';\nimport type { LTEscalationRecord } from '../../../api/types';\n\n/** `format: \"role\"` renders a role name as its title. */\nconst ROLE_FORMAT = 'role';\n\nfunction cellText(template: string, row: RelatedRow): string {\n const ctx = row.escalation ? rowContext(row.escalation as unknown as LTEscalationRecord) : {};\n return interpolateItemTemplate(template, row.item as EscalationItem | undefined, ctx);\n}\n\nfunction DetailSection({ role, host, version, section, roleLabels }: {\n role: string;\n host: LTEscalationRecord;\n version: number | null | undefined;\n section: RowDetailSectionDecl;\n roleLabels?: Record<string, string>;\n}) {\n const navigate = useNavigate();\n const query = useRelatedRows(role, host.id, section.related, version, section.limit);\n const rows = query.data?.rows ?? [];\n const labels = query.data?.roleLabels ?? roleLabels ?? {};\n const restricted = query.data?.restricted ?? [];\n\n // A column whose every row restates a facet the opened row carries says\n // nothing new beneath it: the row already shows that facet.\n const hostValues = new Set(\n Object.values(host.metadata ?? {})\n .filter((v) => (typeof v === 'string' && v !== '') || typeof v === 'number' || typeof v === 'boolean')\n .map(String),\n );\n const shown = section.columns.filter((col, i) => {\n // The first column names each row; it always stays.\n if (i === 0 || rows.length === 0) return true;\n const values = new Set(rows.map((row) => cellText(col.value, row)));\n return !(values.size === 1 && hostValues.has([...values][0]));\n });\n\n const columns: Column<RelatedRow>[] = shown.map((col, i) => ({\n key: `d-${i}`,\n label: col.label,\n priority: col.priority ?? (i === 0 ? 1 : 2),\n render: (row) => {\n const text = cellText(col.value, row);\n if (col.format === ROLE_FORMAT && text !== EM_DASH) {\n return <span className=\"block truncate\">{labels[text] ?? displayRoleTitle({ role: text })}</span>;\n }\n return (\n <span className=\"block truncate\" title={text !== EM_DASH ? text : undefined}>\n <FormattedValue raw={text} format={col.format} />\n </span>\n );\n },\n }));\n\n const target = (row: RelatedRow): string | null =>\n (row.escalation?.id as string | undefined) ?? row.item?.reciprocalId ?? null;\n\n return (\n <div data-testid=\"row-detail-section\">\n <p className=\"text-2xs font-semibold uppercase tracking-widest text-text-tertiary pt-3 pb-1\">\n {section.label ?? section.related}\n {query.data && <span className=\"ml-2 font-normal normal-case tracking-normal tabular-nums\">{query.data.total}</span>}\n </p>\n {query.isLoading ? (\n <p className=\"text-2xs text-text-tertiary italic pb-2\">Loading…</p>\n ) : (\n <DataTable\n columns={columns}\n data={rows}\n keyFn={(row) => row.item?.itemKey ?? String(row.escalation?.id)}\n onRowClick={(row) => {\n const id = target(row);\n if (id) navigate(`/escalations/detail/${id}`);\n }}\n layout=\"fixed\"\n density=\"compact\"\n inline\n emptyMessage=\"\"\n />\n )}\n {!query.isLoading && rows.length === 0 && (\n <p className=\"text-2xs text-text-quaternary italic pb-2\">None.</p>\n )}\n {query.data && query.data.total > rows.length && (\n <p className=\"text-2xs text-text-quaternary pb-2\">Showing {rows.length} of {query.data.total}.</p>\n )}\n {restricted.length > 0 && (\n <p className=\"text-2xs text-text-quaternary italic pb-2\">\n Not shown (outside your view): {restricted.map((r) => labels[r] ?? r).join(', ')}\n </p>\n )}\n </div>\n );\n}\n\n/** A host row's declared detail sections, each loaded when the row opens. */\nexport function RowDetail({ role, host, version, sections }: {\n role: string;\n host: LTEscalationRecord;\n version: number | null | undefined;\n sections: RowDetailSectionDecl[];\n}) {\n return (\n <div className=\"space-y-1\" data-testid=\"row-detail\">\n {sections.map((section, i) => (\n <DetailSection key={i} role={role} host={host} version={version} section={section} />\n ))}\n </div>\n );\n}\n","import { interpolateHelp } from '../../../lib/x-lt-help';\nimport { GROUP_FOLDS, foldExtreme, isExtremeAggregate, type GroupFold, type RelatedAggregate, type RelatedHostAggregate } from '../../../lib/list-schema';\nimport { EM_DASH } from '../../common/display/FormattedValue';\nimport { rowContext, type ColumnDef } from './row-parts';\nimport type { LTEscalationRecord } from '../../../api/types';\n\n/** One page group from the grouped list read. */\nexport interface EscalationGroup {\n key: string | null;\n ids: string[];\n}\n\n/** A facet-table row: one escalation, or a group of rows sharing a facet. */\nexport interface TableRow {\n key: string;\n rows: LTEscalationRecord[];\n /** The shared facet value; null for an ungrouped row or a row without the facet. */\n groupKey: string | null;\n /** 0 for a top-level line; 1 for a member shown under its open group. */\n depth?: number;\n /** A member that closes its group's block. */\n lastChild?: boolean;\n /** A member's group line. */\n parent?: TableRow;\n}\n\n/** The lines the table draws: each open group followed by its members. */\nexport function withOpenMembers(rows: TableRow[], open: ReadonlySet<string>): TableRow[] {\n return rows.flatMap((row) => {\n if (row.rows.length < 2 || !open.has(row.key)) return [row];\n const members = row.rows.map((m, i): TableRow => ({\n key: `${row.key}/${m.id}`,\n rows: [m],\n groupKey: row.groupKey,\n depth: 1,\n lastChild: i === row.rows.length - 1,\n parent: row,\n }));\n return [row, ...members];\n });\n}\n\n/** Table rows in page order: one per group when grouped, else one per row. */\nexport function buildTableRows(rows: LTEscalationRecord[], groups?: EscalationGroup[] | null): TableRow[] {\n if (!groups) return rows.map((r) => ({ key: r.id, rows: [r], groupKey: null }));\n const byId = new Map(rows.map((r) => [r.id, r]));\n return groups\n .map((g) => ({\n key: g.key != null ? `group:${g.key}` : g.ids[0],\n rows: g.ids.map((id) => byId.get(id)).filter((r): r is LTEscalationRecord => !!r),\n groupKey: g.key,\n }))\n .filter((g) => g.rows.length > 0);\n}\n\nfunction numeric(values: string[]): number[] | null {\n const nums = values.map((v) => Number(v));\n return nums.every((n) => Number.isFinite(n)) ? nums : null;\n}\n\n/**\n * A plain column's text across a group's rows. `first` reads the lead row;\n * `min`/`max` compare numerically when every value is a number, else as text\n * (ISO instants order as text); `sum` adds numbers; `count` counts rows.\n */\nexport function foldColumnText(col: ColumnDef & { group?: GroupFold }, rows: LTEscalationRecord[]): string {\n const fold = col.group ?? GROUP_FOLDS.FIRST;\n if (fold === GROUP_FOLDS.COUNT) return String(rows.length);\n const values = rows.map((r) => interpolateHelp(col.value, rowContext(r))).filter((v) => v && v !== EM_DASH);\n if (fold === GROUP_FOLDS.DISTINCT) return values.length ? [...new Set(values)].join(', ') : EM_DASH;\n if (fold === GROUP_FOLDS.FIRST || rows.length === 1) return values[0] ?? EM_DASH;\n if (!values.length) return EM_DASH;\n const nums = numeric(values);\n if (fold === GROUP_FOLDS.SUM) return nums ? String(nums.reduce((a, b) => a + b, 0)) : EM_DASH;\n if (nums) return String(fold === GROUP_FOLDS.MIN ? Math.min(...nums) : Math.max(...nums));\n const sorted = [...values].sort();\n return fold === GROUP_FOLDS.MIN ? sorted[0] : sorted[sorted.length - 1];\n}\n\n/** One aggregate across several host rows: counts and splits sum; a min or max folds its values. */\nexport function mergeAggregates(\n aggs: Array<RelatedHostAggregate | undefined>,\n aggregate?: RelatedAggregate,\n): RelatedHostAggregate | undefined {\n const present = aggs.filter((a): a is RelatedHostAggregate => !!a);\n if (!present.length) return undefined;\n if (present.every((a) => a.unresolved)) return { count: 0, unresolved: true };\n const out: RelatedHostAggregate = { count: 0 };\n for (const a of present) {\n if (a.unresolved) continue;\n out.count += a.count;\n if (a.hidden) out.hidden = (out.hidden ?? 0) + a.hidden;\n if (a.splits) {\n out.splits ??= {};\n for (const [k, n] of Object.entries(a.splits)) out.splits[k] = (out.splits[k] ?? 0) + n;\n }\n }\n if (isExtremeAggregate(aggregate)) {\n const value = foldExtreme(aggregate, present.flatMap((a) => (a.value === undefined ? [] : [a.value])));\n if (value !== undefined) out.value = value;\n }\n return out;\n}\n","import { useMemo, useState } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport { ChevronRight } from 'lucide-react';\nimport { interpolateHelp } from '../../../lib/x-lt-help';\nimport { DataTable, type Column as TableColumn } from '../../common/data/DataTable';\nimport { FormattedValue, EM_DASH } from '../../common/display/FormattedValue';\nimport { RefineDialog } from '../RefineDialog';\nimport { useRelatedAggregates } from '../../../api/escalation-related';\nimport { useRelatedSetEvents } from '../../../hooks/useEventHooks';\nimport { metadataFacetsUrl } from '../../../lib/facet-url';\nimport {\n readListSchemaRelations,\n relatedAggregateKey,\n resolveRelatedFacets,\n rowTemplateContext,\n type GroupFold,\n type ListSchemaRelations,\n type RelatedColumnDecl,\n type RelatedSetResult,\n} from '../../../lib/list-schema';\nimport {\n escalationDotClass,\n rowContext,\n rowRefinePairs,\n RowActionButton,\n RefineTrigger,\n IDENTITY_COLUMN_WIDTH,\n actionColumnWidth,\n type ColumnDef,\n type RowActionDef,\n} from './row-parts';\nimport { RelatedCell } from './RelatedCell';\nimport { RowDetail } from './RowDetail';\nimport { buildTableRows, foldColumnText, mergeAggregates, withOpenMembers, type EscalationGroup, type TableRow } from './group-rows';\nimport type { LTEscalationRecord } from '../../../api/types';\n\nexport type { EscalationGroup } from './group-rows';\n\n/** A plain column (a `value` template) or a related column (a `related` set). */\ntype TableColumnDecl = ColumnDef & Partial<Omit<RelatedColumnDecl, 'label'>> & { group?: GroupFold };\n\nexport interface FacetTableSchema {\n 'x-lt-columns'?: Array<ColumnDef | (Omit<ColumnDef, 'value'> & RelatedColumnDecl)>;\n 'x-lt-row-action'?: RowActionDef;\n [key: string]: unknown;\n}\n\n/** One member per distinct resolved facet match (members whose facets do not resolve stay). */\nfunction distinctByMatch(members: LTEscalationRecord[], facets: Record<string, unknown>, narrow?: Record<string, unknown>): LTEscalationRecord[] {\n const seen = new Set<string>();\n return members.filter((m) => {\n const match = resolveRelatedFacets(facets, rowTemplateContext(m as unknown as Record<string, unknown>), narrow);\n if (!match) return true;\n const key = JSON.stringify(match);\n if (seen.has(key)) return false;\n seen.add(key);\n return true;\n });\n}\n\n/** The related declaration, or none when the stored schema does not validate. */\nfunction safeRelations(schema: FacetTableSchema): ListSchemaRelations | null {\n try {\n return readListSchemaRelations(schema);\n } catch {\n return null;\n }\n}\n\n/**\n * The pending queue as a facet table. Plain columns template over each row;\n * related columns aggregate the row's related sets (one request per page);\n * a declared row detail expands each row into its related rows; grouped\n * rows fold their columns and expand to their members.\n */\ninterface FacetTableProps {\n schema: FacetTableSchema;\n rows: LTEscalationRecord[];\n /** Grouped reads: the page's groups, in order. */\n groups?: EscalationGroup[] | null;\n role: string;\n /** The list schema version the page rendered. */\n version?: number | null;\n onRowClick?: (row: LTEscalationRecord) => void;\n /** RefineDialog \"Add to filters\": merge into the live filter set. */\n onAddFacet?: (key: string, value: unknown) => void;\n forceView?: boolean;\n}\n\n/** Reads the page's related sets and keeps them live; mounted only when the schema declares sets. */\nfunction RelatedFacetTable(props: FacetTableProps & { relations: ListSchemaRelations }) {\n const related = useRelatedAggregates(props.role, props.rows.map((r) => r.id), props.version);\n const sets = related.data?.sets ?? {};\n useRelatedSetEvents(Object.values(sets).flatMap((set) => set.roles ?? []));\n return <FacetTableBody {...props} sets={sets} setsLoading={related.isLoading} />;\n}\n\nexport function FacetTable(props: FacetTableProps) {\n const relations = useMemo(() => safeRelations(props.schema), [props.schema]);\n return relations && Object.keys(relations.sets).length > 0\n ? <RelatedFacetTable {...props} relations={relations} />\n : <FacetTableBody {...props} relations={relations} sets={{}} setsLoading={false} />;\n}\n\nfunction FacetTableBody({ schema, rows, groups, role, version, onRowClick, onAddFacet, forceView, relations, sets, setsLoading }: FacetTableProps & {\n relations: ListSchemaRelations | null;\n sets: Record<string, RelatedSetResult>;\n setsLoading: boolean;\n}) {\n const navigate = useNavigate();\n const columnDefs = (schema['x-lt-columns'] ?? []) as TableColumnDecl[];\n const rowAction = schema['x-lt-row-action'];\n const sections = relations?.rowDetail ?? [];\n const [refineRow, setRefineRow] = useState<LTEscalationRecord | null>(null);\n const [open, setOpen] = useState<Set<string>>(() => new Set());\n\n const tableRows = useMemo(() => buildTableRows(rows, groups), [rows, groups]);\n const lines = useMemo(() => withOpenMembers(tableRows, open), [tableRows, open]);\n const grouped = !!groups;\n const expandable = sections.length > 0 || grouped;\n // A row opens when it has something beneath it: a group its members, a row its detail.\n const opens = (r: TableRow) => r.rows.length > 1 || sections.length > 0;\n\n const toggle = (key: string) =>\n setOpen((prev) => {\n const next = new Set(prev);\n if (next.has(key)) next.delete(key); else next.add(key);\n return next;\n });\n\n const relatedCell = (col: TableColumnDecl, members: LTEscalationRecord[]) => {\n const name = col.related!;\n const set = sets[name];\n const query = relations?.sets[name]?.query;\n // Members that share a facet match read the same related rows: count them once.\n const counted = query?.facets ? distinctByMatch(members, query.facets, query.narrow) : members;\n const key = relatedAggregateKey(col as RelatedColumnDecl, relations?.sets[name]?.source ?? '');\n const agg = mergeAggregates(counted.map((m) => set?.aggregates[key]?.[m.id]), (col as RelatedColumnDecl).aggregate);\n const drillUrl = query?.facets && members.length === 1\n ? (relatedRole: string) => {\n const match = resolveRelatedFacets(query.facets!, rowTemplateContext(members[0] as unknown as Record<string, unknown>), query.narrow);\n return match ? metadataFacetsUrl(match, relatedRole) : null;\n }\n : undefined;\n return <RelatedCell col={col as RelatedColumnDecl} set={set} agg={setsLoading ? undefined : agg} drillUrl={drillUrl} />;\n };\n\n // The authored columns render through the same dense table the engineer\n // views use: the card fold at narrow widths, never a horizontal scroll.\n // Authors steer the fold with `priority` (1 title, 2 folds, 3 dropped).\n const actionLabel = rowAction?.label ?? (forceView ? 'View' : 'Claim');\n const lead = (r: TableRow) => r.rows[0];\n const columns: TableColumn<TableRow>[] = [\n ...(expandable ? [{\n key: '_expand',\n label: '',\n priority: 1 as const,\n className: 'w-12 px-1',\n render: (r: TableRow) => (\n // A member's chevron steps in under its group's, so depth reads at a glance.\n <span className={`flex ${r.depth ? 'pl-5' : ''}`}>\n {opens(r) && (\n <button\n type=\"button\"\n onClick={(e) => { e.stopPropagation(); toggle(r.key); }}\n className=\"p-1 rounded icon-link hover:bg-surface-hover transition-colors\"\n aria-expanded={open.has(r.key)}\n aria-label={open.has(r.key) ? 'Collapse row' : 'Expand row'}\n data-testid=\"row-expand\"\n >\n <ChevronRight className={`w-3.5 h-3.5 transition-transform ${open.has(r.key) ? 'rotate-90' : ''}`} strokeWidth={1.75} />\n </button>\n )}\n </span>\n ),\n }] : []),\n {\n key: '_status',\n label: '',\n priority: 1,\n className: 'w-8',\n render: (r) => (\n <span className=\"inline-flex items-center gap-1\">\n <span className={`w-2.5 h-2.5 inline-block rounded-full dot-ring ${escalationDotClass(lead(r))}`} title={lead(r).status} />\n {r.rows.length > 1 && (\n <span className=\"text-2xs tabular-nums text-text-tertiary\" title={`${r.rows.length} rows in this group`} data-testid=\"group-size\">\n {r.rows.length}\n </span>\n )}\n </span>\n ),\n },\n ...columnDefs.map((col, i): TableColumn<TableRow> => ({\n key: `col-${i}`,\n label: col.label,\n priority: col.priority ?? (i === 0 ? 1 : 2),\n width: col.width ?? (i === 0 && !columnDefs.some((c) => c.width) ? IDENTITY_COLUMN_WIDTH : undefined),\n render: (r) => {\n if (col.related) return relatedCell(col, r.rows);\n const text = r.rows.length > 1 ? foldColumnText(col, r.rows) : interpolateHelp(col.value, rowContext(lead(r)));\n // A member shows only what differs from its group: the group line already states the rest.\n if (r.parent && text === foldColumnText(col, r.parent.rows)) return null;\n // The identity steps in for a member, so the tree reads in the data too.\n const indent = i === 0 && r.depth ? 'pl-4' : '';\n return (\n <span className={`block truncate ${indent}`} title={text && text !== EM_DASH ? text : undefined}>\n <FormattedValue raw={text} format={col.format} />\n </span>\n );\n },\n })),\n {\n key: '_refine',\n label: '',\n priority: 1,\n className: 'w-8 px-1',\n render: (r) =>\n r.rows.length === 1 && rowRefinePairs(lead(r), columnDefs).length > 0\n ? <RefineTrigger onOpen={() => setRefineRow(lead(r))} />\n : null,\n },\n {\n // The action column sizes to its label so the button never wraps.\n key: '_action',\n label: '',\n priority: 1,\n width: actionColumnWidth(actionLabel),\n className: 'text-right whitespace-nowrap',\n render: (r) => r.rows.length === 1\n ? <RowActionButton row={lead(r)} def={rowAction} onView={() => onRowClick?.(lead(r))} forceView={forceView} />\n : null,\n },\n ];\n\n // Containment by depth: an open line takes a light band, its members a\n // stronger band stepped in under it, and a row's detail the band of its\n // row, indented past it. No rules: indentation and value carry the tree.\n const rowClassName = (r: TableRow) => {\n if (r.depth) return 'bg-surface-sunken border-b-surface-border/40';\n return open.has(r.key) && opens(r) ? 'bg-surface-sunken/50 border-b-surface-border/40' : '';\n };\n\n const renderExpansion = (r: TableRow) => {\n if (!open.has(r.key) || r.rows.length > 1 || sections.length === 0) return null;\n return (\n <div\n onClick={(e) => e.stopPropagation()}\n className={`${r.depth ? 'bg-surface-sunken pl-20' : 'bg-surface-sunken/50 pl-12'} pr-3 pt-1 pb-4`}\n data-testid=\"row-detail-block\"\n >\n <RowDetail role={role} host={lead(r)} version={version} sections={sections} />\n </div>\n );\n };\n\n return (\n <>\n <DataTable\n columns={columns}\n data={lines}\n layout=\"fixed\"\n density=\"dense\"\n keyFn={(r) => r.key}\n onRowClick={onRowClick ? (r) => (r.rows.length === 1 ? onRowClick(lead(r)) : toggle(r.key)) : undefined}\n rowClassName={expandable ? rowClassName : undefined}\n emptyMessage=\"No pending items.\"\n renderExpansion={expandable ? renderExpansion : undefined}\n />\n <RefineDialog\n open={!!refineRow}\n onClose={() => setRefineRow(null)}\n role={role}\n pairs={refineRow ? rowRefinePairs(refineRow, columnDefs) : []}\n onNavigate={navigate}\n onAddFacet={onAddFacet}\n />\n </>\n );\n}\n","import { useState, useEffect } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport { interpolateHelp } from '../../lib/x-lt-help';\nimport { MarkdownRenderer } from '../common/display/MarkdownRenderer';\nimport { DateValue } from '../common/display/DateValue';\nimport { FormattedValue as FieldValue, EM_DASH, isAgeFormat } from '../common/display/FormattedValue';\nimport { StickyPagination } from '../common/data/StickyPagination';\nimport { useEscalations } from '../../api/escalations';\nimport { schemaNeedsEnvelope } from '../../lib/schema-needs-envelope';\nimport { getDeep } from '../../lib/x-lt-bind';\nimport { typeColor } from '../../lib/type-color';\nimport { RefineDialog, type RefinePair } from './RefineDialog';\nimport {\n escalationDotClass,\n rowContext,\n RowActionButton,\n RefineTrigger,\n METADATA_TOKEN,\n type ColumnDef,\n type RowActionDef,\n} from './list-view/row-parts';\nimport { FacetTable, type EscalationGroup } from './list-view/FacetTable';\nimport type { LTEscalationRecord } from '../../api/types';\n\nexport { rowContext, rowRefinePairs } from './list-view/row-parts';\nexport type { ColumnDef, RowActionDef } from './list-view/row-parts';\nexport { FIELD_FORMATS } from '../common/display/FormattedValue';\n\n/**\n * EscalationListView — the role-authored rich view of an escalation list, driven\n * by a versioned `list_schema` (x-lt-* markup). The list-page analog of the\n * resolve form: the same `{{domain.path}}` token binding (via interpolateHelp)\n * against each row's context, and MarkdownRenderer for rich bodies.\n *\n * Layouts:\n * active-history — single live item as a card on the left + history column on right\n * active — just the single live item card (no history)\n * facet-table — full pending queue as a table, columns from x-lt-columns\n * facet-board — one card per x-lt-group-by facet value (an entity board:\n * machines, stations), rendered from each group's latest row\n */\n\ninterface CardDef {\n title?: string;\n subtitle?: string;\n body?: string;\n fields?: { label: string; value: string; format?: string }[];\n}\n\ninterface HistoryDef {\n row?: { title?: string; subtitle?: string; meta?: string };\n limit?: number;\n status?: string;\n}\n\n\ninterface BoardCardDef {\n title?: string;\n /** Status chip — any token (commonly {{escalation.subtype}}). */\n state?: string;\n fields?: { label: string; value: string; format?: string }[];\n}\n\n\nexport interface ListSchema {\n 'x-lt-layout'?: string;\n 'x-lt-help'?: string;\n 'x-lt-active'?: CardDef;\n 'x-lt-history'?: HistoryDef;\n 'x-lt-columns'?: ColumnDef[];\n /** facet-board: the \"domain.path\" whose value identifies each entity. */\n 'x-lt-group-by'?: string;\n /** facet-board: the per-entity card definition. */\n 'x-lt-card'?: BoardCardDef;\n /** The per-row action button (claim | view, label, claim duration). */\n 'x-lt-row-action'?: RowActionDef;\n /** facet-table: related sets, row detail sections (see shared/list-schema). */\n 'x-lt-related'?: Record<string, unknown>;\n 'x-lt-row-detail'?: unknown[];\n}\n\n/**\n * Repaint-only minute tick so `format: \"age\"` values stay current. Pure\n * re-render — no network. Mounted once at the view root, only when the\n * schema actually uses ages.\n */\nfunction useAgeTick(enabled: boolean): void {\n const [, setTick] = useState(0);\n useEffect(() => {\n if (!enabled) return;\n const t = window.setInterval(() => setTick((n) => n + 1), 60_000);\n return () => window.clearInterval(t);\n }, [enabled]);\n}\n\nfunction schemaUsesAge(schema: ListSchema): boolean {\n return [...(schema['x-lt-columns'] ?? []), ...(schema['x-lt-card']?.fields ?? [])]\n .some((f) => isAgeFormat(f.format));\n}\n\n\n\n\n\nfunction ActiveCard({ esc, card, rowAction, onOpen, forceView }: {\n esc: LTEscalationRecord;\n card: CardDef;\n rowAction?: RowActionDef;\n onOpen?: () => void;\n forceView?: boolean;\n}) {\n const ctx = rowContext(esc);\n const title = card.title ? interpolateHelp(card.title, ctx) : esc.type;\n return (\n <div>\n <div className=\"flex items-start justify-between gap-6\">\n <button onClick={onOpen} className=\"text-left group min-w-0\">\n <h3 className=\"heading-2 group-hover:text-accent transition-colors leading-tight\">\n {title}\n </h3>\n {card.subtitle && (\n <p className=\"text-xs text-text-tertiary mt-1.5\">{interpolateHelp(card.subtitle, ctx)}</p>\n )}\n </button>\n\n {/* The row action — one-click claim (then the detail page opens already\n claimed), or view for read-only templates. */}\n <RowActionButton row={esc} def={rowAction} onView={onOpen} prominent forceView={forceView} />\n </div>\n\n {card.fields && card.fields.length > 0 && (\n <dl className=\"flex flex-wrap gap-x-10 gap-y-4 mt-6\">\n {card.fields.map((f, i) => (\n <div key={i}>\n <dt className=\"text-2xs font-semibold uppercase tracking-widest text-text-tertiary\">{f.label}</dt>\n <dd className=\"text-xs text-text-primary mt-1\"><FieldValue raw={interpolateHelp(f.value, ctx)} /></dd>\n </div>\n ))}\n </dl>\n )}\n\n {card.body && (\n <div className=\"mt-7 pt-6 border-t border-surface-border/50\">\n <MarkdownRenderer content={interpolateHelp(card.body, ctx)} />\n </div>\n )}\n </div>\n );\n}\n\nfunction HistoryColumn({ role, def, onRowClick }: {\n role: string;\n def: HistoryDef;\n onRowClick?: (row: LTEscalationRecord) => void;\n}) {\n const [show, setShow] = useState(false);\n const query = useEscalations({\n role,\n status: def.status ?? 'resolved',\n sort_by: 'resolved_at',\n order: 'desc',\n limit: def.limit ?? 25,\n enabled: show,\n include: schemaNeedsEnvelope(def) ? 'envelope' : undefined,\n });\n const rows = query.data?.escalations ?? [];\n const total = query.data?.total ?? 0;\n const rowDef = def.row ?? {};\n\n if (!show) {\n return (\n <button\n onClick={() => setShow(true)}\n className=\"text-xs text-accent hover:underline\"\n data-testid=\"load-history\"\n >\n Load full history →\n </button>\n );\n }\n\n if (query.isLoading) {\n return <p className=\"text-xs text-text-tertiary italic\">Loading history…</p>;\n }\n\n if (rows.length === 0) {\n return <p className=\"text-xs text-text-tertiary italic\">No past revisions.</p>;\n }\n\n return (\n <div>\n <div className=\"divide-y divide-surface-border/40\">\n {rows.map((e) => {\n const ctx = rowContext(e);\n return (\n <button\n key={e.id}\n onClick={() => onRowClick?.(e)}\n className=\"w-full text-left py-2.5 group flex items-center gap-3\"\n >\n {/* Status as a bare outlined dot — colour carries the meaning. */}\n <span\n className={`w-2.5 h-2.5 shrink-0 rounded-full dot-ring ${escalationDotClass(e)}`}\n title={e.status}\n />\n <span className=\"min-w-0 flex-1\">\n <span className=\"block text-xs text-text-primary group-hover:text-accent transition-colors truncate\">\n {rowDef.title ? interpolateHelp(rowDef.title, ctx) : e.type}\n </span>\n {rowDef.subtitle && (\n <span className=\"block text-2xs text-text-tertiary truncate\">\n {interpolateHelp(rowDef.subtitle, ctx)}\n </span>\n )}\n </span>\n {rowDef.meta\n ? <span className=\"text-2xs text-text-tertiary shrink-0\">{interpolateHelp(rowDef.meta, ctx)}</span>\n : e.resolved_at && <DateValue date={e.resolved_at} format=\"relative\" className=\"text-2xs text-text-tertiary shrink-0 whitespace-nowrap\" />}\n </button>\n );\n })}\n </div>\n {total > rows.length && (\n <p className=\"text-2xs text-text-quaternary mt-3\">Showing {rows.length} of {total}.</p>\n )}\n </div>\n );\n}\n\n\n\nfunction SectionLabel({ children }: { children: React.ReactNode }) {\n return (\n <p className=\"text-2xs font-semibold uppercase tracking-widest text-text-tertiary mb-3\">{children}</p>\n );\n}\n\n// ── facet-board — one card per entity (machine, station) ─────────────────────\n\ninterface BoardGroup {\n key: string;\n /** The group's identity as stored (native type preserved for the facet URL). */\n rawValue: unknown;\n latest: LTEscalationRecord;\n count: number;\n}\n\n/**\n * Group rows by the resolved x-lt-group-by value; each card renders from the\n * group's most recent row (by created_at). Rows without the facet are skipped —\n * the board reflects the scope, it doesn't invent entities.\n */\nexport function groupBoardRows(rows: LTEscalationRecord[], groupBy: string): BoardGroup[] {\n const dot = groupBy.indexOf('.');\n const facetKey = groupBy.startsWith('metadata.') ? groupBy.slice('metadata.'.length) : null;\n const groups = new Map<string, BoardGroup>();\n for (const row of rows) {\n const ctx = rowContext(row);\n let v: unknown;\n try {\n v = dot === -1\n ? (ctx as unknown as Record<string, unknown>)[groupBy]\n : getDeep((ctx as unknown as Record<string, unknown>)[groupBy.slice(0, dot)], groupBy.slice(dot + 1));\n } catch {\n v = undefined;\n }\n if (v === undefined || v === null || v === '') continue;\n const key = String(v);\n const rawValue = facetKey ? (row.metadata?.[facetKey] ?? v) : v;\n const existing = groups.get(key);\n if (!existing) {\n groups.set(key, { key, rawValue, latest: row, count: 1 });\n } else {\n existing.count += 1;\n if (new Date(row.created_at) > new Date(existing.latest.created_at)) existing.latest = row;\n }\n }\n return [...groups.values()].sort((a, b) => a.key.localeCompare(b.key));\n}\n\n\nfunction FacetBoard({ schema, rows, role, onOpenDetail, onOpenGroup, onAddFacet, forceView }: {\n schema: ListSchema;\n rows: LTEscalationRecord[];\n role: string;\n forceView?: boolean;\n /** Plain card click — the group's latest row opens in the detail view. */\n onOpenDetail?: (row: LTEscalationRecord) => void;\n /** History affordances — receive a filtered table/timeline deep link. */\n onOpenGroup?: (url: string) => void;\n /** Shift+click — merge one facet into the live filter set (additive). */\n onAddFacet?: (key: string, value: unknown) => void;\n}) {\n const navigate = useNavigate();\n const groupBy = schema['x-lt-group-by'];\n const card = schema['x-lt-card'] ?? {};\n const rowAction = schema['x-lt-row-action'];\n const [refineGroup, setRefineGroup] = useState<BoardGroup | null>(null);\n\n if (!groupBy) {\n return <p className=\"text-xs text-text-tertiary italic\">facet-board needs an x-lt-group-by path.</p>;\n }\n const facetKey = groupBy.startsWith('metadata.') ? groupBy.slice('metadata.'.length) : null;\n const groups = groupBoardRows(rows, groupBy);\n if (groups.length === 0) {\n return <p className=\"text-xs text-text-tertiary italic\">No entities in scope.</p>;\n }\n\n // The card's refinable facts: the entity identity (the group-by facet)\n // plus every metadata-bound card field — one dialog per card, replacing\n // hover-revealed per-field icons (hover-only fails the iPad floor).\n const groupRefinePairs = (g: BoardGroup): RefinePair[] => {\n const pairs: RefinePair[] = [];\n if (facetKey) pairs.push({ key: facetKey, label: facetKey, value: g.rawValue });\n const seen = new Set(pairs.map((p) => p.key));\n for (const f of card.fields ?? []) {\n const bound = f.value.match(METADATA_TOKEN)?.[1];\n if (!bound || seen.has(bound)) continue;\n const raw = g.latest.metadata?.[bound];\n if (raw === undefined || raw === null || raw === '') continue;\n seen.add(bound);\n pairs.push({ key: bound, label: f.label, value: raw });\n }\n return pairs;\n };\n\n return (\n <div className=\"grid grid-cols-[repeat(auto-fill,minmax(15rem,1fr))] gap-4\" data-testid=\"facet-board\">\n {groups.map((g) => {\n const ctx = rowContext(g.latest);\n const title = card.title ? interpolateHelp(card.title, ctx) : g.key;\n const state = card.state ? interpolateHelp(card.state, ctx) : (g.latest.subtype || g.latest.status);\n const stateHue = typeColor(state);\n const refinable = groupRefinePairs(g).length > 0;\n\n const activate = (e: { shiftKey: boolean }) => {\n if (e.shiftKey && facetKey && onAddFacet) {\n onAddFacet(facetKey, g.rawValue);\n return;\n }\n onOpenDetail?.(g.latest);\n };\n\n return (\n <div\n key={g.key}\n role=\"button\"\n tabIndex={0}\n onClick={activate}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); activate(e); }\n }}\n title={facetKey ? 'Open the latest item · ⇧ click to filter the board' : 'Open the latest item'}\n className=\"group/card border-l-2 border-accent/30 bg-surface-sunken/40 rounded-[0.125em] px-4 py-3.5 cursor-pointer transition-colors hover:bg-surface-sunken/70 focus:outline-none focus-visible:ring-1 focus-visible:ring-accent/40\"\n data-testid=\"facet-board-card\"\n >\n <div className=\"flex items-center justify-between gap-2 mb-2.5\">\n <span className=\"text-2xs font-semibold uppercase tracking-wider text-text-secondary truncate\">\n {title}\n </span>\n <span className=\"flex items-center gap-1 shrink-0\">\n <span\n className=\"px-1.5 py-0.5 rounded text-2xs font-mono font-medium\"\n style={{ color: stateHue.text, backgroundColor: stateHue.bg }}\n title={state}\n >\n {state}\n </span>\n {refinable && <RefineTrigger onOpen={() => setRefineGroup(g)} className=\"-my-1 -mr-1\" />}\n </span>\n </div>\n {card.fields && card.fields.length > 0 && (\n <dl className=\"space-y-1\">\n {card.fields.map((f, i) => {\n const text = interpolateHelp(f.value, ctx);\n return (\n <div key={i} className=\"flex items-baseline justify-between gap-3\">\n <dt className=\"text-2xs uppercase tracking-wider text-text-quaternary shrink-0\">{f.label}</dt>\n <dd\n className=\"min-w-0 truncate text-2xs text-text-primary\"\n title={text && text !== EM_DASH ? text : undefined}\n >\n <FieldValue raw={text} format={f.format} />\n </dd>\n </div>\n );\n })}\n </dl>\n )}\n\n <div className=\"mt-3 flex justify-end\">\n <RowActionButton row={g.latest} def={rowAction} onView={() => onOpenDetail?.(g.latest)} forceView={forceView} />\n </div>\n </div>\n );\n })}\n\n <RefineDialog\n open={!!refineGroup}\n onClose={() => setRefineGroup(null)}\n role={role}\n pairs={refineGroup ? groupRefinePairs(refineGroup) : []}\n onNavigate={onOpenGroup ?? navigate}\n onAddFacet={onAddFacet}\n />\n </div>\n );\n}\n\nexport function EscalationListView({ role, listSchema, listSchemaVersion, activeEscalations, groups, onRowClick, onOpenGroup, onAddFacet, forceViewAction, total, page, totalPages, pageSize, onPageChange, onPageSizeChange }: {\n role: string;\n listSchema: ListSchema;\n /** The list schema version rendered; related sets read the same version. */\n listSchemaVersion?: number | null;\n activeEscalations: LTEscalationRecord[];\n /** facet-table grouped reads: the page's groups, in order. */\n groups?: EscalationGroup[] | null;\n onRowClick?: (row: LTEscalationRecord) => void;\n /** facet-board history affordances — receive a filtered deep link. */\n onOpenGroup?: (url: string) => void;\n /** facet-board ⇧ click — merge one facet into the live filter set. */\n onAddFacet?: (key: string, value: unknown) => void;\n /** Render claim row-actions as view actions. For surfaces listing rows the\n * viewer already holds (e.g. My Escalations), where a claim gesture is\n * inapplicable — the button opens the detail page instead. */\n forceViewAction?: boolean;\n total?: number;\n page?: number;\n totalPages?: number;\n pageSize?: number;\n onPageChange?: (page: number) => void;\n onPageSizeChange?: (size: number) => void;\n}) {\n const layout = listSchema['x-lt-layout'];\n const card = listSchema['x-lt-active'] ?? {};\n const rowAction = listSchema['x-lt-row-action'];\n const active = activeEscalations[0];\n const help = listSchema['x-lt-help'];\n useAgeTick(schemaUsesAge(listSchema));\n\n // The active item is a distinct surface on the page wash — the same card\n // treatment the detail page gives its form sections. The label heads the\n // card; the history column beside it stays a quiet chronicle on the wash.\n const activeBlock = (\n <div className=\"border border-surface-border/60 bg-surface-sunken rounded-[0.25em] p-4\">\n <SectionLabel>Active</SectionLabel>\n {active ? (\n <ActiveCard esc={active} card={card} rowAction={rowAction} onOpen={() => onRowClick?.(active)} forceView={forceViewAction} />\n ) : (\n <p className=\"text-xs text-text-tertiary italic\">No active item right now.</p>\n )}\n </div>\n );\n\n const header = help && active ? (\n <div className=\"mb-8\"><MarkdownRenderer content={interpolateHelp(help, rowContext(active))} /></div>\n ) : help ? (\n <div className=\"mb-8\"><MarkdownRenderer content={help} /></div>\n ) : null;\n\n if (layout === 'facet-table') {\n // The table stands alone — no header text above it. Instructions belong\n // in the form's help surfaces; totals live in the pagination bar.\n const resolvedTotal = total ?? activeEscalations.length;\n return (\n <div>\n <FacetTable schema={listSchema as Record<string, unknown>} rows={activeEscalations} groups={groups} role={role} version={listSchemaVersion} onRowClick={onRowClick} onAddFacet={onAddFacet} forceView={forceViewAction} />\n {page !== undefined && totalPages !== undefined && onPageChange && (\n <StickyPagination\n page={page}\n totalPages={totalPages}\n onPageChange={onPageChange}\n total={resolvedTotal}\n pageSize={pageSize ?? 25}\n onPageSizeChange={onPageSizeChange}\n />\n )}\n </div>\n );\n }\n\n if (layout === 'facet-board') {\n return (\n <div>\n {header}\n <FacetBoard\n schema={listSchema}\n rows={activeEscalations}\n role={role}\n onOpenDetail={onRowClick}\n onOpenGroup={onOpenGroup}\n onAddFacet={onAddFacet}\n forceView={forceViewAction}\n />\n {page !== undefined && totalPages !== undefined && onPageChange && totalPages > 1 && (\n <StickyPagination\n page={page}\n totalPages={totalPages}\n onPageChange={onPageChange}\n total={total ?? activeEscalations.length}\n pageSize={pageSize ?? 25}\n onPageSizeChange={onPageSizeChange}\n />\n )}\n </div>\n );\n }\n\n if (layout === 'active-history') {\n return (\n <div>\n {header}\n <div className=\"grid grid-cols-1 @split:grid-cols-[1.6fr_1fr] gap-8 @split:gap-12 items-start\">\n {activeBlock}\n {/* pt-4 seats the History label on the Active label's optical line\n (the card's own padding provides that inset on the left). */}\n <div className=\"@split:pt-4\">\n <SectionLabel>History</SectionLabel>\n <HistoryColumn role={role} def={listSchema['x-lt-history'] ?? {}} onRowClick={onRowClick} />\n </div>\n </div>\n </div>\n );\n }\n\n // \"active\" (or any non-table layout): just the active card.\n return (\n <div>\n {header}\n {activeBlock}\n </div>\n );\n}\n","import { useState } from 'react';\nimport { Link } from 'react-router-dom';\nimport { Circle, Bell, Clock, ListFilter, Search, History } from 'lucide-react';\nimport { EntityTimelinePanel } from '../../components/escalation/EntityTimelinePanel';\nimport { useShellPanelOptional } from '../../hooks/useShellPanel';\nimport type { Column } from '../../components/common/data/DataTable';\nimport { FilterBar, FilterSelect, FilterInput, FilterDivider } from '../../components/common/data/FilterBar';\nimport { PriorityBadge } from '../../components/common/display/PriorityBadge';\nimport { RolePill } from '../../components/common/display/RolePill';\nimport { WorkflowPill } from '../../components/common/display/WorkflowPill';\nimport { UserName } from '../../components/common/display/UserName';\nimport { CountdownTimer } from '../../components/common/display/CountdownTimer';\nimport { formatAgoCompact } from '../../lib/format';\nimport { isEffectivelyClaimed, isAckEscalation } from '../../lib/escalation';\nimport { metadataFacetUrl } from '../../lib/facet-url';\nimport type { LTEscalationRecord } from '../../api/types';\n\nexport interface EscalationColumnOpts {\n highlightKeys?: string[];\n}\n\n// Shared cell text: a consistent resting shade for every cell, sharpening to\n// the primary text colour when the row is hovered. Cells (and pills via their\n// `inherit` tone) all read this single source so the whole row darkens as one.\nconst CELL_TEXT = 'text-text-secondary transition-colors group-hover/row:text-text-primary';\n\n/** Status dot — rendered inline before summary. */\nfunction StatusDot({ row }: { row: LTEscalationRecord }) {\n if (isAckEscalation(row)) {\n const color = row.status === 'resolved' ? 'text-status-success' : 'text-text-tertiary';\n return <Bell className={`w-3 h-3 shrink-0 ${color}`} />;\n }\n if (row.status === 'resolved') {\n return <Circle className=\"w-2.5 h-2.5 shrink-0 text-status-success\" strokeWidth={2.5} />;\n }\n if (row.status === 'cancelled') {\n return <Circle className=\"w-2.5 h-2.5 shrink-0 text-status-error\" strokeWidth={2.5} />;\n }\n if (row.status === 'expired') {\n return <Circle className=\"w-2.5 h-2.5 shrink-0 text-text-tertiary\" strokeWidth={2.5} />;\n }\n if (isEffectivelyClaimed(row)) {\n return <Circle className=\"w-2.5 h-2.5 shrink-0 text-status-warning\" strokeWidth={2.5} />;\n }\n // pending (unclaimed)\n return <Circle className=\"w-2.5 h-2.5 shrink-0 text-status-active\" strokeWidth={2.5} />;\n}\n\n/** Key/value metadata dict with 1 row collapsed by default, expand for the rest. */\nexport function MetadataCell({\n metadata,\n role,\n highlightKeys,\n}: {\n metadata: Record<string, unknown> | null;\n role: string;\n highlightKeys?: string[];\n}) {\n const [expanded, setExpanded] = useState(false);\n // Null outside the shell (tests, standalone renders) — the timeline\n // affordance simply doesn't render there.\n const shell = useShellPanelOptional();\n\n if (!metadata || Object.keys(metadata).length === 0) {\n return <span className=\"text-2xs text-text-tertiary\">—</span>;\n }\n\n const hl = highlightKeys ?? [];\n // Highlighted keys first, then the rest in insertion order.\n const allKeys = [\n ...hl.filter((k) => k in metadata),\n ...Object.keys(metadata).filter((k) => !hl.includes(k)),\n ];\n\n const shown = expanded ? allKeys : allKeys.slice(0, 1);\n const hiddenCount = allKeys.length - 1;\n\n return (\n <div className=\"w-full\" onClick={(e) => e.stopPropagation()}>\n <div className=\"space-y-px\">\n {shown.map((k, i) => {\n const sv = typeof metadata[k] === 'object' && metadata[k] !== null\n ? JSON.stringify(metadata[k])\n : String(metadata[k]);\n const isHl = hl.includes(k);\n const isLastShown = i === shown.length - 1;\n return (\n <div key={k} className=\"group/mrow flex items-center gap-1 min-w-0\">\n <span\n className={`shrink-0 w-14 text-2xs font-mono uppercase tracking-wide truncate ${isHl ? 'text-accent' : 'text-text-tertiary'}`}\n title={k}\n >\n {k}\n </span>\n <span\n className={`flex-1 min-w-0 text-2xs font-medium truncate ${isHl ? 'text-text-primary' : 'text-text-secondary'}`}\n title={sv}\n >\n {sv}\n </span>\n <span className=\"flex items-center gap-px shrink-0 opacity-50 group-hover/mrow:opacity-100 transition-opacity\">\n <Link\n to={metadataFacetUrl(k, metadata[k], role)}\n className=\"p-0.5 rounded text-text-quaternary hover:text-accent transition-colors\"\n title={`Filter ${role}: ${k} = ${sv}`}\n onClick={(ev) => ev.stopPropagation()}\n >\n <ListFilter className=\"w-3 h-3\" />\n </Link>\n <Link\n to={metadataFacetUrl(k, metadata[k])}\n className=\"p-0.5 rounded text-text-quaternary hover:text-accent transition-colors\"\n title={`Search all: ${k} = ${sv}`}\n onClick={(ev) => ev.stopPropagation()}\n >\n <Search className=\"w-3 h-3\" />\n </Link>\n {/* filter-present / search-present / history-past — the third\n verb of the triad. String values only: the timeline's GIN\n containment match only serves JSON-string facets. */}\n {shell && typeof metadata[k] === 'string' && (\n <button\n className=\"p-0.5 rounded text-text-quaternary hover:text-accent transition-colors\"\n title={`Timeline: every station ${sv} has moved through`}\n onClick={(ev) => {\n ev.stopPropagation();\n shell.setPanel(\n <EntityTimelinePanel facetKey={k} value={metadata[k] as string} role={role} />,\n { key: 'entity-timeline', width: 420 },\n );\n }}\n >\n <History className=\"w-3 h-3\" />\n </button>\n )}\n </span>\n {/* +N inline at end of single visible row when collapsed */}\n {!expanded && hiddenCount > 0 && (\n <button\n onClick={(ev) => { ev.stopPropagation(); setExpanded(true); }}\n className=\"shrink-0 text-2xs text-text-quaternary hover:text-accent transition-colors font-mono\"\n title={`Show ${hiddenCount} more fields`}\n >\n +{hiddenCount}\n </button>\n )}\n {/* ↑ inline at end of last row when expanded */}\n {expanded && isLastShown && hiddenCount > 0 && (\n <button\n onClick={(ev) => { ev.stopPropagation(); setExpanded(false); }}\n className=\"shrink-0 text-2xs text-text-quaternary hover:text-accent transition-colors\"\n title=\"Show less\"\n >\n ↑\n </button>\n )}\n </div>\n );\n })}\n </div>\n </div>\n );\n}\n\n/** Build the shared column set, optionally wiring metadata filter callbacks. */\nexport function makeEscalationColumns(opts: EscalationColumnOpts = {}): Column<LTEscalationRecord>[] {\n return [\n {\n key: 'description',\n label: 'Summary',\n priority: 1,\n render: (row) => (\n <div className=\"flex items-center gap-2 overflow-hidden\">\n <span className=\"shrink-0\"><StatusDot row={row} /></span>\n <span className={`truncate text-xs ${CELL_TEXT}`}>{row.description || row.type}</span>\n </div>\n ),\n className: 'max-w-0',\n },\n // The manufacturing-floor column budget: identity, owner, urgency, age.\n // Everything else (workflow type, metadata, exact timestamps) lives in\n // the facet drawer and the detail page — never as a scrolling column.\n {\n key: 'assigned_to',\n label: 'Assignee',\n priority: 2,\n render: (row) => (row.assigned_to\n ? <UserName userId={row.assigned_to} className={`block truncate text-xs ${CELL_TEXT}`} />\n : <span className=\"text-xs text-text-quaternary\">—</span>),\n className: 'w-36 max-w-[9rem]',\n },\n {\n key: 'role',\n label: 'Role',\n priority: 2,\n render: (row) => (\n <span className={CELL_TEXT}>\n <RolePill role={row.role} size=\"md\" tone=\"inherit\" />\n </span>\n ),\n className: 'w-44 min-w-[11rem]',\n },\n {\n key: 'priority',\n label: 'Pri',\n priority: 2,\n render: (row) => (\n <span className={CELL_TEXT}>\n <PriorityBadge priority={row.priority} size=\"sm\" tone=\"inherit\" />\n </span>\n ),\n className: 'w-10',\n },\n // Enrichment columns — the jumping-off facets. The budget governs the\n // floor: these return only when the table has room (@split / @wall),\n // and in card mode they fold to pairs. The metadata cell carries the\n // clickable refine icons: filter within the role, search across roles\n // (admins), shift+click to AND facets.\n {\n key: 'workflow_type',\n label: 'Workflow',\n priority: 2,\n showFrom: 'split',\n render: (row) => <WorkflowPill type={row.workflow_type || row.type} />,\n className: 'w-40 whitespace-nowrap',\n },\n {\n key: 'metadata',\n label: 'Metadata',\n priority: 2,\n showFrom: 'wall',\n render: (row) => (\n <MetadataCell\n metadata={row.metadata}\n role={row.role}\n highlightKeys={opts.highlightKeys}\n />\n ),\n className: 'w-80 max-w-[19rem] align-top',\n },\n {\n key: 'created_at',\n label: 'Ago',\n priority: 1,\n render: (row) => (\n <span className={`text-xs tabular-nums ${CELL_TEXT}`} title={row.created_at}>\n {formatAgoCompact(row.created_at)}\n </span>\n ),\n className: 'w-14 whitespace-nowrap',\n },\n ];\n}\n\n/** Base columns shared by all escalation list pages (no filter callback). */\nexport const ESCALATION_COLUMNS: Column<LTEscalationRecord>[] = makeEscalationColumns();\n\n/** Time-remaining column for claimed escalations — aligns with checkbox column on All Escalations. */\nexport const TIME_LEFT_COLUMN: Column<LTEscalationRecord> = {\n key: 'expires',\n label: (<Clock className=\"w-3.5 h-3.5 text-text-tertiary\" />) as any,\n render: (row) =>\n row.assigned_until ? (\n <CountdownTimer until={row.assigned_until} />\n ) : (\n <span className=\"text-xs text-text-tertiary\">—</span>\n ),\n className: 'w-16 whitespace-nowrap',\n priority: 1,\n};\n\n/** Status icon column — color-coded filled circle, or bell for ACK/notification escalations. */\nexport const STATUS_COLUMN: Column<LTEscalationRecord> = {\n key: 'status',\n label: '',\n render: (row) => {\n if (isAckEscalation(row)) {\n const color = row.status === 'resolved' ? 'text-status-success' : 'text-text-tertiary';\n return <Bell className={`w-3 h-3 ${color}`} />;\n }\n if (row.status === 'resolved') {\n return <Circle className=\"w-2.5 h-2.5 text-status-success\" strokeWidth={2.5} />;\n }\n if (isEffectivelyClaimed(row)) {\n return <Circle className=\"w-2.5 h-2.5 text-status-warning\" strokeWidth={2.5} />;\n }\n // pending (unclaimed)\n return <Circle className=\"w-2.5 h-2.5 text-text-tertiary\" strokeWidth={2.5} />;\n },\n className: 'w-8',\n priority: 1,\n};\n\n/** Claimed-only status icon (always orange, or bell for ACK). */\nexport const CLAIMED_STATUS_COLUMN: Column<LTEscalationRecord> = {\n key: 'status',\n label: '',\n render: (row) =>\n isAckEscalation(row)\n ? <Bell className=\"w-3 h-3 text-status-warning\" />\n : <Circle className=\"w-2.5 h-2.5 text-status-warning\" strokeWidth={2.5} />,\n className: 'w-8',\n priority: 1,\n};\n\n/** Priority filter options shared by both pages. */\nexport const PRIORITY_OPTIONS = [\n { value: '1', label: 'P1' },\n { value: '2', label: 'P2' },\n { value: '3', label: 'P3' },\n { value: '4', label: 'P4' },\n];\n\n/** Status filter options for escalation list pages. `all` spans every status so a\n * metadata search (e.g. one order id) returns its escalations regardless of status. */\nexport const STATUS_OPTIONS = [\n { value: 'all', label: 'All' },\n { value: 'available', label: 'Available' },\n { value: 'claimed', label: 'Claimed' },\n { value: 'resolved', label: 'Resolved' },\n { value: 'cancelled', label: 'Cancelled' },\n { value: 'expired', label: 'Expired' },\n];\n\n/** Shared filter bar for escalation list pages. */\nexport function EscalationFilterBar({\n filters,\n setFilter,\n roles,\n types,\n showStatus = false,\n showSearch = true,\n showRole = true,\n actions,\n}: {\n filters: { role: string; type: string; priority: string; status?: string; search?: string };\n setFilter: (key: any, value: string) => void;\n roles: string[];\n types: string[];\n showStatus?: boolean;\n // Free-text search lives here by default, but the faceted page folds it into\n // the drawer instead so there's a single search surface.\n showSearch?: boolean;\n /** Kiosk sessions hide the role filter — the session IS the role. */\n showRole?: boolean;\n actions?: React.ReactNode;\n}) {\n // Non-default filters power the folded Filters button's badge.\n const activeFilterCount = [\n filters.role,\n filters.type,\n filters.priority,\n filters.status && filters.status !== 'all' ? filters.status : '',\n filters.search ?? '',\n ].filter(Boolean).length;\n\n return (\n <FilterBar actions={actions} activeFilterCount={activeFilterCount}>\n {showStatus && (\n <>\n <FilterSelect\n label=\"Status\"\n value={filters.status ?? ''}\n onChange={(v) => setFilter('status', v)}\n options={STATUS_OPTIONS}\n />\n <FilterDivider />\n </>\n )}\n {/* Role is the queue's primary facet — URL-driven (?role=). Pages whose\n title doubles as a queue selector share the same param, so the two\n controls mirror each other. Kiosk sessions hide it: the session IS\n the role. */}\n {showRole && (\n <>\n <FilterSelect\n label=\"Role\"\n value={filters.role}\n onChange={(v) => setFilter('role', v)}\n options={roles.map((r) => ({ value: r, label: r }))}\n />\n <FilterDivider />\n </>\n )}\n <FilterSelect\n label=\"Priority\"\n value={filters.priority}\n onChange={(v) => setFilter('priority', v)}\n options={PRIORITY_OPTIONS}\n />\n <FilterDivider />\n <FilterSelect\n label=\"Workflow Type\"\n value={filters.type}\n onChange={(v) => setFilter('type', v)}\n options={types.map((t) => ({ value: t, label: t }))}\n />\n {showSearch && (\n <>\n <FilterDivider />\n <FilterInput\n label=\"Search\"\n value={filters.search ?? ''}\n onChange={(v) => setFilter('search', v)}\n placeholder=\"ID, workflow, origin…\"\n />\n </>\n )}\n </FilterBar>\n );\n}\n"],"names":["PALETTE","hash","str","h","i","typeColor","typeName","FIND_THRESHOLD","RefineDialog","open","onClose","role","pairs","onNavigate","onAddFacet","selected","setSelected","useState","find","setFind","prevOpen","setPrevOpen","bound","p","preset","needle","visible","t","toggle","key","prev","next","chosen","facets","none","go","url","jsx","Modal","jsxs","Search","e","on","Check","metadataFacetsUrl","useRelatedAggregates","ids","version","enabled","sorted","useQuery","apiFetch","useRelatedRows","id","set","limit","SINGLE_TOKEN","ANY_TOKEN","MISSING_VALUE","parseJsonObject","value","parsed","rowTemplateContext","row","readToken","path","ctx","dot","domain","HELP_DOMAINS","root","getDeep","resolveTemplateValue","single","raw","text","interpolateHelp","resolveRelatedFacets","narrow","out","resolved","splitLabel","col","_a","SPLIT_PATHS","_b","RelatedCell","agg","drillUrl","EM_DASH","isExtremeAggregate","FormattedValue","countText","relatedCountText","order","splits","n","a","x","b","y","restricted","title","r","href","chip","Link","ROLE_FORMAT","cellText","template","rowContext","interpolateItemTemplate","DetailSection","host","section","roleLabels","navigate","useNavigate","query","rows","labels","_c","hostValues","v","columns","values","displayRoleTitle","target","DataTable","RowDetail","sections","withOpenMembers","members","m","buildTableRows","groups","byId","g","numeric","nums","foldColumnText","fold","GROUP_FOLDS","mergeAggregates","aggs","aggregate","present","k","foldExtreme","distinctByMatch","seen","match","safeRelations","schema","readListSchemaRelations","RelatedFacetTable","props","related","sets","useRelatedSetEvents","FacetTableBody","FacetTable","relations","useMemo","onRowClick","forceView","setsLoading","columnDefs","rowAction","refineRow","setRefineRow","setOpen","tableRows","lines","grouped","expandable","opens","relatedCell","name","counted","relatedAggregateKey","relatedRole","actionLabel","lead","ChevronRight","escalationDotClass","c","IDENTITY_COLUMN_WIDTH","indent","rowRefinePairs","RefineTrigger","actionColumnWidth","RowActionButton","rowClassName","renderExpansion","Fragment","useAgeTick","setTick","useEffect","schemaUsesAge","f","isAgeFormat","ActiveCard","esc","card","onOpen","FieldValue","MarkdownRenderer","HistoryColumn","def","show","setShow","useEscalations","schemaNeedsEnvelope","total","rowDef","DateValue","SectionLabel","children","groupBoardRows","groupBy","facetKey","rawValue","existing","FacetBoard","onOpenDetail","onOpenGroup","refineGroup","setRefineGroup","groupRefinePairs","METADATA_TOKEN","state","stateHue","refinable","activate","EscalationListView","listSchema","listSchemaVersion","activeEscalations","forceViewAction","page","totalPages","pageSize","onPageChange","onPageSizeChange","layout","active","help","activeBlock","header","resolvedTotal","StickyPagination","CELL_TEXT","StatusDot","isAckEscalation","color","Bell","Circle","isEffectivelyClaimed","MetadataCell","metadata","highlightKeys","expanded","setExpanded","shell","useShellPanelOptional","hl","allKeys","shown","hiddenCount","sv","isHl","isLastShown","metadataFacetUrl","ev","ListFilter","EntityTimelinePanel","History","makeEscalationColumns","opts","UserName","RolePill","PriorityBadge","WorkflowPill","formatAgoCompact","ESCALATION_COLUMNS","TIME_LEFT_COLUMN","Clock","CountdownTimer","PRIORITY_OPTIONS","STATUS_OPTIONS","EscalationFilterBar","filters","setFilter","roles","types","showStatus","showSearch","showRole","actions","activeFilterCount","FilterBar","FilterSelect","FilterDivider","FilterInput"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import{j as E,a as w}from"./vendor-query-DvWWuNIB.js";import{a as Q}from"./StatusBadge-DHVwxre2.js";import{r as J}from"./index-BaCDL5fh.js";import{b as V}from"./vendor-icons-C_DQEeBy.js";import{u as tt,a as et}from"./vendor-react-_9U4mKFr.js";const nt={LINK:"link",ESCALATION:"escalation",ESCALATION_LIST:"escalation-list",INVOKE:"invoke",ROSTER:"roster"},rt=new Set(Object.values(nt));function st(t){return typeof t=="string"&&rt.has(t)}function ot(t){return st(t==null?void 0:t["x-lt-widget"])}const it=new Set(["__proto__","constructor","prototype"]);function U(t){const e=[];for(const n of t.split(".")){const r=n.match(/^([^[\]]*)((?:\[\d+\])*)$/);if(!r)throw new Error(`invalid x-lt-bind path segment: "${n}"`);const[,o,s]=r;if(o){if(it.has(o))throw new Error(`x-lt-bind path may not target "${o}"`);e.push({key:o})}for(const i of s.match(/\d+/g)??[])e.push({index:Number(i)})}if(e.length===0)throw new Error(`empty x-lt-bind path: "${t}"`);return e}function at(t,e,n){const r=U(e);let o=t;for(let i=0;i<r.length-1;i++){const l=r[i],u=r[i+1],c="key"in l?l.key:l.index,d="index"in u;(o[c]==null||typeof o[c]!="object")&&(o[c]=d?[]:{}),o=o[c]}const s=r[r.length-1];o["key"in s?s.key:s.index]=n}function S(t,e){let n=t;for(const r of U(e)){if(n==null||typeof n!="object")return;n=n["key"in r?r.key:r.index]}return n}function Y(t,e){const n=e==null?void 0:e["x-lt-bind"];return typeof n=="string"&&n.length>0?n:t}function Wt(t,e){const n=e==null?void 0:e.properties;if(!n)return{...t};const r={};for(const[o,s]of Object.entries(n))o in t&&(ot(s)||at(r,Y(o,s),t[o]));return r}function Kt(t,e){const n=e==null?void 0:e.properties;if(!n)return t?{...t}:{};const r={};for(const[o,s]of Object.entries(n)){const i=S(t,Y(o,s));i!==void 0&&(r[o]=i)}return r}const lt=["escalation","metadata","envelope","payload","resolver","lookup","input","roster"],ct=/\{\{\s*([^{}]+?)\s*\}\}/g,_="—";function I(t){if(t==null)return _;if(typeof t=="string")return t;if(typeof t=="number"||typeof t=="boolean")return String(t);try{return JSON.stringify(t)}catch{return _}}function P(t,e){return t.replace(ct,(n,r)=>{const o=r.indexOf("."),s=o===-1?r:r.slice(0,o);if(!lt.includes(s))return _;const i=e[s];if(o===-1)return I(i);try{return I(S(i,r.slice(o+1)))}catch{return _}})}function ut(t){const e=t==null?void 0:t["x-lt-help"];if(typeof e=="string"&&e.trim().length>0)return e;const n=t==null?void 0:t["x-lt-context"];return typeof n=="string"&&n.trim().length>0?n:null}function Xt(t,e){const n=ut(t);return n?P(n,e):null}function Ht({isTerminal:t,status:e,claimed:n,claimedByMe:r}){return t?e==="cancelled"?"This escalation was cancelled. The record is shown for reference.":"This escalation has been resolved. The submitted form is shown for reference.":r?"You have claimed this escalation. Fill out the form and submit to resolve it.":n?"Another user has claimed this escalation. It unlocks if their claim expires or is released.":"Claim this escalation to enable the form."}function Ft(t){if(!t)return!1;try{const e=JSON.stringify(t);return e.includes("envelope.")||e.includes("payload.")}catch{return!1}}function q(t){return!!(t.assigned_to&&t.assigned_until&&new Date(t.assigned_until)>new Date)}function Gt(t){return!t.workflow_type}function ft(t){return t.replace(/[_\-.]+/g," ").replace(/([a-z\d])([A-Z])/g,"$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g,"$1 $2").replace(/([a-zA-Z])(\d)/g,"$1 $2").trim().split(/\s+/).filter(Boolean).map(n=>n===n.toUpperCase()&&n.length>1?n:n.charAt(0).toUpperCase()+n.slice(1)).join(" ")}function Bt(t){return t.status==="pending"?q(t)?"bg-status-claimed-graphic":"bg-status-active":Q[t.status]??"bg-status-active"}function zt(t){const e=n=>{if(!n)return null;try{const r=JSON.parse(n);return r&&typeof r=="object"?r:null}catch{return null}};return{escalation:t,metadata:t.metadata??null,envelope:e(t.envelope),payload:e(t.escalation_payload),resolver:e(t.resolver_payload)}}const Zt="200px";function wt(t){return`${Math.max(6,Math.round(t.length*.55+3.5))}rem`}const dt=30;function mt(t){return t.status==="pending"&&!q(t)}function Qt({row:t,def:e,onView:n,prominent:r,forceView:o}){const s=(e==null?void 0:e.action)??"claim",i=o?"view":s,l=s===i&&(e!=null&&e.label)?e.label:i==="claim"?"Claim":"View",u=J(),c=tt(),d=et(),[b,M]=w.useState(""),L=i==="claim"&&!mt(t),G=z=>{if(z.stopPropagation(),i==="view"){n==null||n();return}if(e!=null&&e.submitOnClaim){c(`/escalations/detail/${t.id}`,{state:{autoStart:!0,durationMinutes:e==null?void 0:e.durationMinutes,from:d.pathname}});return}M(""),u.mutate({id:t.id,durationMinutes:(e==null?void 0:e.durationMinutes)??dt},{onSuccess:()=>n==null?void 0:n(),onError:Z=>M(Z.message)})},B=r?"btn-primary text-xs shrink-0 disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:bg-accent":"px-2 py-0.5 rounded text-2xs font-medium text-accent/70 border border-accent/30 enabled:hover:text-accent enabled:hover:border-accent/60 enabled:hover:bg-accent/5 transition-colors disabled:opacity-50 disabled:cursor-not-allowed whitespace-nowrap";return E.jsxs("span",{className:"inline-flex flex-col items-end gap-0.5",children:[E.jsx("button",{type:"button",onClick:G,disabled:u.isPending||L,title:L?t.status==="pending"?"claimed":t.status:void 0,className:B,"data-testid":"row-action-button",children:u.isPending?"Claiming…":l}),b&&E.jsx("span",{className:"text-2xs text-status-error","data-testid":"row-action-error",children:b})]})}const yt=/^\{\{\s*metadata\.([a-zA-Z0-9_]+)\s*\}\}$/;function D(t){return typeof t=="string"&&t!==""||typeof t=="number"||typeof t=="boolean"}function Jt(t,e){var s;const n=[],r=new Set,o=t.metadata??{};for(const i of e){const l=typeof i.value=="string"?(s=i.value.match(yt))==null?void 0:s[1]:void 0;if(!l||r.has(l))continue;const u=o[l];D(u)&&(r.add(l),n.push({key:l,label:i.label,value:u,bound:!0}))}for(const[i,l]of Object.entries(o))r.has(i)||!D(l)||(r.add(i),n.push({key:i,label:ft(i),value:l}));return n}function Vt({onOpen:t,className:e=""}){return E.jsx("button",{type:"button",onClick:n=>{n.stopPropagation(),t()},className:`p-1.5 rounded text-text-quaternary/70 hover:text-accent hover:bg-surface-hover transition-colors ${e}`,title:"Refine — filter or search by this row's values","aria-label":"Refine — filter or search by this row's values","data-testid":"row-refine",children:E.jsx(V,{className:"w-3.5 h-3.5",strokeWidth:1.5})})}const T={RELATED:"x-lt-related",COLUMNS:"x-lt-columns",ROW_DETAIL:"x-lt-row-detail",GROUP_BY:"x-lt-group-by",LAYOUT:"x-lt-layout"},p={ITEMS:"items",QUERY:"query"},x={COUNT:"count",MIN:"min",MAX:"max"},gt={FIRST:"first",MIN:"min",MAX:"max",SUM:"sum",COUNT:"count",DISTINCT:"distinct"},f={ROLE:"role",METADATA:"metadata.",PAYLOAD:"payload.",RECIPROCAL_METADATA:"reciprocal.metadata."},y={MAX_SETS:4,MAX_QUERY_ROLES:12,MAX_ROW_DETAIL_SECTIONS:4,ROWS_MAX:100},pt="facet-table",W="default",At=/^\{\{\s*([^{}]+?)\s*\}\}$/,N="item.",bt=/^[a-zA-Z0-9_]+$/,Et=/^[a-zA-Z0-9_]+$/,Tt=/\{n\}/g;function O(t){return t===x.MIN||t===x.MAX}function K(t,e){var o;if(typeof e!="string")return null;const n=(o=e.match(At))==null?void 0:o[1];if(!n)return null;if(t===p.ITEMS){if(!n.startsWith(`${N}${f.PAYLOAD}`))return null;const s=n.slice(N.length+f.PAYLOAD.length);return s&&s.split(".").every(i=>bt.test(i))?`${f.PAYLOAD}${s}`:null}if(!n.startsWith(f.METADATA))return null;const r=n.slice(f.METADATA.length);return Et.test(r)?n:null}function te(t,e){return O(t.aggregate)?`${t.aggregate}:${K(e,t.value)??""}`:t.splitBy??""}function ee(t,e){if(!t)return null;const n=t[String(e)]??t[W];return n===void 0?null:n.replace(Tt,String(e))}function ne(t,e){if(!e.length)return;const n=t===x.MIN;if(e.every(o=>typeof o=="number"))return n?Math.min(...e):Math.max(...e);const r=e.map(String).sort((o,s)=>o<s?-1:o>s?1:0);return n?r[0]:r[r.length-1]}const h=/^[a-zA-Z0-9_]+$/,ht=/^[a-zA-Z][a-zA-Z0-9_-]{0,47}$/,_t=/^[a-zA-Z0-9_]+$/,xt=/^(0|[1-9][0-9]*)$/;class $t extends Error{}function a(t){throw new $t(t)}function m(t){return!!t&&typeof t=="object"&&!Array.isArray(t)}function A(t){return typeof t=="string"&&t.trim().length>0}function Ot(t){return t.length>0&&t.split(".").every(e=>_t.test(e))}function St(t,e){return t===p.QUERY?e===f.ROLE||e.startsWith(f.METADATA)&&h.test(e.slice(f.METADATA.length))?null:`splitBy "${e}" on a query set must be "role" or "metadata.<key>"`:e.startsWith(f.PAYLOAD)&&Ot(e.slice(f.PAYLOAD.length))||e.startsWith(f.RECIPROCAL_METADATA)&&h.test(e.slice(f.RECIPROCAL_METADATA.length))?null:`splitBy "${e}" on an items set must be "payload.<path>" or "reciprocal.metadata.<key>"`}function Mt(t,e){if(ht.test(t)||a(`x-lt-related name "${t}" must start with a letter (letters, digits, _ or -)`),m(e)||a(`x-lt-related.${t} must be an object`),e.source===p.ITEMS)return e.query!==void 0&&a(`x-lt-related.${t}: an items set takes no query`),{source:p.ITEMS};e.source!==p.QUERY&&a(`x-lt-related.${t}.source must be "items" or "query"`);const n=e.query;m(n)||a(`x-lt-related.${t}.query is required for a query set`);const r=n.roles!==void 0,o=n.segment!==void 0;if(r===o&&a(`x-lt-related.${t}.query takes exactly one of roles or segment`),r){const s=n.roles;(!Array.isArray(s)||s.length===0||s.length>y.MAX_QUERY_ROLES||!s.every(A))&&a(`x-lt-related.${t}.query.roles must be 1..${y.MAX_QUERY_ROLES} role names`)}else A(n.segment)||a(`x-lt-related.${t}.query.segment must be a role name`);(!m(n.facets)||Object.keys(n.facets).length===0)&&a(`x-lt-related.${t}.query.facets must name at least one facet`);for(const[s,i]of Object.entries(n.facets))h.test(s)||a(`x-lt-related.${t}.query.facets key "${s}" must be letters, digits or _`),(i===null||typeof i=="object")&&a(`x-lt-related.${t}.query.facets.${s} must be a scalar or template`);if(n.narrow!==void 0){(!m(n.narrow)||Object.keys(n.narrow).length===0)&&a(`x-lt-related.${t}.query.narrow must name at least one facet`);for(const[s,i]of Object.entries(n.narrow))h.test(s)||a(`x-lt-related.${t}.query.narrow key "${s}" must be letters, digits or _`),s in n.facets&&a(`x-lt-related.${t}.query.narrow.${s} is already a required facet`),(i===null||typeof i=="object")&&a(`x-lt-related.${t}.query.narrow.${s} must be a scalar or template`)}return n.status!==void 0&&!A(n.status)&&a(`x-lt-related.${t}.query.status must be a status`),{source:p.QUERY,query:{...r?{roles:[...n.roles]}:{segment:n.segment},facets:{...n.facets},...n.narrow!==void 0?{narrow:{...n.narrow}}:{},...n.status!==void 0?{status:n.status}:{}}}}function Lt(t,e,n){const r=t.related;(!A(r)||!e[r])&&a(`${n}.related must name a set declared in x-lt-related`),t.aggregate!==void 0&&t.aggregate!==x.COUNT&&!O(t.aggregate)&&a(`${n}.aggregate must be "count", "min" or "max"`);const o=e[r].source;if(O(t.aggregate)?(K(o,t.value)||a(o===p.ITEMS?`${n}.value must be "{{item.payload.<path>}}" on an items set`:`${n}.value must be "{{metadata.<key>}}" on a query set`),t.splitBy!==void 0&&a(`${n}: a ${t.aggregate} column takes no splitBy`),t.display!==void 0&&a(`${n}: display applies to a count column`)):t.value!==void 0&&a(`${n}.value applies to a min or max column`),t.format!==void 0&&typeof t.format!="string"&&a(`${n}.format must be a format name`),t.display!==void 0&&(!m(t.display)||Object.keys(t.display).length===0||!Object.entries(t.display).every(([s,i])=>(s===W||xt.test(s))&&typeof i=="string"))&&a(`${n}.display must map counts (or "default") to display text`),t.splitBy!==void 0){A(t.splitBy)||a(`${n}.splitBy must be a path`);const s=St(e[r].source,t.splitBy);s&&a(`${n}: ${s}`)}return t.labels!==void 0&&(!m(t.labels)||!Object.values(t.labels).every(s=>typeof s=="string"))&&a(`${n}.labels must map values to display text`),t}function It(t,e){return t===void 0?[]:((!Array.isArray(t)||t.length===0||t.length>y.MAX_ROW_DETAIL_SECTIONS)&&a(`x-lt-row-detail must be 1..${y.MAX_ROW_DETAIL_SECTIONS} sections`),t.map((n,r)=>{const o=`x-lt-row-detail[${r}]`;m(n)||a(`${o} must be an object`),(!A(n.related)||!e[n.related])&&a(`${o}.related must name a set declared in x-lt-related`),(!Array.isArray(n.columns)||n.columns.length===0)&&a(`${o}.columns must list at least one column`);for(const[s,i]of n.columns.entries())(!m(i)||!A(i.label)||typeof i.value!="string")&&a(`${o}.columns[${s}] needs a label and a value template`);return n.limit!==void 0&&(!Number.isInteger(n.limit)||n.limit<1||n.limit>y.ROWS_MAX)&&a(`${o}.limit must be 1..${y.ROWS_MAX}`),n}))}function Dt(t){const e=t[T.GROUP_BY];if(e===void 0||t[T.LAYOUT]!==pt)return null;const n=typeof e=="string"&&e.startsWith(f.METADATA)?e.slice(f.METADATA.length):"";return h.test(n)||a('x-lt-group-by on a facet-table must be "metadata.<key>"'),n}const R=new Set(Object.values(gt));function re(t){const e={sets:{},columns:[],rowDetail:[],groupKey:null};if(!m(t))return e;const n=t[T.RELATED],r={};if(n!==void 0){m(n)||a("x-lt-related must map set names to declarations");const i=Object.keys(n);(i.length===0||i.length>y.MAX_SETS)&&a(`x-lt-related must declare 1..${y.MAX_SETS} sets`);for(const l of i)r[l]=Mt(l,n[l])}const o=[],s=t[T.COLUMNS];return Array.isArray(s)&&s.forEach((i,l)=>{m(i)&&(i.related!==void 0&&o.push(Lt(i,r,`x-lt-columns[${l}]`)),i.group!==void 0&&(typeof i.group!="string"||!R.has(i.group))&&a(`x-lt-columns[${l}].group must be one of ${[...R].join(", ")}`))}),{sets:r,columns:o,rowDetail:It(t[T.ROW_DETAIL],r),groupKey:Dt(t)}}const Nt="accumulate_items",Rt="accumulate_max",C="batch_items",k="batch_filled_at",j="batch_filled_by",Ct="batch_keys",kt="batch_pending";function g(t){return!!t&&typeof t=="object"&&!Array.isArray(t)}function v(t,e){return t.at.localeCompare(e.at)||t.itemKey.localeCompare(e.itemKey)}function se(t,e){const n=t.metadata??{},r=e==null?void 0:e[Nt];if(g(r)){const s=Object.entries(r).map(([l,u])=>{const c=g(u)?u:{};return{itemKey:l,at:typeof c.at=="string"?c.at:"",...g(c.payload)?{payload:c.payload}:{},...typeof c.actor=="string"?{actor:c.actor}:{},...typeof c.reciprocalId=="string"?{reciprocalId:c.reciprocalId}:{}}}).sort(v),i=n[Rt];return{kind:"accumulate",count:s.length,max:typeof i=="number"?i:null,items:s,pending:[]}}const o=n[kt];if(Array.isArray(o)){const s=g(e==null?void 0:e[C])?e[C]:{},i=g(e==null?void 0:e[k])?e[k]:{},l=g(e==null?void 0:e[j])?e[j]:{},u=Object.entries(s).map(([d,b])=>({itemKey:d,at:typeof i[d]=="string"?i[d]:"",...g(b)?{payload:b}:{},...typeof l[d]=="string"?{actor:l[d]}:{}})).sort(v),c=n[Ct];return{kind:"batch",count:u.length,max:Array.isArray(c)?c.length:null,items:u,pending:o.filter(d=>typeof d=="string")}}return null}function oe(t){if(!t)return"";const e=Object.entries(t).slice(0,3).map(([r,o])=>{const s=typeof o=="object"&&o!==null?JSON.stringify(o):String(o);return`${r}: ${s.length>24?`${s.slice(0,23)}…`:s}`}),n=Object.keys(t).length-e.length;return n>0?`${e.join(" · ")} · +${n}`:e.join(" · ")}const ie="x-lt-item-label",X=/\{\{\s*([^{}]+?)\s*\}\}/g,H="item",$="—";function jt(t){if(t==null||t==="")return null;if(typeof t=="string")return t;if(typeof t=="number"||typeof t=="boolean")return String(t);try{return JSON.stringify(t)}catch{return null}}function F(t,e,n){const r=t.indexOf(".");if((r===-1?t:t.slice(0,r))===H)try{return jt(r===-1?e:S(e,t.slice(r+1)))}catch{return null}const s=P(`{{${t}}}`,n);return s===$?null:s}function ae(t,e,n={}){if(typeof t!="string"||!t.trim())return null;let r=0,o=0;const s=t.replace(X,(i,l)=>{o+=1;const u=F(l,e,n);return u===null?$:(r+=1,u)}).trim();return o>0&&r===0?null:s||null}function le(t,e,n={}){return t.replace(X,(r,o)=>!e&&o.split(".")[0]===H?$:F(o,e??{},n)??$)}export{gt as G,lt as H,ie as I,yt as M,Vt as R,f as S,ae as a,Xt as b,P as c,Ht as d,se as e,ft as f,S as g,Wt as h,q as i,Ft as j,le as k,re as l,Kt as m,O as n,ee as o,ne as p,Bt as q,zt as r,oe as s,Zt as t,Jt as u,Qt as v,wt as w,te as x,Gt as y};
2
+ //# sourceMappingURL=escalation-items-BIgBWbaw.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"escalation-items-BIgBWbaw.js","sources":["../../../shared/form-validation/display-only-widgets.ts","../../../shared/form-validation/x-lt-bind.ts","../../../shared/form-validation/x-lt-help.ts","../../src/lib/schema-needs-envelope.ts","../../src/lib/escalation.ts","../../src/lib/identifier-label.ts","../../src/components/escalation/list-view/row-parts.tsx","../../../shared/list-schema/types.ts","../../../shared/list-schema/aggregate.ts","../../../shared/list-schema/validate.ts","../../src/lib/escalation-items.ts"],"sourcesContent":["/**\n * Widgets that render from the escalation context and produce no answer of\n * their own: navigation links, embedded records and lists, and invoke\n * controls. Their form slot exists only to place them in the layout, so\n * the payload mapper drops them and the server never sees a value.\n */\nexport const DISPLAY_ONLY_WIDGET_NAMES = {\n LINK: 'link',\n ESCALATION: 'escalation',\n ESCALATION_LIST: 'escalation-list',\n INVOKE: 'invoke',\n ROSTER: 'roster',\n} as const;\n\nexport const DISPLAY_ONLY_WIDGETS: ReadonlySet<string> = new Set(Object.values(DISPLAY_ONLY_WIDGET_NAMES));\n\nexport function isDisplayOnlyWidget(name: unknown): boolean {\n return typeof name === 'string' && DISPLAY_ONLY_WIDGETS.has(name);\n}\n\n/** Whether a property definition renders a display-only widget. */\nexport function isDisplayOnlyField(def: Record<string, unknown> | null | undefined): boolean {\n return isDisplayOnlyWidget(def?.['x-lt-widget']);\n}\n","/**\n * x-lt-bind — maps the escalation FORM (flat field values the user edits) to and\n * from the PAYLOAD (the nested JSON the workflow consumes). A form_schema property\n * may declare `x-lt-bind: \"a.b[0].c\"`, the path its value occupies in the payload;\n * a property with no bind sits at its own name at the root (1:1). This module is\n * isomorphic — the dashboard renders forms with it, and the API layer inverts a\n * submitted payload through it to validate against the form contract. One\n * implementation, both sides.\n *\n * mapPayloadToForm — payload → flat form values, to PREFILL/display the form\n * (server-side: to validate a submitted payload)\n * mapFormToPayload — flat form values → payload, the shape submitted/stored\n */\nimport { isDisplayOnlyField } from './display-only-widgets';\n\ntype PathSeg = { key: string } | { index: number };\n\nconst BLOCKED_KEYS = new Set(['__proto__', 'constructor', 'prototype']);\n\n/** Parse a bind path — dot keys with optional `[n]` indices. Rejects pollution keys. */\nexport function parsePath(path: string): PathSeg[] {\n const segs: PathSeg[] = [];\n for (const raw of path.split('.')) {\n const m = raw.match(/^([^[\\]]*)((?:\\[\\d+\\])*)$/);\n if (!m) throw new Error(`invalid x-lt-bind path segment: \"${raw}\"`);\n const [, name, brackets] = m;\n if (name) {\n if (BLOCKED_KEYS.has(name)) throw new Error(`x-lt-bind path may not target \"${name}\"`);\n segs.push({ key: name });\n }\n for (const b of brackets.match(/\\d+/g) ?? []) segs.push({ index: Number(b) });\n }\n if (segs.length === 0) throw new Error(`empty x-lt-bind path: \"${path}\"`);\n return segs;\n}\n\n/** Set `value` at `path` inside `root`, creating intermediate objects/arrays. */\nexport function setDeep(root: Record<string, any>, path: string, value: unknown): void {\n const segs = parsePath(path);\n let node: any = root;\n for (let i = 0; i < segs.length - 1; i++) {\n const seg = segs[i];\n const next = segs[i + 1];\n const childKey = 'key' in seg ? seg.key : seg.index;\n const wantArray = 'index' in next;\n if (node[childKey] == null || typeof node[childKey] !== 'object') {\n node[childKey] = wantArray ? [] : {};\n }\n node = node[childKey];\n }\n const last = segs[segs.length - 1];\n node['key' in last ? last.key : last.index] = value;\n}\n\n/** Read the value at `path` inside `root` (undefined if any segment is missing). */\nexport function getDeep(root: unknown, path: string): unknown {\n let node: any = root;\n for (const seg of parsePath(path)) {\n if (node == null || typeof node !== 'object') return undefined;\n node = node['key' in seg ? seg.key : seg.index];\n }\n return node;\n}\n\n/** The bind path for a form property (its `x-lt-bind`, or the property name). */\nexport function bindPathFor(propName: string, propDef: Record<string, any> | undefined): string {\n const bind = propDef?.['x-lt-bind'];\n return typeof bind === 'string' && bind.length > 0 ? bind : propName;\n}\n\n/**\n * Assemble the payload from the form's flat values. A field absent from\n * `formValues` is omitted (so clearing/deleting a field drops it from the\n * payload). Unknown keys not declared in the schema are dropped, and so are\n * display-only widget fields, which carry no answer. With no schema\n * properties, values pass through unchanged.\n */\nexport function mapFormToPayload(\n formValues: Record<string, any>,\n formSchema: Record<string, any> | null | undefined,\n): Record<string, any> {\n const props = formSchema?.properties as Record<string, any> | undefined;\n if (!props) return { ...formValues };\n const payload: Record<string, any> = {};\n for (const [name, def] of Object.entries(props)) {\n if (!(name in formValues)) continue;\n if (isDisplayOnlyField(def as Record<string, unknown>)) continue;\n setDeep(payload, bindPathFor(name, def as Record<string, any>), formValues[name]);\n }\n return payload;\n}\n\n/**\n * Reverse of {@link mapFormToPayload}: pull each form field's value out of the\n * payload via its bind path, to prefill/display the form. A field whose bound\n * path is missing from the payload is omitted (the caller falls back to the\n * schema default).\n */\nexport function mapPayloadToForm(\n payload: Record<string, any> | null | undefined,\n formSchema: Record<string, any> | null | undefined,\n): Record<string, any> {\n const props = formSchema?.properties as Record<string, any> | undefined;\n if (!props) return payload ? { ...payload } : {};\n const form: Record<string, any> = {};\n for (const [name, def] of Object.entries(props)) {\n const v = getDeep(payload, bindPathFor(name, def as Record<string, any>));\n if (v !== undefined) form[name] = v;\n }\n return form;\n}\n","/**\n * x-lt-help — the form's guidance content, rendered in the side panel beside\n * the resolve form. A form_schema may declare schema-level `x-lt-help`: a\n * markdown string whose `{{domain.path}}` tokens interpolate values from the\n * escalation surface, so help text can reference the live record:\n *\n * {{escalation.role}} — any column on the escalation row\n * {{metadata.schema_version}} — the row's metadata dict\n * {{envelope.formDefaults.customer.name}} — the workflow-sent input envelope\n * {{payload.category}} — the escalation context payload\n * {{resolver.notes}} — the submitted resolver payload\n * {{lookup.materials.items}} — versioned knowledge lookups pinned on the row\n * {{roster.orders.outstanding}} (a roster field's counts, x-lt-roster.ts)\n *\n * Paths reuse the x-lt-bind syntax (`a.b[0].c`). A missing value renders as an\n * em dash. `x-lt-context` is accepted as the plain-text fallback source when\n * `x-lt-help` is absent.\n */\nimport { getDeep } from './x-lt-bind';\n\n/** The token domains a help template may reference. `input` is the invoke-form name for the live values `resolver` also carries. */\nexport const HELP_DOMAINS = ['escalation', 'metadata', 'envelope', 'payload', 'resolver', 'lookup', 'input', 'roster'] as const;\nexport type HelpDomain = (typeof HELP_DOMAINS)[number];\n\nexport type HelpTokenContext = Partial<Record<HelpDomain, Record<string, unknown> | null>>;\n\nconst TOKEN_PATTERN = /\\{\\{\\s*([^{}]+?)\\s*\\}\\}/g;\nconst MISSING_VALUE = '—';\n\nfunction formatTokenValue(value: unknown): string {\n if (value === undefined || value === null) return MISSING_VALUE;\n if (typeof value === 'string') return value;\n if (typeof value === 'number' || typeof value === 'boolean') return String(value);\n try {\n return JSON.stringify(value);\n } catch {\n return MISSING_VALUE;\n }\n}\n\n/** Replace every `{{domain.path}}` token with its value from the context. */\nexport function interpolateHelp(template: string, ctx: HelpTokenContext): string {\n return template.replace(TOKEN_PATTERN, (_match, rawPath: string) => {\n const dot = rawPath.indexOf('.');\n const domain = (dot === -1 ? rawPath : rawPath.slice(0, dot)) as HelpDomain;\n if (!HELP_DOMAINS.includes(domain)) return MISSING_VALUE;\n const root = ctx[domain];\n if (dot === -1) return formatTokenValue(root);\n try {\n return formatTokenValue(getDeep(root, rawPath.slice(dot + 1)));\n } catch {\n return MISSING_VALUE;\n }\n });\n}\n\n/** The schema's help source: `x-lt-help` first, `x-lt-context` as fallback. */\nexport function resolveHelpSource(schema: Record<string, unknown> | null | undefined): string | null {\n const help = schema?.['x-lt-help'];\n if (typeof help === 'string' && help.trim().length > 0) return help;\n const context = schema?.['x-lt-context'];\n if (typeof context === 'string' && context.trim().length > 0) return context;\n return null;\n}\n\n/** The schema's help content, interpolated. Null when the schema declares none. */\nexport function buildHelpMarkdown(\n schema: Record<string, unknown> | null | undefined,\n ctx: HelpTokenContext,\n): string | null {\n const source = resolveHelpSource(schema);\n return source ? interpolateHelp(source, ctx) : null;\n}\n\nexport interface HelpStateHint {\n isTerminal: boolean;\n status?: string;\n claimed: boolean;\n claimedByMe: boolean;\n}\n\n/**\n * State-aware guidance shown when the schema carries no help content — the\n * panel always tells the user what this page expects of them right now.\n */\nexport function defaultHelpMarkdown({ isTerminal, status, claimed, claimedByMe }: HelpStateHint): string {\n if (isTerminal) {\n return status === 'cancelled'\n ? 'This escalation was cancelled. The record is shown for reference.'\n : 'This escalation has been resolved. The submitted form is shown for reference.';\n }\n if (claimedByMe) return 'You have claimed this escalation. Fill out the form and submit to resolve it.';\n if (claimed) return 'Another user has claimed this escalation. It unlocks if their claim expires or is released.';\n return 'Claim this escalation to enable the form.';\n}\n","/**\n * List rows arrive without the heavyweight `envelope`/`escalation_payload`\n * columns by default. A surface driven by an x-lt schema fragment opts back in\n * only when the fragment actually interpolates those domains — `envelope.` or\n * `payload.` in any token, condition, or source path. `metadata.` and\n * `resolver.` ride the slim rows and never trigger the opt-in.\n */\nexport function schemaNeedsEnvelope(fragment: unknown): boolean {\n if (!fragment) return false;\n try {\n const s = JSON.stringify(fragment);\n return s.includes('envelope.') || s.includes('payload.');\n } catch {\n return false;\n }\n}\n","import type { LTEscalationRecord } from '../api/types';\n\nexport function isEffectivelyClaimed(esc: LTEscalationRecord): boolean {\n return !!(\n esc.assigned_to &&\n esc.assigned_until &&\n new Date(esc.assigned_until) > new Date()\n );\n}\n\n/** An ACK escalation has no associated workflow — it's a notification, not a task. */\nexport function isAckEscalation(esc: LTEscalationRecord): boolean {\n return !esc.workflow_type;\n}\n\nexport function isAvailable(esc: LTEscalationRecord): boolean {\n return (\n esc.status === 'pending' &&\n (!esc.assigned_to ||\n !esc.assigned_until ||\n new Date(esc.assigned_until) <= new Date())\n );\n}\n","/**\n * A human label for a code identifier: camelCase, snake_case, kebab-case, and\n * digit runs become Title Case words. `fleetTools` → `Fleet Tools`,\n * `print_order2` → `Print Order 2`. Acronyms keep their capitals: `mcpQuery`\n * → `Mcp Query` is avoided by treating an all-caps run as one word.\n */\nexport function identifierToTitle(id: string): string {\n const words = id\n .replace(/[_\\-.]+/g, ' ')\n .replace(/([a-z\\d])([A-Z])/g, '$1 $2')\n .replace(/([A-Z]+)([A-Z][a-z])/g, '$1 $2')\n .replace(/([a-zA-Z])(\\d)/g, '$1 $2')\n .trim()\n .split(/\\s+/)\n .filter(Boolean);\n return words\n .map((w) => (w === w.toUpperCase() && w.length > 1 ? w : w.charAt(0).toUpperCase() + w.slice(1)))\n .join(' ');\n}\n","import { useState } from 'react';\nimport { useNavigate, useLocation } from 'react-router-dom';\nimport { Search } from 'lucide-react';\nimport type { HelpTokenContext } from '../../../lib/x-lt-help';\nimport { STATUS_DOT_STYLES } from '../../common/display/StatusBadge';\nimport { useClaimEscalation } from '../../../api/escalations';\nimport { isEffectivelyClaimed } from '../../../lib/escalation';\nimport { identifierToTitle } from '../../../lib/identifier-label';\nimport type { RefinePair } from '../RefineDialog';\nimport type { LTEscalationRecord } from '../../../api/types';\n\n/** The row-level pieces every list layout shares: column and action\n * declarations, the row's token context, the row action, and refine. */\n\n/** Dot colour matches the standard table view: blue = pending unclaimed,\n * orange = under a live claim; other statuses follow the shared map. */\nexport function escalationDotClass(e: LTEscalationRecord): string {\n if (e.status === 'pending') {\n return isEffectivelyClaimed(e) ? 'bg-status-claimed-graphic' : 'bg-status-active';\n }\n return STATUS_DOT_STYLES[e.status] ?? 'bg-status-active';\n}\n\nexport interface ColumnDef {\n label: string;\n value: string;\n /** \"age\" renders an ISO timestamp as a compact age with an absolute tooltip. */\n format?: string;\n /**\n * Card-fold behavior when the table folds at narrow widths (same contract\n * as the engineer table): 1 = identity — always visible, forms the card's\n * title line; 2 = folds into the card body as a label/value pair; 3 =\n * dropped in card mode. Undeclared, the first column is the identity and\n * the rest fold.\n */\n priority?: 1 | 2 | 3;\n /** CSS column width (\"40%\", \"12rem\"). Unset columns share the remainder;\n * when no column declares one, the first column holds a fixed 200px so\n * the identity stays legible and every other value keeps its room. */\n width?: string;\n}\n\n/**\n * The per-row action button — the queue-working gesture, always available on\n * every layout. Template-driven: the schema author sets the action, its text,\n * and (for claim) the hold time.\n */\nexport interface RowActionDef {\n /** \"claim\" fires a one-click claim then opens the detail page already\n * claimed; \"view\" just opens it. Default \"claim\". */\n action?: 'claim' | 'view';\n /** Button text. Defaults \"Claim\" / \"View\" by action. */\n label?: string;\n /** Claim hold time in minutes. Default 30 (the platform claim default). */\n durationMinutes?: number;\n /**\n * Launch the detail page's claim-and-submit flow instead of a plain claim:\n * the row is claimed, the form's seeded defaults are resolved, and — when the\n * form declares `x-lt-transition` — the wait screen bridges to the born-assigned\n * follow-on. One list gesture (\"Start Harvesting\") starts the work and lands\n * the person on the next step. The behavior lives on the detail page (form\n * defaults, validation, transition); the list only points there with intent.\n */\n submitOnClaim?: boolean;\n}\n\n/** Build the token context for one escalation row (payloads are JSON strings). */\nexport function rowContext(e: LTEscalationRecord): HelpTokenContext {\n const parse = (s: string | null | undefined): Record<string, unknown> | null => {\n if (!s) return null;\n try {\n const v = JSON.parse(s);\n return v && typeof v === 'object' ? v : null;\n } catch {\n return null;\n }\n };\n return {\n escalation: e as unknown as Record<string, unknown>,\n metadata: e.metadata ?? null,\n envelope: parse(e.envelope),\n payload: parse(e.escalation_payload),\n resolver: parse(e.resolver_payload),\n };\n}\n\n/** The identity column's width when no column declares one: room for a label, no more. */\nexport const IDENTITY_COLUMN_WIDTH = '200px';\n\n/** The action column sizes to its label so the button never wraps or truncates. */\nexport function actionColumnWidth(label: string): string {\n return `${Math.max(6, Math.round(label.length * 0.55 + 3.5))}rem`;\n}\n\nconst DEFAULT_CLAIM_MINUTES = 30;\n\n/** Claim targets pending rows without a live claim window. */\nfunction isClaimable(row: LTEscalationRecord): boolean {\n return row.status === 'pending' && !isEffectivelyClaimed(row);\n}\n\n/**\n * The x-lt-row-action button. `claim` is one click: claim for the template's\n * duration, then open the detail page already claimed — the fast path for\n * working a queue. `view` opens the detail page. Persistent (light accent at\n * rest, saturating on hover); a rejected claim surfaces its message inline.\n */\nexport function RowActionButton({ row, def, onView, prominent, forceView }: {\n row: LTEscalationRecord;\n def?: RowActionDef;\n onView?: () => void;\n /** Hero treatment for the active-card CTA; default is the compact row button. */\n prominent?: boolean;\n /** Render claim templates as view actions (see EscalationListView). */\n forceView?: boolean;\n}) {\n const authored = def?.action ?? 'claim';\n const action = forceView ? 'view' : authored;\n // The authored label describes the authored gesture. When view is forced\n // over a claim template, claim wording would mislead — use the view default.\n const label = authored === action && def?.label\n ? def.label\n : action === 'claim' ? 'Claim' : 'View';\n const claim = useClaimEscalation();\n const navigate = useNavigate();\n const location = useLocation();\n const [error, setError] = useState('');\n\n // A spent gesture stays visible — the disabled button keeps every row's\n // layout uniform instead of leaving a hole on resolved/held rows.\n const spent = action === 'claim' && !isClaimable(row);\n\n const fire = (e: React.MouseEvent) => {\n e.stopPropagation();\n if (action === 'view') {\n onView?.();\n return;\n }\n // Launch the detail page's claim → submit → transition flow. The detail\n // page owns the heavy lifting (seed defaults, validate, resolve, hand-off);\n // the list points there with the intent and the authored claim duration.\n if (def?.submitOnClaim) {\n navigate(`/escalations/detail/${row.id}`, {\n state: { autoStart: true, durationMinutes: def?.durationMinutes, from: location.pathname },\n });\n return;\n }\n setError('');\n claim.mutate(\n { id: row.id, durationMinutes: def?.durationMinutes ?? DEFAULT_CLAIM_MINUTES },\n {\n onSuccess: () => onView?.(),\n onError: (err) => setError((err as Error).message),\n },\n );\n };\n\n const classes = prominent\n ? 'btn-primary text-xs shrink-0 disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:bg-accent'\n : 'px-2 py-0.5 rounded text-2xs font-medium text-accent/70 border border-accent/30 enabled:hover:text-accent enabled:hover:border-accent/60 enabled:hover:bg-accent/5 transition-colors disabled:opacity-50 disabled:cursor-not-allowed whitespace-nowrap';\n\n return (\n <span className=\"inline-flex flex-col items-end gap-0.5\">\n <button\n type=\"button\"\n onClick={fire}\n disabled={claim.isPending || spent}\n title={spent ? (row.status === 'pending' ? 'claimed' : row.status) : undefined}\n className={classes}\n data-testid=\"row-action-button\"\n >\n {claim.isPending ? 'Claiming…' : label}\n </button>\n {error && <span className=\"text-2xs text-status-error\" data-testid=\"row-action-error\">{error}</span>}\n </span>\n );\n}\n\n/** A field value token that is a pure metadata binding — facet-linkable. */\nexport const METADATA_TOKEN = /^\\{\\{\\s*metadata\\.([a-zA-Z0-9_]+)\\s*\\}\\}$/;\n\n/** A metadata value the faceted query can match on: a scalar with something in it. */\nfunction isFacetValue(raw: unknown): raw is string | number | boolean {\n return (typeof raw === 'string' && raw !== '') || typeof raw === 'number' || typeof raw === 'boolean';\n}\n\n/**\n * The refinable facts one row offers: every metadata facet the row carries.\n * Columns the author bound to a metadata value lead, under their authored\n * labels; every other scalar facet follows under a label derived from its\n * key, so the dialog reaches the whole record, not only what the columns\n * show. Feeds the row's RefineDialog.\n */\nexport function rowRefinePairs(row: LTEscalationRecord, columnDefs: ColumnDef[]): RefinePair[] {\n const pairs: RefinePair[] = [];\n const seen = new Set<string>();\n const metadata = row.metadata ?? {};\n for (const col of columnDefs) {\n const bound = typeof col.value === 'string' ? col.value.match(METADATA_TOKEN)?.[1] : undefined;\n if (!bound || seen.has(bound)) continue;\n const raw = metadata[bound];\n if (!isFacetValue(raw)) continue;\n seen.add(bound);\n pairs.push({ key: bound, label: col.label, value: raw, bound: true });\n }\n for (const [key, raw] of Object.entries(metadata)) {\n if (seen.has(key) || !isFacetValue(raw)) continue;\n seen.add(key);\n pairs.push({ key, label: identifierToTitle(key), value: raw });\n }\n return pairs;\n}\n\n/** The always-tappable row/card refine trigger — one magnifier, dialog behind it. */\nexport function RefineTrigger({ onOpen, className = '' }: { onOpen: () => void; className?: string }) {\n return (\n <button\n type=\"button\"\n onClick={(e) => { e.stopPropagation(); onOpen(); }}\n className={`p-1.5 rounded text-text-quaternary/70 hover:text-accent hover:bg-surface-hover transition-colors ${className}`}\n title=\"Refine — filter or search by this row's values\"\n aria-label=\"Refine — filter or search by this row's values\"\n data-testid=\"row-refine\"\n >\n <Search className=\"w-3.5 h-3.5\" strokeWidth={1.5} />\n </button>\n );\n}\n","/**\n * Related sets on a role's list schema. A set is named once under\n * `x-lt-related`; columns (`related`) and row details (`x-lt-row-detail`)\n * reference it by name. The server reads the declaration from the stored\n * list schema, never from the caller.\n *\n * items the host row's accumulated or batch items, each read through its\n * payload or its reciprocal row\n * query rows in other roles that share facets with the host row; facet\n * values are `{{domain.path}}` templates over the host row\n */\n\nexport const LIST_SCHEMA_KEYS = {\n RELATED: 'x-lt-related',\n COLUMNS: 'x-lt-columns',\n ROW_DETAIL: 'x-lt-row-detail',\n GROUP_BY: 'x-lt-group-by',\n LAYOUT: 'x-lt-layout',\n} as const;\n\nexport const RELATED_SOURCES = {\n ITEMS: 'items',\n QUERY: 'query',\n} as const;\nexport type RelatedSource = (typeof RELATED_SOURCES)[keyof typeof RELATED_SOURCES];\n\nexport const RELATED_AGGREGATES = {\n COUNT: 'count',\n /** The least item or row value: numbers as numbers, everything else as text. */\n MIN: 'min',\n MAX: 'max',\n} as const;\nexport type RelatedAggregate = (typeof RELATED_AGGREGATES)[keyof typeof RELATED_AGGREGATES];\n\n/** How a grouped table folds a plain column across a group's rows. */\nexport const GROUP_FOLDS = {\n FIRST: 'first',\n MIN: 'min',\n MAX: 'max',\n SUM: 'sum',\n COUNT: 'count',\n /** The distinct values, in row order, joined: \"standard, express\". */\n DISTINCT: 'distinct',\n} as const;\nexport type GroupFold = (typeof GROUP_FOLDS)[keyof typeof GROUP_FOLDS];\n\n/** Split prefixes. `role` splits a query set by the related row's role. */\nexport const SPLIT_PATHS = {\n ROLE: 'role',\n METADATA: 'metadata.',\n PAYLOAD: 'payload.',\n RECIPROCAL_METADATA: 'reciprocal.metadata.',\n} as const;\n\nexport const RELATED_LIMITS = {\n MAX_SETS: 4,\n MAX_QUERY_ROLES: 12,\n MAX_ROW_DETAIL_SECTIONS: 4,\n MAX_HOSTS: 100,\n ROWS_DEFAULT: 25,\n ROWS_MAX: 100,\n} as const;\n\n/** The table layout that renders related columns, row details, and groups. */\nexport const FACET_TABLE_LAYOUT = 'facet-table';\n\nexport interface RelatedQueryDecl {\n /** Related roles, in display order. Exclusive with `segment`. */\n roles?: string[];\n /** A Pace Board sequence by its first role; resolves to the ordered chain. */\n segment?: string;\n /** Facet containment; string values may be `{{domain.path}}` templates. */\n facets?: Record<string, unknown>;\n /**\n * Facets that narrow the match when the host row carries a value, and\n * drop away when it does not: a lane narrows its tub's look-ahead to its\n * own service level, a tub without lanes keeps the whole destination.\n */\n narrow?: Record<string, unknown>;\n /** Default `pending`. */\n status?: string;\n}\n\nexport interface RelatedSetDecl {\n source: RelatedSource;\n query?: RelatedQueryDecl;\n}\n\n/** A count column's text keyed by count; `default` covers the rest, `{n}` reads the count. */\nexport const RELATED_DISPLAY_DEFAULT = 'default';\n\nexport interface RelatedColumnDecl {\n label: string;\n related: string;\n aggregate?: RelatedAggregate;\n /** min/max: `{{item.payload.<path>}}` on an items set, `{{metadata.<key>}}` on a query set. */\n value?: string;\n /** min/max: how the value renders, as on any facet-table column. */\n format?: string;\n /** count: text by count, e.g. `{ \"0\": \"Ready\", \"default\": \"Waiting on {n}\" }`. */\n display?: Record<string, string>;\n splitBy?: string;\n labels?: Record<string, string>;\n priority?: 1 | 2 | 3;\n /** CSS width, as on any facet-table column. */\n width?: string;\n}\n\nexport interface RowDetailColumnDecl {\n label: string;\n value: string;\n format?: string;\n priority?: 1 | 2 | 3;\n}\n\nexport interface RowDetailSectionDecl {\n related: string;\n label?: string;\n columns: RowDetailColumnDecl[];\n limit?: number;\n}\n\n/** The validated, normalized related declaration of one list schema. */\nexport interface ListSchemaRelations {\n sets: Record<string, RelatedSetDecl>;\n columns: RelatedColumnDecl[];\n rowDetail: RowDetailSectionDecl[];\n /** The metadata key a facet-table groups by, when declared. */\n groupKey: string | null;\n}\n\n/** Per-host aggregate for one (set, splitBy) pair, or one (set, min/max, value) triple. */\nexport interface RelatedHostAggregate {\n count: number;\n /** min/max: the extreme value among `count` values; absent when none carries one. */\n value?: string | number;\n /** Split value to count; a null value is keyed by the empty string. */\n splits?: Record<string, number>;\n /** Items whose reciprocal row the viewer cannot read. */\n hidden?: number;\n /** A host whose facet templates resolved to nothing; the set did not run. */\n unresolved?: boolean;\n}\n\nexport interface RelatedSetResult {\n source: RelatedSource;\n /**\n * The roles whose rows the set reads, which a list follows for live\n * changes: a query set's resolved roles in order, or the roles of an item\n * set's readable reciprocal rows when a column splits by them.\n */\n roles?: string[];\n /** Query sets: role titles, keyed by role. */\n roleLabels?: Record<string, string>;\n /** Query sets: declared roles outside the viewer's full read scope. */\n restricted?: string[];\n /** Keyed by relatedAggregateKey (the splitBy, '' when unsplit, or `min:<path>`), then host id. */\n aggregates: Record<string, Record<string, RelatedHostAggregate>>;\n}\n\nexport interface RelatedAggregatesResponse {\n version: number | null;\n sets: Record<string, RelatedSetResult>;\n}\n\nexport interface RelatedItemEntry {\n itemKey: string;\n payload?: unknown;\n at?: string;\n actor?: string;\n reciprocalId?: string;\n}\n\nexport interface RelatedRow {\n /** Items sets only. */\n item?: RelatedItemEntry;\n /** The reciprocal row (items) or the related row (query); null when unreadable. */\n escalation: Record<string, unknown> | null;\n}\n\nexport interface RelatedRowsResponse {\n source: RelatedSource;\n rows: RelatedRow[];\n total: number;\n restricted?: string[];\n roleLabels?: Record<string, string>;\n}\n","import {\n RELATED_AGGREGATES,\n RELATED_DISPLAY_DEFAULT,\n RELATED_SOURCES,\n SPLIT_PATHS,\n type RelatedAggregate,\n type RelatedColumnDecl,\n} from './types';\n\nconst VALUE_TOKEN = /^\\{\\{\\s*([^{}]+?)\\s*\\}\\}$/;\nconst ITEM_PREFIX = 'item.';\nconst PATH_SEGMENT = /^[a-zA-Z0-9_]+$/;\nconst METADATA_KEY = /^[a-zA-Z0-9_]+$/;\nconst COUNT_TOKEN = /\\{n\\}/g;\n\nexport type RelatedExtreme = typeof RELATED_AGGREGATES.MIN | typeof RELATED_AGGREGATES.MAX;\n\n/** True for the aggregates that pick one value rather than count. */\nexport function isExtremeAggregate(aggregate: unknown): aggregate is RelatedExtreme {\n return aggregate === RELATED_AGGREGATES.MIN || aggregate === RELATED_AGGREGATES.MAX;\n}\n\n/**\n * The stored path a min/max `value` template reads: `payload.<path>` for an\n * items set, `metadata.<key>` for a query set. Null when the template does\n * not fit the set's source.\n */\nexport function relatedValuePath(source: string, value: unknown): string | null {\n if (typeof value !== 'string') return null;\n const token = value.match(VALUE_TOKEN)?.[1];\n if (!token) return null;\n if (source === RELATED_SOURCES.ITEMS) {\n if (!token.startsWith(`${ITEM_PREFIX}${SPLIT_PATHS.PAYLOAD}`)) return null;\n const path = token.slice(ITEM_PREFIX.length + SPLIT_PATHS.PAYLOAD.length);\n return path && path.split('.').every((s) => PATH_SEGMENT.test(s)) ? `${SPLIT_PATHS.PAYLOAD}${path}` : null;\n }\n if (!token.startsWith(SPLIT_PATHS.METADATA)) return null;\n const key = token.slice(SPLIT_PATHS.METADATA.length);\n return METADATA_KEY.test(key) ? token : null;\n}\n\n/** The key a column's per-host aggregates are stored under in its set's result. */\nexport function relatedAggregateKey(col: Pick<RelatedColumnDecl, 'aggregate' | 'splitBy' | 'value'>, source: string): string {\n if (isExtremeAggregate(col.aggregate)) return `${col.aggregate}:${relatedValuePath(source, col.value) ?? ''}`;\n return col.splitBy ?? '';\n}\n\n/** A count column's display text, or null when the column declares none for this count. */\nexport function relatedCountText(display: Record<string, string> | undefined, count: number): string | null {\n if (!display) return null;\n const text = display[String(count)] ?? display[RELATED_DISPLAY_DEFAULT];\n return text === undefined ? null : text.replace(COUNT_TOKEN, String(count));\n}\n\n/**\n * The least or greatest of several values: numbers when every value is a\n * number, otherwise text in code-unit order (ISO instants order as text).\n */\nexport function foldExtreme(fold: RelatedAggregate, values: Array<string | number>): string | number | undefined {\n if (!values.length) return undefined;\n const pickMin = fold === RELATED_AGGREGATES.MIN;\n if (values.every((v) => typeof v === 'number')) {\n return pickMin ? Math.min(...(values as number[])) : Math.max(...(values as number[]));\n }\n const texts = values.map(String).sort((a, b) => (a < b ? -1 : a > b ? 1 : 0));\n return pickMin ? texts[0] : texts[texts.length - 1];\n}\n","import {\n FACET_TABLE_LAYOUT,\n GROUP_FOLDS,\n LIST_SCHEMA_KEYS,\n RELATED_AGGREGATES,\n RELATED_DISPLAY_DEFAULT,\n RELATED_LIMITS,\n RELATED_SOURCES,\n SPLIT_PATHS,\n type ListSchemaRelations,\n type RelatedColumnDecl,\n type RelatedSetDecl,\n type RowDetailSectionDecl,\n} from './types';\nimport { isExtremeAggregate, relatedValuePath } from './aggregate';\n\n/** A metadata key: interpolated as a JSON path, so strictly validated. */\nexport const METADATA_KEY = /^[a-zA-Z0-9_]+$/;\nconst SET_NAME = /^[a-zA-Z][a-zA-Z0-9_-]{0,47}$/;\nconst PATH_SEGMENT = /^[a-zA-Z0-9_]+$/;\nconst COUNT_KEY = /^(0|[1-9][0-9]*)$/;\n\ntype Obj = Record<string, unknown>;\n\nclass ListSchemaError extends Error {}\n\nfunction fail(message: string): never {\n throw new ListSchemaError(message);\n}\n\nfunction isObj(value: unknown): value is Obj {\n return !!value && typeof value === 'object' && !Array.isArray(value);\n}\n\nfunction isNonEmptyString(value: unknown): value is string {\n return typeof value === 'string' && value.trim().length > 0;\n}\n\n/** True when a dotted path has only plain segments. */\nfunction isPlainPath(path: string): boolean {\n return path.length > 0 && path.split('.').every((s) => PATH_SEGMENT.test(s));\n}\n\n/** The split paths a set's source accepts. */\nexport function splitPathError(source: string, splitBy: string): string | null {\n if (source === RELATED_SOURCES.QUERY) {\n if (splitBy === SPLIT_PATHS.ROLE) return null;\n if (splitBy.startsWith(SPLIT_PATHS.METADATA) && METADATA_KEY.test(splitBy.slice(SPLIT_PATHS.METADATA.length))) return null;\n return `splitBy \"${splitBy}\" on a query set must be \"role\" or \"metadata.<key>\"`;\n }\n if (splitBy.startsWith(SPLIT_PATHS.PAYLOAD) && isPlainPath(splitBy.slice(SPLIT_PATHS.PAYLOAD.length))) return null;\n if (splitBy.startsWith(SPLIT_PATHS.RECIPROCAL_METADATA)\n && METADATA_KEY.test(splitBy.slice(SPLIT_PATHS.RECIPROCAL_METADATA.length))) return null;\n return `splitBy \"${splitBy}\" on an items set must be \"payload.<path>\" or \"reciprocal.metadata.<key>\"`;\n}\n\nfunction readSet(name: string, raw: unknown): RelatedSetDecl {\n if (!SET_NAME.test(name)) fail(`x-lt-related name \"${name}\" must start with a letter (letters, digits, _ or -)`);\n if (!isObj(raw)) fail(`x-lt-related.${name} must be an object`);\n if (raw.source === RELATED_SOURCES.ITEMS) {\n if (raw.query !== undefined) fail(`x-lt-related.${name}: an items set takes no query`);\n return { source: RELATED_SOURCES.ITEMS };\n }\n if (raw.source !== RELATED_SOURCES.QUERY) fail(`x-lt-related.${name}.source must be \"items\" or \"query\"`);\n const q = raw.query;\n if (!isObj(q)) fail(`x-lt-related.${name}.query is required for a query set`);\n const hasRoles = q.roles !== undefined;\n const hasSegment = q.segment !== undefined;\n if (hasRoles === hasSegment) fail(`x-lt-related.${name}.query takes exactly one of roles or segment`);\n if (hasRoles) {\n const roles = q.roles;\n if (!Array.isArray(roles) || roles.length === 0 || roles.length > RELATED_LIMITS.MAX_QUERY_ROLES\n || !roles.every(isNonEmptyString)) {\n fail(`x-lt-related.${name}.query.roles must be 1..${RELATED_LIMITS.MAX_QUERY_ROLES} role names`);\n }\n } else if (!isNonEmptyString(q.segment)) {\n fail(`x-lt-related.${name}.query.segment must be a role name`);\n }\n if (!isObj(q.facets) || Object.keys(q.facets).length === 0) {\n fail(`x-lt-related.${name}.query.facets must name at least one facet`);\n }\n for (const [key, value] of Object.entries(q.facets)) {\n if (!METADATA_KEY.test(key)) fail(`x-lt-related.${name}.query.facets key \"${key}\" must be letters, digits or _`);\n if (value === null || typeof value === 'object') fail(`x-lt-related.${name}.query.facets.${key} must be a scalar or template`);\n }\n if (q.narrow !== undefined) {\n if (!isObj(q.narrow) || Object.keys(q.narrow).length === 0) fail(`x-lt-related.${name}.query.narrow must name at least one facet`);\n for (const [key, value] of Object.entries(q.narrow)) {\n if (!METADATA_KEY.test(key)) fail(`x-lt-related.${name}.query.narrow key \"${key}\" must be letters, digits or _`);\n if (key in q.facets) fail(`x-lt-related.${name}.query.narrow.${key} is already a required facet`);\n if (value === null || typeof value === 'object') fail(`x-lt-related.${name}.query.narrow.${key} must be a scalar or template`);\n }\n }\n if (q.status !== undefined && !isNonEmptyString(q.status)) fail(`x-lt-related.${name}.query.status must be a status`);\n return {\n source: RELATED_SOURCES.QUERY,\n query: {\n ...(hasRoles ? { roles: [...(q.roles as string[])] } : { segment: q.segment as string }),\n facets: { ...q.facets },\n ...(q.narrow !== undefined ? { narrow: { ...(q.narrow as Obj) } } : {}),\n ...(q.status !== undefined ? { status: q.status as string } : {}),\n },\n };\n}\n\nfunction readRelatedColumn(raw: Obj, sets: Record<string, RelatedSetDecl>, at: string): RelatedColumnDecl {\n const name = raw.related;\n if (!isNonEmptyString(name) || !sets[name]) fail(`${at}.related must name a set declared in x-lt-related`);\n if (raw.aggregate !== undefined && raw.aggregate !== RELATED_AGGREGATES.COUNT && !isExtremeAggregate(raw.aggregate)) {\n fail(`${at}.aggregate must be \"count\", \"min\" or \"max\"`);\n }\n const source = sets[name].source;\n if (isExtremeAggregate(raw.aggregate)) {\n if (!relatedValuePath(source, raw.value)) {\n fail(source === RELATED_SOURCES.ITEMS\n ? `${at}.value must be \"{{item.payload.<path>}}\" on an items set`\n : `${at}.value must be \"{{metadata.<key>}}\" on a query set`);\n }\n if (raw.splitBy !== undefined) fail(`${at}: a ${raw.aggregate} column takes no splitBy`);\n if (raw.display !== undefined) fail(`${at}: display applies to a count column`);\n } else if (raw.value !== undefined) {\n fail(`${at}.value applies to a min or max column`);\n }\n if (raw.format !== undefined && typeof raw.format !== 'string') fail(`${at}.format must be a format name`);\n if (raw.display !== undefined) {\n if (!isObj(raw.display) || Object.keys(raw.display).length === 0\n || !Object.entries(raw.display).every(([k, v]) => (k === RELATED_DISPLAY_DEFAULT || COUNT_KEY.test(k)) && typeof v === 'string')) {\n fail(`${at}.display must map counts (or \"default\") to display text`);\n }\n }\n if (raw.splitBy !== undefined) {\n if (!isNonEmptyString(raw.splitBy)) fail(`${at}.splitBy must be a path`);\n const err = splitPathError(sets[name].source, raw.splitBy);\n if (err) fail(`${at}: ${err}`);\n }\n if (raw.labels !== undefined && (!isObj(raw.labels) || !Object.values(raw.labels).every((v) => typeof v === 'string'))) {\n fail(`${at}.labels must map values to display text`);\n }\n return raw as unknown as RelatedColumnDecl;\n}\n\nfunction readRowDetail(raw: unknown, sets: Record<string, RelatedSetDecl>): RowDetailSectionDecl[] {\n if (raw === undefined) return [];\n if (!Array.isArray(raw) || raw.length === 0 || raw.length > RELATED_LIMITS.MAX_ROW_DETAIL_SECTIONS) {\n fail(`x-lt-row-detail must be 1..${RELATED_LIMITS.MAX_ROW_DETAIL_SECTIONS} sections`);\n }\n return raw.map((section, i) => {\n const at = `x-lt-row-detail[${i}]`;\n if (!isObj(section)) fail(`${at} must be an object`);\n if (!isNonEmptyString(section.related) || !sets[section.related]) fail(`${at}.related must name a set declared in x-lt-related`);\n if (!Array.isArray(section.columns) || section.columns.length === 0) fail(`${at}.columns must list at least one column`);\n for (const [j, col] of section.columns.entries()) {\n if (!isObj(col) || !isNonEmptyString(col.label) || typeof col.value !== 'string') {\n fail(`${at}.columns[${j}] needs a label and a value template`);\n }\n }\n if (section.limit !== undefined && (!Number.isInteger(section.limit) || (section.limit as number) < 1\n || (section.limit as number) > RELATED_LIMITS.ROWS_MAX)) {\n fail(`${at}.limit must be 1..${RELATED_LIMITS.ROWS_MAX}`);\n }\n return section as unknown as RowDetailSectionDecl;\n });\n}\n\nfunction readGroupKey(schema: Obj): string | null {\n const raw = schema[LIST_SCHEMA_KEYS.GROUP_BY];\n if (raw === undefined || schema[LIST_SCHEMA_KEYS.LAYOUT] !== FACET_TABLE_LAYOUT) return null;\n const key = typeof raw === 'string' && raw.startsWith(SPLIT_PATHS.METADATA) ? raw.slice(SPLIT_PATHS.METADATA.length) : '';\n if (!METADATA_KEY.test(key)) fail('x-lt-group-by on a facet-table must be \"metadata.<key>\"');\n return key;\n}\n\nconst FOLDS = new Set<string>(Object.values(GROUP_FOLDS));\n\n/**\n * Validate and normalize the related declaration of a list schema. Throws on\n * an invalid declaration; keys outside this vocabulary stay opaque.\n */\nexport function readListSchemaRelations(schema: unknown): ListSchemaRelations {\n const empty: ListSchemaRelations = { sets: {}, columns: [], rowDetail: [], groupKey: null };\n if (!isObj(schema)) return empty;\n const rawSets = schema[LIST_SCHEMA_KEYS.RELATED];\n const sets: Record<string, RelatedSetDecl> = {};\n if (rawSets !== undefined) {\n if (!isObj(rawSets)) fail('x-lt-related must map set names to declarations');\n const names = Object.keys(rawSets);\n if (names.length === 0 || names.length > RELATED_LIMITS.MAX_SETS) fail(`x-lt-related must declare 1..${RELATED_LIMITS.MAX_SETS} sets`);\n for (const name of names) sets[name] = readSet(name, rawSets[name]);\n }\n const columns: RelatedColumnDecl[] = [];\n const rawColumns = schema[LIST_SCHEMA_KEYS.COLUMNS];\n if (Array.isArray(rawColumns)) {\n rawColumns.forEach((col, i) => {\n if (!isObj(col)) return;\n if (col.related !== undefined) columns.push(readRelatedColumn(col, sets, `x-lt-columns[${i}]`));\n if (col.group !== undefined && (typeof col.group !== 'string' || !FOLDS.has(col.group))) {\n fail(`x-lt-columns[${i}].group must be one of ${[...FOLDS].join(', ')}`);\n }\n });\n }\n return { sets, columns, rowDetail: readRowDetail(schema[LIST_SCHEMA_KEYS.ROW_DETAIL], sets), groupKey: readGroupKey(schema) };\n}\n\n/** The declaration's first error, or null when valid. */\nexport function listSchemaRelationsError(schema: unknown): string | null {\n try {\n readListSchemaRelations(schema);\n return null;\n } catch (err) {\n if (err instanceof ListSchemaError) return err.message;\n throw err;\n }\n}\n","import type { LTEscalationRecord } from '../api/types';\nimport { interpolateHelp, type HelpTokenContext } from './x-lt-help';\nimport { getDeep } from './x-lt-bind';\n\n/** One held item of an accumulator or batch row, in the shape the workflow receives. */\nexport interface EscalationItem {\n itemKey: string;\n payload?: Record<string, unknown>;\n /** ISO-8601 from the database clock; empty for a batch item with no stamp. */\n at: string;\n actor?: string;\n reciprocalId?: string;\n}\n\nexport interface EscalationItems {\n kind: 'accumulate' | 'batch';\n count: number;\n /** The count trigger (accumulate) or the declared size (batch); null when unbounded. */\n max: number | null;\n items: EscalationItem[];\n /** Batch only: declared keys still awaiting submission. */\n pending: string[];\n}\n\nconst ACCUMULATE_ITEMS = 'accumulate_items';\nconst ACCUMULATE_MAX = 'accumulate_max';\nconst BATCH_ITEMS = 'batch_items';\nconst BATCH_FILLED_AT = 'batch_filled_at';\nconst BATCH_FILLED_BY = 'batch_filled_by';\nconst BATCH_KEYS = 'batch_keys';\nconst BATCH_PENDING = 'batch_pending';\n\nfunction isRecord(v: unknown): v is Record<string, unknown> {\n return !!v && typeof v === 'object' && !Array.isArray(v);\n}\n\nfunction byArrival(a: EscalationItem, b: EscalationItem): number {\n return a.at.localeCompare(b.at) || a.itemKey.localeCompare(b.itemKey);\n}\n\n/**\n * The held items of a row, or null when the row is neither an accumulator\n * nor a batch. Mirrors the server's items view so the panel and the API\n * agree on order (arrival, then key).\n */\nexport function escalationItems(\n esc: Pick<LTEscalationRecord, 'metadata'>,\n envelope: Record<string, unknown> | null,\n): EscalationItems | null {\n const metadata = (esc.metadata ?? {}) as Record<string, unknown>;\n const store = envelope?.[ACCUMULATE_ITEMS];\n if (isRecord(store)) {\n const items = Object.entries(store).map(([itemKey, entry]) => {\n const e = isRecord(entry) ? entry : {};\n return {\n itemKey,\n at: typeof e.at === 'string' ? e.at : '',\n ...(isRecord(e.payload) ? { payload: e.payload } : {}),\n ...(typeof e.actor === 'string' ? { actor: e.actor } : {}),\n ...(typeof e.reciprocalId === 'string' ? { reciprocalId: e.reciprocalId } : {}),\n } as EscalationItem;\n }).sort(byArrival);\n const max = metadata[ACCUMULATE_MAX];\n return { kind: 'accumulate', count: items.length, max: typeof max === 'number' ? max : null, items, pending: [] };\n }\n const pending = metadata[BATCH_PENDING];\n if (Array.isArray(pending)) {\n const filled = isRecord(envelope?.[BATCH_ITEMS]) ? (envelope![BATCH_ITEMS] as Record<string, unknown>) : {};\n const stamps = isRecord(envelope?.[BATCH_FILLED_AT]) ? (envelope![BATCH_FILLED_AT] as Record<string, unknown>) : {};\n const actors = isRecord(envelope?.[BATCH_FILLED_BY]) ? (envelope![BATCH_FILLED_BY] as Record<string, unknown>) : {};\n const items = Object.entries(filled).map(([itemKey, payload]) => ({\n itemKey,\n at: typeof stamps[itemKey] === 'string' ? (stamps[itemKey] as string) : '',\n ...(isRecord(payload) ? { payload } : {}),\n ...(typeof actors[itemKey] === 'string' ? { actor: actors[itemKey] as string } : {}),\n } as EscalationItem)).sort(byArrival);\n const keys = metadata[BATCH_KEYS];\n return {\n kind: 'batch',\n count: items.length,\n max: Array.isArray(keys) ? keys.length : null,\n items,\n pending: pending.filter((k): k is string => typeof k === 'string'),\n };\n }\n return null;\n}\n\n/** A one-line summary of an item payload for the list row. */\nexport function summarizePayload(payload: Record<string, unknown> | undefined): string {\n if (!payload) return '';\n const parts = Object.entries(payload).slice(0, 3).map(([k, v]) => {\n const text = typeof v === 'object' && v !== null ? JSON.stringify(v) : String(v);\n return `${k}: ${text.length > 24 ? `${text.slice(0, 23)}…` : text}`;\n });\n const more = Object.keys(payload).length - parts.length;\n return more > 0 ? `${parts.join(' · ')} · +${more}` : parts.join(' · ');\n}\n\n/** The container role's form-schema key naming how each held item displays. */\nexport const ITEM_LABEL_KEY = 'x-lt-item-label';\n\nconst TOKEN = /\\{\\{\\s*([^{}]+?)\\s*\\}\\}/g;\nconst ITEM_DOMAIN = 'item';\nconst MISSING = '—';\n\nfunction formatValue(value: unknown): string | null {\n if (value === undefined || value === null || value === '') return null;\n if (typeof value === 'string') return value;\n if (typeof value === 'number' || typeof value === 'boolean') return String(value);\n try {\n return JSON.stringify(value);\n } catch {\n return null;\n }\n}\n\n/** One token's value: `item.*` from the held item, every other domain as help tokens resolve it. */\nfunction tokenValue(path: string, item: EscalationItem, ctx: HelpTokenContext): string | null {\n const dot = path.indexOf('.');\n const domain = dot === -1 ? path : path.slice(0, dot);\n if (domain === ITEM_DOMAIN) {\n try {\n return formatValue(dot === -1 ? item : getDeep(item, path.slice(dot + 1)));\n } catch {\n return null;\n }\n }\n const value = interpolateHelp(`{{${path}}}`, ctx);\n return value === MISSING ? null : value;\n}\n\n/**\n * An item's display label from the role's `x-lt-item-label` template, whose\n * `{{item.*}}` tokens read the held item (itemKey, payload, actor, at) beside\n * the usual escalation domains. Null when there is no template or every token\n * it names is missing, so the caller falls back to the item key.\n */\nexport function itemLabel(\n template: unknown,\n item: EscalationItem,\n ctx: HelpTokenContext = {},\n): string | null {\n if (typeof template !== 'string' || !template.trim()) return null;\n let resolved = 0;\n let tokens = 0;\n const label = template.replace(TOKEN, (_match, rawPath: string) => {\n tokens += 1;\n const value = tokenValue(rawPath, item, ctx);\n if (value === null) return MISSING;\n resolved += 1;\n return value;\n }).trim();\n if (tokens > 0 && resolved === 0) return null;\n return label || null;\n}\n\n/** A template over `{{item.*}}` and the escalation domains; missing tokens read as an em dash. */\nexport function interpolateItemTemplate(template: string, item: EscalationItem | undefined, ctx: HelpTokenContext = {}): string {\n return template.replace(TOKEN, (_match, rawPath: string) => {\n if (!item && rawPath.split('.')[0] === ITEM_DOMAIN) return MISSING;\n return tokenValue(rawPath, item ?? ({} as EscalationItem), ctx) ?? MISSING;\n });\n}\n"],"names":["DISPLAY_ONLY_WIDGET_NAMES","DISPLAY_ONLY_WIDGETS","isDisplayOnlyWidget","name","isDisplayOnlyField","def","BLOCKED_KEYS","parsePath","path","segs","raw","m","brackets","b","setDeep","root","value","node","seg","next","childKey","wantArray","last","getDeep","bindPathFor","propName","propDef","bind","mapFormToPayload","formValues","formSchema","props","payload","mapPayloadToForm","form","v","HELP_DOMAINS","TOKEN_PATTERN","MISSING_VALUE","formatTokenValue","interpolateHelp","template","ctx","_match","rawPath","dot","domain","resolveHelpSource","schema","help","context","buildHelpMarkdown","source","defaultHelpMarkdown","isTerminal","status","claimed","claimedByMe","schemaNeedsEnvelope","fragment","s","isEffectivelyClaimed","esc","isAckEscalation","identifierToTitle","id","w","escalationDotClass","e","STATUS_DOT_STYLES","rowContext","parse","IDENTITY_COLUMN_WIDTH","actionColumnWidth","label","DEFAULT_CLAIM_MINUTES","isClaimable","row","RowActionButton","onView","prominent","forceView","authored","action","claim","useClaimEscalation","navigate","useNavigate","location","useLocation","error","setError","useState","spent","fire","err","classes","jsxs","jsx","METADATA_TOKEN","isFacetValue","rowRefinePairs","columnDefs","pairs","seen","metadata","col","bound","_a","key","RefineTrigger","onOpen","className","Search","LIST_SCHEMA_KEYS","RELATED_SOURCES","RELATED_AGGREGATES","GROUP_FOLDS","SPLIT_PATHS","RELATED_LIMITS","FACET_TABLE_LAYOUT","RELATED_DISPLAY_DEFAULT","VALUE_TOKEN","ITEM_PREFIX","PATH_SEGMENT","METADATA_KEY","COUNT_TOKEN","isExtremeAggregate","aggregate","relatedValuePath","token","relatedAggregateKey","relatedCountText","display","count","text","foldExtreme","fold","values","pickMin","texts","a","SET_NAME","COUNT_KEY","ListSchemaError","fail","message","isObj","isNonEmptyString","isPlainPath","splitPathError","splitBy","readSet","q","hasRoles","hasSegment","roles","readRelatedColumn","sets","at","k","readRowDetail","section","i","j","readGroupKey","FOLDS","readListSchemaRelations","empty","rawSets","names","columns","rawColumns","ACCUMULATE_ITEMS","ACCUMULATE_MAX","BATCH_ITEMS","BATCH_FILLED_AT","BATCH_FILLED_BY","BATCH_KEYS","BATCH_PENDING","isRecord","byArrival","escalationItems","envelope","store","items","itemKey","entry","max","pending","filled","stamps","actors","keys","summarizePayload","parts","more","ITEM_LABEL_KEY","TOKEN","ITEM_DOMAIN","MISSING","formatValue","tokenValue","item","itemLabel","resolved","tokens","interpolateItemTemplate"],"mappings":"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"}