@hotmeshio/long-tail 0.16.2 → 0.16.4
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.
- package/build/api/exports.d.ts +15 -0
- package/build/api/exports.js +35 -0
- package/build/bin/ltc.js +4 -0
- package/build/lib/cli/commands/workflows.d.ts +3 -0
- package/build/lib/cli/commands/workflows.js +22 -0
- package/build/routes/exports.js +11 -0
- package/build/sdk/index.d.ts +1 -0
- package/build/sdk/index.js +1 -0
- package/build/services/export/index.d.ts +19 -0
- package/build/services/export/index.js +53 -33
- package/build/shared/form-validation/field-validator.d.ts +8 -6
- package/build/shared/form-validation/field-validator.js +23 -15
- package/build/shared/form-validation/x-lt-options.js +35 -21
- package/build/system/mcp-servers/admin/exports.js +15 -0
- package/build/system/mcp-servers/admin/schemas.d.ts +7 -0
- package/build/system/mcp-servers/admin/schemas.js +5 -2
- package/build/system/seed/tool-manifests-admin.js +1 -0
- package/dashboard/dist/assets/{AdminDashboard-BrOvvDHF.js → AdminDashboard-Csq-oxmY.js} +2 -2
- package/dashboard/dist/assets/{AdminDashboard-BrOvvDHF.js.map → AdminDashboard-Csq-oxmY.js.map} +1 -1
- package/dashboard/dist/assets/{AgentConfigPage-CtVq8J0L.js → AgentConfigPage-Bnr5zbyJ.js} +2 -2
- package/dashboard/dist/assets/{AgentConfigPage-CtVq8J0L.js.map → AgentConfigPage-Bnr5zbyJ.js.map} +1 -1
- package/dashboard/dist/assets/{AgentDetailPage-DTfTQDug.js → AgentDetailPage-DgRu-Fhg.js} +2 -2
- package/dashboard/dist/assets/{AgentDetailPage-DTfTQDug.js.map → AgentDetailPage-DgRu-Fhg.js.map} +1 -1
- package/dashboard/dist/assets/{AgentsPage-vCTc3Qvj.js → AgentsPage-BuyXKkP3.js} +2 -2
- package/dashboard/dist/assets/{AgentsPage-vCTc3Qvj.js.map → AgentsPage-BuyXKkP3.js.map} +1 -1
- package/dashboard/dist/assets/{AvailableEscalationsPage-DJODShd7.js → AvailableEscalationsPage-BIzTjUMG.js} +2 -2
- package/dashboard/dist/assets/{AvailableEscalationsPage-DJODShd7.js.map → AvailableEscalationsPage-BIzTjUMG.js.map} +1 -1
- package/dashboard/dist/assets/{BotPicker-GU44inXA.js → BotPicker-xpPjRnkf.js} +2 -2
- package/dashboard/dist/assets/{BotPicker-GU44inXA.js.map → BotPicker-xpPjRnkf.js.map} +1 -1
- package/dashboard/dist/assets/{BulkAssignModal-ChqzG6FY.js → BulkAssignModal-CQ3k-7rO.js} +2 -2
- package/dashboard/dist/assets/{BulkAssignModal-ChqzG6FY.js.map → BulkAssignModal-CQ3k-7rO.js.map} +1 -1
- package/dashboard/dist/assets/{CapabilitiesPage-Y2hycdPY.js → CapabilitiesPage-DCkEJ0In.js} +2 -2
- package/dashboard/dist/assets/{CapabilitiesPage-Y2hycdPY.js.map → CapabilitiesPage-DCkEJ0In.js.map} +1 -1
- package/dashboard/dist/assets/{CollapsibleSection-CmCwt_Rs.js → CollapsibleSection-10sJSNNF.js} +2 -2
- package/dashboard/dist/assets/{CollapsibleSection-CmCwt_Rs.js.map → CollapsibleSection-10sJSNNF.js.map} +1 -1
- package/dashboard/dist/assets/{CountdownTimer-Bx2XXJOd.js → CountdownTimer-BFy9Joxb.js} +2 -2
- package/dashboard/dist/assets/{CountdownTimer-Bx2XXJOd.js.map → CountdownTimer-BFy9Joxb.js.map} +1 -1
- package/dashboard/dist/assets/{CredentialsPage-CoX_PNBe.js → CredentialsPage-DIR-fUoF.js} +2 -2
- package/dashboard/dist/assets/{CredentialsPage-CoX_PNBe.js.map → CredentialsPage-DIR-fUoF.js.map} +1 -1
- package/dashboard/dist/assets/{CronLabel-CVYKRipP.js → CronLabel-C66ASvgE.js} +2 -2
- package/dashboard/dist/assets/{CronLabel-CVYKRipP.js.map → CronLabel-C66ASvgE.js.map} +1 -1
- package/dashboard/dist/assets/{ElapsedCell-jRURiCRW.js → ElapsedCell-RWvrCHn7.js} +2 -2
- package/dashboard/dist/assets/{ElapsedCell-jRURiCRW.js.map → ElapsedCell-RWvrCHn7.js.map} +1 -1
- package/dashboard/dist/assets/{EntityTimelinePanel-G6nzvgpl.js → EntityTimelinePanel-CNaYs3nA.js} +2 -2
- package/dashboard/dist/assets/{EntityTimelinePanel-G6nzvgpl.js.map → EntityTimelinePanel-CNaYs3nA.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationListSchemaPage-D-rVTQ1m.js → EscalationListSchemaPage-BsRQtDDc.js} +2 -2
- package/dashboard/dist/assets/{EscalationListSchemaPage-D-rVTQ1m.js.map → EscalationListSchemaPage-BsRQtDDc.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationSchemaPage-CV0R_xY9.js → EscalationSchemaPage-BMYQmwGA.js} +2 -2
- package/dashboard/dist/assets/{EscalationSchemaPage-CV0R_xY9.js.map → EscalationSchemaPage-BMYQmwGA.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationsOverview-DMdx15CQ.js → EscalationsOverview-yv4Yn6zl.js} +2 -2
- package/dashboard/dist/assets/{EscalationsOverview-DMdx15CQ.js.map → EscalationsOverview-yv4Yn6zl.js.map} +1 -1
- package/dashboard/dist/assets/{EventTable-CIvsdt-q.js → EventTable-ebZK7vXl.js} +2 -2
- package/dashboard/dist/assets/{EventTable-CIvsdt-q.js.map → EventTable-ebZK7vXl.js.map} +1 -1
- package/dashboard/dist/assets/{FilterBar-DWYGkVRH.js → FilterBar-D6JDMSHi.js} +2 -2
- package/dashboard/dist/assets/{FilterBar-DWYGkVRH.js.map → FilterBar-D6JDMSHi.js.map} +1 -1
- package/dashboard/dist/assets/{GraphInvokePage-BGHlXh4r.js → GraphInvokePage-BFntNMop.js} +2 -2
- package/dashboard/dist/assets/{GraphInvokePage-BGHlXh4r.js.map → GraphInvokePage-BFntNMop.js.map} +1 -1
- package/dashboard/dist/assets/{HomePage-BHOnp8SK.js → HomePage-B24GH9Ga.js} +2 -2
- package/dashboard/dist/assets/{HomePage-BHOnp8SK.js.map → HomePage-B24GH9Ga.js.map} +1 -1
- package/dashboard/dist/assets/{ListToolbar-iOgn_db5.js → ListToolbar-DlGreUpP.js} +2 -2
- package/dashboard/dist/assets/{ListToolbar-iOgn_db5.js.map → ListToolbar-DlGreUpP.js.map} +1 -1
- package/dashboard/dist/assets/{McpOverview-Be9sMKCA.js → McpOverview-D0G2vACW.js} +2 -2
- package/dashboard/dist/assets/{McpOverview-Be9sMKCA.js.map → McpOverview-D0G2vACW.js.map} +1 -1
- package/dashboard/dist/assets/{McpQueryDetailPage-BIgpmGJN.js → McpQueryDetailPage-LZO04PEB.js} +2 -2
- package/dashboard/dist/assets/{McpQueryDetailPage-BIgpmGJN.js.map → McpQueryDetailPage-LZO04PEB.js.map} +1 -1
- package/dashboard/dist/assets/{McpQueryPage-Okcxw_Um.js → McpQueryPage-BIwSDHgB.js} +2 -2
- package/dashboard/dist/assets/{McpQueryPage-Okcxw_Um.js.map → McpQueryPage-BIwSDHgB.js.map} +1 -1
- package/dashboard/dist/assets/{McpRunDetailPage-DT8kOfih.js → McpRunDetailPage-DjYWJLWh.js} +2 -2
- package/dashboard/dist/assets/{McpRunDetailPage-DT8kOfih.js.map → McpRunDetailPage-DjYWJLWh.js.map} +1 -1
- package/dashboard/dist/assets/{McpRunsPage-BXhoP77D.js → McpRunsPage-CTT7B-pf.js} +2 -2
- package/dashboard/dist/assets/{McpRunsPage-BXhoP77D.js.map → McpRunsPage-CTT7B-pf.js.map} +1 -1
- package/dashboard/dist/assets/{OperationsPage-rVhC8JPv.js → OperationsPage-Dd0WxAwH.js} +2 -2
- package/dashboard/dist/assets/{OperationsPage-rVhC8JPv.js.map → OperationsPage-Dd0WxAwH.js.map} +1 -1
- package/dashboard/dist/assets/{OperatorDashboard-CIt061hu.js → OperatorDashboard-BfKMaVzV.js} +2 -2
- package/dashboard/dist/assets/{OperatorDashboard-CIt061hu.js.map → OperatorDashboard-BfKMaVzV.js.map} +1 -1
- package/dashboard/dist/assets/{PersonaDetailPage-r46uNF4E.js → PersonaDetailPage-B48MX4lq.js} +2 -2
- package/dashboard/dist/assets/{PersonaDetailPage-r46uNF4E.js.map → PersonaDetailPage-B48MX4lq.js.map} +1 -1
- package/dashboard/dist/assets/{PersonasPage-CayYv9-j.js → PersonasPage-dGX6E96g.js} +2 -2
- package/dashboard/dist/assets/{PersonasPage-CayYv9-j.js.map → PersonasPage-dGX6E96g.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessDetailPage-dn7lkM4c.js → ProcessDetailPage-Co5oCg31.js} +2 -2
- package/dashboard/dist/assets/{ProcessDetailPage-dn7lkM4c.js.map → ProcessDetailPage-Co5oCg31.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessesListPage-DOp5J6Be.js → ProcessesListPage-CrB4VAS6.js} +2 -2
- package/dashboard/dist/assets/{ProcessesListPage-DOp5J6Be.js.map → ProcessesListPage-CrB4VAS6.js.map} +1 -1
- package/dashboard/dist/assets/{RoleDetailPage-DOlNoiAK.js → RoleDetailPage-C4UTNx0p.js} +2 -2
- package/dashboard/dist/assets/{RoleDetailPage-DOlNoiAK.js.map → RoleDetailPage-C4UTNx0p.js.map} +1 -1
- package/dashboard/dist/assets/{RolesPage-DPppT6Zl.js → RolesPage-BXo5RirX.js} +2 -2
- package/dashboard/dist/assets/{RolesPage-DPppT6Zl.js.map → RolesPage-BXo5RirX.js.map} +1 -1
- package/dashboard/dist/assets/{RunAsSelector-BgntKfSA.js → RunAsSelector-BRQiGv2-.js} +2 -2
- package/dashboard/dist/assets/{RunAsSelector-BgntKfSA.js.map → RunAsSelector-BRQiGv2-.js.map} +1 -1
- package/dashboard/dist/assets/{ScanCodesPage-DPm1lG79.js → ScanCodesPage-BUT5wjzC.js} +2 -2
- package/dashboard/dist/assets/{ScanCodesPage-DPm1lG79.js.map → ScanCodesPage-BUT5wjzC.js.map} +1 -1
- package/dashboard/dist/assets/{ScanSchemeDetailPage-CuoG89q1.js → ScanSchemeDetailPage-CkzoOyjd.js} +2 -2
- package/dashboard/dist/assets/{ScanSchemeDetailPage-CuoG89q1.js.map → ScanSchemeDetailPage-CkzoOyjd.js.map} +1 -1
- package/dashboard/dist/assets/{ScanStationPage-2SLXqqs0.js → ScanStationPage-DYamACNZ.js} +2 -2
- package/dashboard/dist/assets/{ScanStationPage-2SLXqqs0.js.map → ScanStationPage-DYamACNZ.js.map} +1 -1
- package/dashboard/dist/assets/{StickyPagination-Bc_Mzu_R.js → StickyPagination-B3yiAcrs.js} +2 -2
- package/dashboard/dist/assets/{StickyPagination-Bc_Mzu_R.js.map → StickyPagination-B3yiAcrs.js.map} +1 -1
- package/dashboard/dist/assets/{StreamMessageDetail-S1cnLGkf.js → StreamMessageDetail-C56PtZSb.js} +2 -2
- package/dashboard/dist/assets/{StreamMessageDetail-S1cnLGkf.js.map → StreamMessageDetail-C56PtZSb.js.map} +1 -1
- package/dashboard/dist/assets/{SwimlaneTimeline-BUu2sPmY.js → SwimlaneTimeline-D64ep5KY.js} +2 -2
- package/dashboard/dist/assets/{SwimlaneTimeline-BUu2sPmY.js.map → SwimlaneTimeline-D64ep5KY.js.map} +1 -1
- package/dashboard/dist/assets/{TaskDetailPage-BMfNNtbN.js → TaskDetailPage-C2V7BcgB.js} +2 -2
- package/dashboard/dist/assets/{TaskDetailPage-BMfNNtbN.js.map → TaskDetailPage-C2V7BcgB.js.map} +1 -1
- package/dashboard/dist/assets/{TasksListPage-BmNnopOU.js → TasksListPage-C4ctoAa0.js} +2 -2
- package/dashboard/dist/assets/{TasksListPage-BmNnopOU.js.map → TasksListPage-C4ctoAa0.js.map} +1 -1
- package/dashboard/dist/assets/{TimeAgo-Dip7gQQx.js → TimeAgo-BpJ7In27.js} +2 -2
- package/dashboard/dist/assets/{TimeAgo-Dip7gQQx.js.map → TimeAgo-BpJ7In27.js.map} +1 -1
- package/dashboard/dist/assets/{TimestampCell-DRAYnIrx.js → TimestampCell-BKrIaU_R.js} +2 -2
- package/dashboard/dist/assets/{TimestampCell-DRAYnIrx.js.map → TimestampCell-BKrIaU_R.js.map} +1 -1
- package/dashboard/dist/assets/{ToolTestPanel-CQVYC3Ba.js → ToolTestPanel-CdTXWPqn.js} +2 -2
- package/dashboard/dist/assets/{ToolTestPanel-CQVYC3Ba.js.map → ToolTestPanel-CdTXWPqn.js.map} +1 -1
- package/dashboard/dist/assets/{TopicDetailPage-Bmtwuksg.js → TopicDetailPage-B6tb1RG4.js} +2 -2
- package/dashboard/dist/assets/{TopicDetailPage-Bmtwuksg.js.map → TopicDetailPage-B6tb1RG4.js.map} +1 -1
- package/dashboard/dist/assets/{TopicsPage-DIgF7-mJ.js → TopicsPage-DgdOKjwE.js} +2 -2
- package/dashboard/dist/assets/{TopicsPage-DIgF7-mJ.js.map → TopicsPage-DgdOKjwE.js.map} +1 -1
- package/dashboard/dist/assets/{UserName-DNKFz7X9.js → UserName-A-ET2GnX.js} +2 -2
- package/dashboard/dist/assets/{UserName-DNKFz7X9.js.map → UserName-A-ET2GnX.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowExecutionPage-DraIBNpl.js → WorkflowExecutionPage-CzhoRsis.js} +2 -2
- package/dashboard/dist/assets/{WorkflowExecutionPage-DraIBNpl.js.map → WorkflowExecutionPage-CzhoRsis.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsDashboard-BH7kmFjM.js → WorkflowsDashboard-B_tCYLei.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsDashboard-BH7kmFjM.js.map → WorkflowsDashboard-B_tCYLei.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsOverview-C98pCjQX.js → WorkflowsOverview-B4Bh8MIo.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsOverview-C98pCjQX.js.map → WorkflowsOverview-B4Bh8MIo.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-BWQjXenZ.js → YamlWorkflowDetailPage-zRrcxk0e.js} +2 -2
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-BWQjXenZ.js.map → YamlWorkflowDetailPage-zRrcxk0e.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowsPage-BGTI_sdP.js → YamlWorkflowsPage-DMK3ojp3.js} +2 -2
- package/dashboard/dist/assets/{YamlWorkflowsPage-BGTI_sdP.js.map → YamlWorkflowsPage-DMK3ojp3.js.map} +1 -1
- package/dashboard/dist/assets/{agents-DfMrlw54.js → agents-B67yyE1z.js} +2 -2
- package/dashboard/dist/assets/{agents-DfMrlw54.js.map → agents-B67yyE1z.js.map} +1 -1
- package/dashboard/dist/assets/{bots-B9zS0z7D.js → bots-pSLFdOm-.js} +2 -2
- package/dashboard/dist/assets/{bots-B9zS0z7D.js.map → bots-pSLFdOm-.js.map} +1 -1
- package/dashboard/dist/assets/{capabilities-DkLM1xgH.js → capabilities-B2Dem6zw.js} +2 -2
- package/dashboard/dist/assets/{capabilities-DkLM1xgH.js.map → capabilities-B2Dem6zw.js.map} +1 -1
- package/dashboard/dist/assets/{controlplane-SJK1yvbm.js → controlplane-DGdaM9f3.js} +2 -2
- package/dashboard/dist/assets/{controlplane-SJK1yvbm.js.map → controlplane-DGdaM9f3.js.map} +1 -1
- package/dashboard/dist/assets/{escalation-columns-BvAylNM1.js → escalation-columns-BM7vp-hY.js} +2 -2
- package/dashboard/dist/assets/{escalation-columns-BvAylNM1.js.map → escalation-columns-BM7vp-hY.js.map} +1 -1
- package/dashboard/dist/assets/{index-DamcWcqG.js → index-5eRsj758.js} +2 -2
- package/dashboard/dist/assets/{index-DamcWcqG.js.map → index-5eRsj758.js.map} +1 -1
- package/dashboard/dist/assets/{index-CLxuBb17.js → index-BD6nhSOu.js} +2 -2
- package/dashboard/dist/assets/{index-CLxuBb17.js.map → index-BD6nhSOu.js.map} +1 -1
- package/dashboard/dist/assets/{index-DvmyIGeZ.js → index-Baf-tOnA.js} +2 -2
- package/dashboard/dist/assets/{index-DvmyIGeZ.js.map → index-Baf-tOnA.js.map} +1 -1
- package/dashboard/dist/assets/{index-ClVNU3G3.js → index-Brf_fpE4.js} +2 -2
- package/dashboard/dist/assets/{index-ClVNU3G3.js.map → index-Brf_fpE4.js.map} +1 -1
- package/dashboard/dist/assets/{index-CXe2d5kg.js → index-CGoXyPlO.js} +2 -2
- package/dashboard/dist/assets/{index-CXe2d5kg.js.map → index-CGoXyPlO.js.map} +1 -1
- package/dashboard/dist/assets/{index-DazfFRUx.js → index-CKt5YK2z.js} +2 -2
- package/dashboard/dist/assets/{index-DazfFRUx.js.map → index-CKt5YK2z.js.map} +1 -1
- package/dashboard/dist/assets/index-CLq228E2.js +3 -0
- package/dashboard/dist/assets/index-CLq228E2.js.map +1 -0
- package/dashboard/dist/assets/{index-DKXOIcO3.js → index-Cd2RdpOx.js} +2 -2
- package/dashboard/dist/assets/{index-DKXOIcO3.js.map → index-Cd2RdpOx.js.map} +1 -1
- package/dashboard/dist/assets/{index-Cw-V0VhS.js → index-Cn__VdSf.js} +2 -2
- package/dashboard/dist/assets/{index-Cw-V0VhS.js.map → index-Cn__VdSf.js.map} +1 -1
- package/dashboard/dist/assets/{index-DSfY8oDp.js → index-CunrdEfT.js} +2 -2
- package/dashboard/dist/assets/{index-DSfY8oDp.js.map → index-CunrdEfT.js.map} +1 -1
- package/dashboard/dist/assets/{index-D2IRxjSf.js → index-DajlugVw.js} +2 -2
- package/dashboard/dist/assets/{index-D2IRxjSf.js.map → index-DajlugVw.js.map} +1 -1
- package/dashboard/dist/assets/{index-PjiXOVdw.js → index-DbLOvfv5.js} +2 -2
- package/dashboard/dist/assets/{index-PjiXOVdw.js.map → index-DbLOvfv5.js.map} +1 -1
- package/dashboard/dist/assets/{index-zrTQcPjB.js → index-zqoZDL5j.js} +3 -3
- package/dashboard/dist/assets/{index-zrTQcPjB.js.map → index-zqoZDL5j.js.map} +1 -1
- package/dashboard/dist/assets/{knowledge-BNp6MH-4.js → knowledge-BExXJ0Ib.js} +2 -2
- package/dashboard/dist/assets/{knowledge-BNp6MH-4.js.map → knowledge-BExXJ0Ib.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-Bb1k5rv-.js → mcp-D2WA-SHc.js} +2 -2
- package/dashboard/dist/assets/{mcp-Bb1k5rv-.js.map → mcp-D2WA-SHc.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-query-QVakMQnS.js → mcp-query-4Tsojk-z.js} +2 -2
- package/dashboard/dist/assets/{mcp-query-QVakMQnS.js.map → mcp-query-4Tsojk-z.js.map} +1 -1
- package/dashboard/dist/assets/{personas-DV2JUjVj.js → personas-Dy_XSYfJ.js} +2 -2
- package/dashboard/dist/assets/{personas-DV2JUjVj.js.map → personas-Dy_XSYfJ.js.map} +1 -1
- package/dashboard/dist/assets/{pipelines-BkVB7Q0p.js → pipelines-yDHgNtdx.js} +2 -2
- package/dashboard/dist/assets/{pipelines-BkVB7Q0p.js.map → pipelines-yDHgNtdx.js.map} +1 -1
- package/dashboard/dist/assets/{tasks-DvYWcASM.js → tasks-CGoPhQyw.js} +2 -2
- package/dashboard/dist/assets/{tasks-DvYWcASM.js.map → tasks-CGoPhQyw.js.map} +1 -1
- package/dashboard/dist/assets/{topics-B9zXFuVG.js → topics-DA1MHDwJ.js} +2 -2
- package/dashboard/dist/assets/{topics-B9zXFuVG.js.map → topics-DA1MHDwJ.js.map} +1 -1
- package/dashboard/dist/assets/{useEventHooks-JDpifqGZ.js → useEventHooks-onx-Z6IY.js} +2 -2
- package/dashboard/dist/assets/{useEventHooks-JDpifqGZ.js.map → useEventHooks-onx-Z6IY.js.map} +1 -1
- package/dashboard/dist/assets/{useNamespace-Bqr-LdWx.js → useNamespace-BkuU0SeK.js} +2 -2
- package/dashboard/dist/assets/{useNamespace-Bqr-LdWx.js.map → useNamespace-BkuU0SeK.js.map} +1 -1
- package/dashboard/dist/assets/{useYamlActivityEvents-n3naCEbw.js → useYamlActivityEvents-XXS3wg6-.js} +2 -2
- package/dashboard/dist/assets/{useYamlActivityEvents-n3naCEbw.js.map → useYamlActivityEvents-XXS3wg6-.js.map} +1 -1
- package/dashboard/dist/assets/{users-BNXLRVTS.js → users-B_9mC6D_.js} +2 -2
- package/dashboard/dist/assets/{users-BNXLRVTS.js.map → users-B_9mC6D_.js.map} +1 -1
- package/dashboard/dist/assets/{workflows-D8uMBPvQ.js → workflows-5sds1Ko8.js} +2 -2
- package/dashboard/dist/assets/{workflows-D8uMBPvQ.js.map → workflows-5sds1Ko8.js.map} +1 -1
- package/dashboard/dist/assets/{yaml-workflows-DVDOQM3Y.js → yaml-workflows-CjNa2u3I.js} +2 -2
- package/dashboard/dist/assets/{yaml-workflows-DVDOQM3Y.js.map → yaml-workflows-CjNa2u3I.js.map} +1 -1
- package/dashboard/dist/index.html +1 -1
- package/docs/api/http/workflows.md +35 -0
- package/docs/api/mcp/admin.md +14 -0
- package/docs/api/sdk/workflows.md +21 -0
- package/docs/hitl/lookups.md +10 -0
- package/docs/hitl/x-lt-validation.md +2 -1
- package/docs/hitl/x-lt-widget.md +1 -1
- package/docs/hitl-guide.md +2 -2
- package/package.json +2 -2
- package/dashboard/dist/assets/index-DTZxHZJO.js +0 -3
- package/dashboard/dist/assets/index-DTZxHZJO.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-CLq228E2.js","sources":["../../../types/validation.ts","../../src/components/scan/ScanConfirmModal.tsx","../../src/components/common/display/EscalationTimeline.tsx","../../src/components/escalation/TriageContext.tsx","../../../shared/form-validation/derive-field-label.ts","../../src/components/escalation/EscalationSidePanel.tsx","../../../shared/form-validation/ctx-path.ts","../../../shared/form-validation/x-lt-options.ts","../../../shared/form-validation/field-validator.ts","../../../shared/form-validation/x-lt-show-if.ts","../../../shared/form-validation/x-lt-require-any.ts","../../../shared/form-validation/x-lt-require-sum.ts","../../../shared/form-validation/validate-resolver-payload.ts","../../src/lib/resolver-payload.ts","../../src/pages/operator/escalation-detail/EscalationActionBar.tsx","../../src/components/escalation/RoundsExhaustedContext.tsx","../../src/components/escalation/IframeViewport.tsx","../../src/components/escalation/resolver-form/LockedFormFrame.tsx","../../src/components/escalation/resolver-form/FieldChrome.tsx","../../src/components/escalation/widgets/FileUploadWidget.tsx","../../src/components/escalation/widgets/CodeEditorWidget.tsx","../../src/components/escalation/widgets/SignatureWidget.tsx","../../src/components/escalation/widgets/RichTextWidget.tsx","../../src/components/escalation/widgets/MarkdownWidget.tsx","../../src/components/escalation/widgets/ChecklistWidget.tsx","../../src/components/escalation/widgets/AttachmentWidget.tsx","../../src/components/escalation/widgets/LinkWidget.tsx","../../src/components/escalation/widgets/OpenDetailButton.tsx","../../src/components/escalation/widgets/EscalationWidget.tsx","../../../shared/form-validation/x-lt-query.ts","../../src/components/escalation/widgets/EscalationListWidget.tsx","../../src/components/escalation/widgets/index.ts","../../src/components/escalation/resolver-form/FieldRow.tsx","../../src/components/escalation/resolver-form/DictionaryList.tsx","../../src/components/escalation/resolver-form/form-cells.ts","../../src/components/escalation/resolver-form/SectionGroup.tsx","../../src/components/escalation/resolver-form/ResolverForm.tsx","../../src/pages/operator/escalation-detail/ResolverSection.tsx","../../src/pages/operator/escalation-detail/EscalationDetailSections.tsx","../../src/pages/operator/escalation-detail/ClaimExpiryModal.tsx","../../src/hooks/useClaimClock.ts","../../src/lib/draft-store.ts","../../../shared/form-validation/x-lt-transition.ts","../../../shared/form-validation/x-lt-submit-on-claim.ts","../../../shared/form-validation/x-lt-submit-guard.ts","../../src/hooks/useSubmitGuard.ts","../../src/components/escalation/TransitionWaitModal.tsx","../../src/pages/operator/escalation-detail/EscalationDetailPage.tsx"],"sourcesContent":["/**\n * Canonical validation-error shapes — one vocabulary across every surface.\n *\n * When server-side resolver schema enforcement rejects a payload, the API\n * layer returns status 422 with `LTValidationErrorBody` as the response body.\n * The same body shape flows to every consumer:\n * - HTTP routes serialize it as the JSON response body\n * - SDK callers receive it as `result.data` (with `result.code` set)\n * - MCP resolve tools return it as the tool's JSON error content\n * - the CLI prints the violation list beneath the error line\n * - the dashboard maps `violations` into the same errors panel the\n * pre-submission pass feeds\n */\n\n/** Machine-readable error codes carried on error envelopes and bodies. */\nexport const LT_ERROR_CODES = {\n /** The resolver payload failed the role's enforced form schema. */\n SCHEMA_VALIDATION: 'schema_validation',\n} as const;\n\nexport type LTErrorCode = (typeof LT_ERROR_CODES)[keyof typeof LT_ERROR_CODES];\n\n/**\n * One field-level violation — the same `{ field, message }` pair the dashboard\n * validation panel renders. Bulk surfaces add `escalationId` so a violation is\n * attributable to the row that produced it.\n */\nexport interface LTFieldViolation {\n field: string;\n message: string;\n escalationId?: string;\n}\n\n/** The 422 response body for a schema-validation rejection. */\nexport interface LTValidationErrorBody {\n /** Human-readable summary, e.g. \"resolverPayload failed schema validation (2 violations)\". */\n error: string;\n code: typeof LT_ERROR_CODES.SCHEMA_VALIDATION;\n /** Every field-level violation, in schema property order. */\n violations: LTFieldViolation[];\n /** The role whose enforced schema rejected the payload. */\n role: string;\n /** The schema version validated against; null when the role's live (unversioned) schema applied. */\n schemaVersion: number | null;\n}\n\n/** Narrow an unknown response body to the canonical validation-error shape. */\nexport function isValidationErrorBody(body: unknown): body is LTValidationErrorBody {\n return (\n typeof body === 'object' && body !== null\n && (body as Record<string, unknown>).code === LT_ERROR_CODES.SCHEMA_VALIDATION\n && Array.isArray((body as Record<string, unknown>).violations)\n );\n}\n","import { useState } from 'react';\nimport { useLocation, useNavigate } from 'react-router-dom';\nimport { useQueryClient } from '@tanstack/react-query';\nimport { Modal } from '../common/modal/Modal';\nimport { apiFetch } from '../../api/client';\nimport { SCAN_VERBS, type ScanPendingAction } from '../../api/scan-codes';\nimport { SCAN_PENDING_ACTION_STATE } from '../../hooks/useScanInput';\n\n/**\n * Second phase of a confirmed scan action. The scan located the escalation\n * and navigated here with the pending action in route state; this modal asks\n * the rule's prompt and, on confirm, fires the standard per-id endpoint —\n * the same guarded calls every other surface uses.\n */\nexport function ScanConfirmModal({ escalationId }: { escalationId: string }) {\n const location = useLocation();\n const navigate = useNavigate();\n const queryClient = useQueryClient();\n const pending = (location.state as Record<string, unknown> | null)\n ?.[SCAN_PENDING_ACTION_STATE] as ScanPendingAction | undefined;\n const [busy, setBusy] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [dismissed, setDismissed] = useState(false);\n\n if (!pending || pending.escalationId !== escalationId || dismissed) return null;\n\n const clearState = () => {\n setDismissed(true);\n // Drop the pending action from history so refresh/back never re-prompts.\n navigate(location.pathname, { replace: true, state: null });\n };\n\n const confirm = async () => {\n setBusy(true);\n setError(null);\n try {\n switch (pending.verb) {\n case SCAN_VERBS.CANCEL:\n await apiFetch(`/escalations/${escalationId}/cancel`, { method: 'POST' });\n break;\n case SCAN_VERBS.CLAIM:\n case SCAN_VERBS.CLAIM_SHOW_DETAIL:\n await apiFetch(`/escalations/${escalationId}/claim`, {\n method: 'POST',\n body: JSON.stringify({ durationMinutes: pending.params?.durationMinutes ?? 30 }),\n });\n break;\n case SCAN_VERBS.RELEASE:\n await apiFetch(`/escalations/${escalationId}/release`, { method: 'POST' });\n break;\n case SCAN_VERBS.RESOLVE:\n await apiFetch(`/escalations/${escalationId}/resolve`, {\n method: 'POST',\n body: JSON.stringify({ resolverPayload: pending.params?.resolverPayload ?? {} }),\n });\n break;\n case SCAN_VERBS.ESCALATE:\n await apiFetch(`/escalations/${escalationId}/escalate`, {\n method: 'PATCH',\n body: JSON.stringify({ targetRole: pending.params?.targetRole }),\n });\n break;\n default:\n throw new Error(`Unsupported confirm verb \"${pending.verb}\"`);\n }\n queryClient.resetQueries({ queryKey: ['escalations'] });\n queryClient.resetQueries({ queryKey: ['escalationStats'] });\n clearState();\n } catch (err: any) {\n setError(err.message);\n } finally {\n setBusy(false);\n }\n };\n\n return (\n <Modal open onClose={clearState} title=\"Confirm scan action\">\n <div className=\"space-y-4\">\n <p className=\"text-sm text-text-secondary\">{pending.prompt}</p>\n {error && <p className=\"text-xs text-status-error\">{error}</p>}\n <div className=\"flex justify-end gap-3 pt-2\">\n <button onClick={clearState} disabled={busy} className=\"btn-secondary text-xs\">\n No, go back\n </button>\n <button onClick={confirm} disabled={busy} className=\"btn-primary text-xs\">\n {busy ? 'Working…' : 'Yes, continue'}\n </button>\n </div>\n </div>\n </Modal>\n );\n}\n","import { formatDurationCompact } from '../../../lib/format';\nimport { isEffectivelyClaimed } from '../../../lib/escalation';\nimport type { LTEscalationRecord } from '../../../api/types';\n\n// Matches the palette used in EscalationTimeline (the spine view) and PaceChart.\n// Hues resolve through the --lt-* status tokens so registered themes restyle\n// the bar; the navy default keeps the sky/orange/green/red look.\nconst COLORS = {\n pending: 'rgb(var(--lt-status-queued-graphic))', // sky blue — waiting to be claimed\n claimed: 'rgb(var(--lt-status-claimed-graphic))', // orange — actively being worked\n resolved: 'rgb(var(--lt-status-success-graphic))', // green — done\n cancelled: 'rgb(var(--lt-status-error))', // red — cancelled or expired\n} as const;\n\nconst BAR_H = 4; // px\n\n/** A duration label tethered to a point on the bar by a thin vertical tick. */\nfunction Marker({ pct, place, label, title, emphasis }: {\n pct: number;\n place: 'above' | 'below';\n label: string;\n title: string;\n emphasis?: boolean;\n}) {\n const tick = <span className=\"w-px h-1 bg-text-quaternary/70\" aria-hidden />;\n const text = (\n <span className={`whitespace-nowrap leading-none tabular-nums text-[10px] ${emphasis ? 'text-text-tertiary' : 'text-text-quaternary'}`}>\n {label}\n </span>\n );\n return (\n <div\n title={title}\n className={`absolute ${place === 'above' ? 'bottom-0' : 'top-0'} flex flex-col items-center gap-0 -translate-x-1/2 cursor-help`}\n style={{ left: `${pct}%` }}\n >\n {place === 'above' ? <>{text}{tick}</> : <>{tick}{text}</>}\n </div>\n );\n}\n\n/**\n * Compact lifecycle sparkline for the escalation detail side panel.\n *\n * Bar segments: blue (pending — waiting to be claimed) → orange (claimed —\n * being worked) → green (resolved) or red (cancelled). Markers show\n * time-to-claim above the split point and total duration below the right edge.\n */\nexport function EscalationTimeline({ esc, className = '' }: { esc: LTEscalationRecord; className?: string }) {\n const created = new Date(esc.created_at).getTime();\n const claimedAt = esc.claimed_at ? new Date(esc.claimed_at).getTime() : null;\n\n const isResolved = esc.status === 'resolved';\n const isCancelled = esc.status === 'cancelled' || esc.status === 'expired';\n const isTerminal = isResolved || isCancelled;\n const activeClaim = isEffectivelyClaimed(esc);\n\n const showClaimed = !!claimedAt && (activeClaim || isTerminal);\n\n const end = isResolved && esc.resolved_at\n ? new Date(esc.resolved_at).getTime()\n : isCancelled\n ? new Date(esc.updated_at).getTime()\n : Date.now();\n\n const total = Math.max(end - created, 1);\n const pendingMs = showClaimed && claimedAt ? Math.max(claimedAt - created, 0) : total;\n const activeMs = showClaimed && claimedAt ? Math.max(end - claimedAt, 0) : 0;\n\n const pendingPct = Math.min(100, Math.max(0, (pendingMs / total) * 100));\n const activePct = showClaimed ? Math.max(0, 100 - pendingPct) : 0;\n\n const activeColor = isResolved ? COLORS.resolved : isCancelled ? COLORS.cancelled : COLORS.claimed;\n const activeVerb = isResolved ? 'Resolved after' : isCancelled ? 'Cancelled after' : 'In progress';\n\n const split = formatDurationCompact(pendingMs);\n const totalStr = formatDurationCompact(total);\n const totalTip = isResolved\n ? `Resolved in ${totalStr} total`\n : isCancelled\n ? `Cancelled after ${totalStr}`\n : `Open ${totalStr} so far`;\n\n const legend = `Lifecycle bar: blue = time waiting to be claimed, ${isResolved ? 'green' : isCancelled ? 'red' : 'orange'} = ${activeVerb.toLowerCase()} the claim.`;\n\n return (\n <div className={className} title={legend}>\n {/* claim split label (above bar) */}\n <div className=\"relative h-2.5 font-mono\">\n {showClaimed && (\n <Marker\n pct={pendingPct}\n place=\"above\"\n label={split}\n title={`Time to claim: ${split}`}\n />\n )}\n </div>\n\n {/* Bar track */}\n <div\n className=\"flex w-full rounded-full overflow-hidden\"\n style={{ height: BAR_H, backgroundColor: 'rgb(var(--lt-surface-sunken))' }}\n title={legend}\n >\n {/* Pending (blue) */}\n <div\n style={{ width: `${pendingPct}%`, minWidth: BAR_H, backgroundColor: COLORS.pending, opacity: 0.75 }}\n title={`Waiting ${split} — created → claimed`}\n />\n {/* Claimed / resolved / cancelled */}\n {showClaimed && activePct > 0 && (\n <div\n style={{ width: `${activePct}%`, minWidth: BAR_H, backgroundColor: activeColor, opacity: 0.75 }}\n title={`${activeVerb} ${formatDurationCompact(activeMs)}`}\n />\n )}\n </div>\n\n {/* Total / age label (below bar, anchored at right edge) */}\n <div className=\"relative h-2.5 font-mono\">\n <Marker pct={100} place=\"below\" emphasis label={totalStr} title={totalTip} />\n </div>\n </div>\n );\n}\n","interface TriageData {\n diagnosis?: string;\n actions_taken?: string[];\n tool_calls_made?: number;\n confidence?: number;\n recommendation?: string;\n correctedData?: Record<string, unknown>;\n originalData?: Record<string, unknown>;\n}\n\ntype Diff = { key: string; label: string; original: unknown; corrected: unknown };\n\n/**\n * Renders a triage summary when escalation payload contains `_triage`.\n *\n * Fully generic — no knowledge of workflow types or field semantics.\n * Diffs `_triage.originalData` against the payload to detect changes.\n * Follows the unboxed section pattern used throughout the dashboard.\n */\nexport function TriageContext({ triage, payload }: {\n triage: TriageData;\n payload: Record<string, unknown>;\n}) {\n const confidence = triage.confidence ?? 0;\n const confidenceColor =\n confidence >= 0.8 ? 'text-status-success' :\n confidence >= 0.5 ? 'text-status-pending' :\n 'text-status-error';\n\n // Generic diff: compare originalData fields to current payload\n const diffs = computeDiffs(triage.originalData, payload);\n\n return (\n <div className=\"space-y-5\">\n {/* Diagnosis + metadata — unboxed, natural flow */}\n {triage.diagnosis && (\n <p className=\"text-sm text-text-primary leading-relaxed\">\n {triage.diagnosis}\n </p>\n )}\n\n <div className=\"flex flex-wrap items-center gap-3 text-xs text-text-tertiary\">\n {triage.tool_calls_made != null && (\n <span>{triage.tool_calls_made} tool call{triage.tool_calls_made !== 1 ? 's' : ''}</span>\n )}\n {triage.tool_calls_made != null && <span className=\"text-text-quaternary\">·</span>}\n <span className={`font-medium ${confidenceColor}`}>\n {Math.round(confidence * 100)}% confidence\n </span>\n </div>\n\n {triage.actions_taken && triage.actions_taken.length > 0 && (\n <div className=\"flex flex-wrap gap-1.5\">\n {triage.actions_taken.map((action, i) => (\n <span\n key={i}\n className=\"inline-flex items-center gap-1.5 px-2 py-0.5 text-2xs\n text-text-secondary\"\n >\n <svg className=\"w-3 h-3 text-status-success shrink-0\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2.5}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M5 13l4 4L19 7\" />\n </svg>\n {action}\n </span>\n ))}\n </div>\n )}\n\n {triage.recommendation && (\n <p className=\"text-2xs text-text-tertiary italic\">\n {triage.recommendation}\n </p>\n )}\n\n {/* Generic before/after diffs — separated by subtle dividers */}\n {diffs.length > 0 && (\n <div className=\"space-y-4 pt-2\">\n {diffs.map((diff) => (\n <DiffRow key={diff.key} diff={diff} />\n ))}\n </div>\n )}\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Generic diff computation\n// ---------------------------------------------------------------------------\n\nfunction computeDiffs(\n original: Record<string, unknown> | undefined,\n current: Record<string, unknown>,\n): Diff[] {\n if (!original) return [];\n\n const diffs: Diff[] = [];\n for (const key of Object.keys(original)) {\n if (key.startsWith('_')) continue;\n const origVal = original[key];\n const currVal = current[key];\n if (currVal === undefined) continue;\n\n if (JSON.stringify(origVal) !== JSON.stringify(currVal)) {\n diffs.push({\n key,\n label: key.replace(/[_-]/g, ' '),\n original: origVal,\n corrected: currVal,\n });\n }\n }\n return diffs;\n}\n\n// ---------------------------------------------------------------------------\n// Diff row — clean, unboxed before/after\n// ---------------------------------------------------------------------------\n\nfunction DiffRow({ diff }: { diff: Diff }) {\n const origStr = renderValue(diff.original);\n const corrStr = renderValue(diff.corrected);\n\n // Both are primitives — side by side when the container allows. This view\n // renders inside the side panel, so the container is what matters.\n if (origStr !== null && corrStr !== null) {\n return (\n <div className=\"@container\">\n <div className=\"grid grid-cols-1 @form-cols:grid-cols-2 gap-x-8 gap-y-3\">\n <div>\n <p className=\"text-2xs font-semibold uppercase tracking-widest text-text-tertiary mb-1\">\n {diff.label} <span className=\"normal-case font-normal\">(original)</span>\n </p>\n <p className=\"text-sm text-text-tertiary leading-relaxed line-through decoration-text-tertiary/30\">\n {origStr}\n </p>\n </div>\n <div>\n <p className=\"text-2xs font-semibold uppercase tracking-widest text-text-tertiary mb-1\">\n {diff.label} <span className=\"normal-case font-normal text-status-success\">(corrected)</span>\n </p>\n <p className=\"text-sm text-text-primary leading-relaxed\">\n {corrStr}\n </p>\n </div>\n </div>\n </div>\n );\n }\n\n // Complex values — stacked\n return (\n <div className=\"space-y-3\">\n <div>\n <p className=\"text-2xs font-semibold uppercase tracking-widest text-text-tertiary mb-1\">\n {diff.label} <span className=\"normal-case font-normal\">(original)</span>\n </p>\n <pre className=\"text-xs text-text-tertiary font-mono whitespace-pre-wrap leading-relaxed\">\n {typeof diff.original === 'object' ? JSON.stringify(diff.original, null, 2) : String(diff.original)}\n </pre>\n </div>\n <div>\n <p className=\"text-2xs font-semibold uppercase tracking-widest text-text-tertiary mb-1\">\n {diff.label} <span className=\"normal-case font-normal text-status-success\">(corrected)</span>\n </p>\n <pre className=\"text-xs text-text-primary font-mono whitespace-pre-wrap leading-relaxed\">\n {typeof diff.corrected === 'object' ? JSON.stringify(diff.corrected, null, 2) : String(diff.corrected)}\n </pre>\n </div>\n </div>\n );\n}\n\n/** Render a value as a string if it's a primitive, null otherwise */\nfunction renderValue(val: unknown): string | null {\n if (val === null || val === undefined) return 'null';\n if (typeof val === 'string') return val;\n if (typeof val === 'number' || typeof val === 'boolean') return String(val);\n return null;\n}\n","/**\n * Human-readable label for a schema field.\n *\n * Resolution order:\n * 1. The JSON Schema `title` keyword — the author's explicit label, always wins.\n * 2. Snake/kebab keys become Title Case: `left_quantity` → `Left Quantity`.\n * 3. Single-token keys pass through unchanged: `PO`, `SKU`, `LEFTQUANTITY` —\n * a run of capitals carries no word boundaries to recover, and lowercasing\n * would mangle acronyms. Authors who want prose labels declare `title`.\n *\n * Used everywhere a field name faces a human: form labels, dictionary lists,\n * the errors panel, and metadata displays.\n */\nexport function deriveFieldLabel(\n key: string,\n fieldSchema?: Record<string, unknown> | null,\n): string {\n const title = fieldSchema?.title;\n if (typeof title === 'string' && title.trim().length > 0) return title.trim();\n\n const words = key.split(/[_-]+/).filter(Boolean);\n if (words.length <= 1) return key;\n\n return words\n .map((w) => (isCapsToken(w) ? w : w.charAt(0).toUpperCase() + w.slice(1)))\n .join(' ');\n}\n\n/** All-caps tokens (PO, SKU, ID) keep their casing inside multi-word keys. */\nfunction isCapsToken(word: string): boolean {\n return word.length > 1 && word === word.toUpperCase() && /[A-Z]/.test(word);\n}\n","import { useMemo, useState, useCallback, useEffect } from 'react';\nimport { useNavigate, Link } from 'react-router-dom';\nimport { HelpCircle, Info, Tags, Layers, Braces, Sparkles, User, ListFilter, Search, AlertCircle } from 'lucide-react';\nimport { SlidePanel, SlidePanelViews, PanelField, type SlidePanelView } from '../common/layout/SlidePanel';\nimport { MarkdownRenderer } from '../common/display/MarkdownRenderer';\nimport { JsonViewer } from '../common/data/JsonViewer';\nimport { StatusBadge } from '../common/display/StatusBadge';\nimport { EscalationTimeline } from '../common/display/EscalationTimeline';\nimport { RolePill } from '../common/display/RolePill';\nimport { CountdownTimer } from '../common/display/CountdownTimer';\nimport { DateValue } from '../common/display/DateValue';\nimport { CopyableId } from '../common/display/CopyableId';\nimport { UserName } from '../common/display/UserName';\nimport { TriageContext } from './TriageContext';\nimport { buildHelpMarkdown, defaultHelpMarkdown } from '../../lib/x-lt-help';\nimport { deriveFieldLabel } from '../../lib/derive-field-label';\nimport { metadataFacetUrl } from '../../lib/facet-url';\nimport { displayMetadataEntries } from '../../lib/metadata-display';\nimport type { LTEscalationRecord } from '../../api/types';\nimport type { FieldError } from '../../lib/field-validator';\n\nexport const ESCALATION_PANEL_VIEWS = {\n HELP: 'help',\n DETAILS: 'details',\n TRIAGE: 'triage',\n METADATA: 'metadata',\n CONTEXT: 'context',\n RECORD: 'record',\n ERRORS: 'errors',\n} as const;\n\nconst PANEL_VIEW_KEY = 'lt:escalation:panel:view';\n\nfunction readPanelView(validIds: readonly string[]): PanelViewId {\n try {\n const v = localStorage.getItem(PANEL_VIEW_KEY);\n if (v && validIds.includes(v)) return v as PanelViewId;\n } catch {}\n return ESCALATION_PANEL_VIEWS.HELP;\n}\n\ntype PanelViewId = (typeof ESCALATION_PANEL_VIEWS)[keyof typeof ESCALATION_PANEL_VIEWS];\n\nfunction MetadataList({ metadata, role }: { metadata: Record<string, unknown> | null; role: string }) {\n const entries = displayMetadataEntries(metadata);\n if (entries.length === 0) {\n return <p className=\"text-xs text-text-tertiary italic\">No metadata on this escalation.</p>;\n }\n return (\n <dl className=\"space-y-3.5\">\n {entries.map(([key, value]) => {\n const displayValue = typeof value === 'object' && value !== null\n ? JSON.stringify(value)\n : String(value);\n const roleUrl = metadataFacetUrl(key, value, role);\n const globalUrl = metadataFacetUrl(key, value);\n return (\n <div key={key} className=\"group relative\">\n <dt className=\"text-2xs font-medium text-text-secondary uppercase tracking-wide\">\n {deriveFieldLabel(key)}\n </dt>\n <dd className=\"mt-0.5 flex items-center gap-1\">\n <span className=\"text-xs text-text-primary font-mono break-all flex-1\">\n {displayValue}\n </span>\n <Link\n to={roleUrl}\n title={`Filter this queue: ${key} = ${displayValue}`}\n className=\"opacity-50 group-hover:opacity-100 transition-opacity shrink-0 p-0.5 text-text-quaternary hover:text-accent\"\n >\n <ListFilter className=\"w-3 h-3\" />\n </Link>\n <Link\n to={globalUrl}\n title={`Search all queues: ${key} = ${displayValue}`}\n className=\"opacity-50 group-hover:opacity-100 transition-opacity shrink-0 p-0.5 text-text-quaternary hover:text-accent\"\n >\n <Search className=\"w-3 h-3\" />\n </Link>\n </dd>\n </div>\n );\n })}\n </dl>\n );\n}\n\n/** The escalation's status facts — what used to sit as a strip above the form. */\nfunction DetailsList({ esc, claimed, isTerminal, isBuilder, traceUrl }: {\n esc: LTEscalationRecord;\n claimed: boolean;\n isTerminal: boolean;\n isBuilder: boolean;\n traceUrl: string | null;\n}) {\n return (\n <div className=\"space-y-5\">\n <dl className=\"space-y-3.5\">\n <PanelField label=\"Status\"><StatusBadge status={esc.status} /></PanelField>\n <PanelField label=\"Assigned to Role\"><RolePill role={esc.role} size=\"md\" /></PanelField>\n <PanelField label=\"Priority\">P{esc.priority}</PanelField>\n {(claimed || isTerminal) && esc.assigned_to && (\n <PanelField label=\"Claimed By\">\n <span className=\"inline-flex items-center gap-1.5 font-medium text-text-primary\">\n <User className=\"w-3 h-3 shrink-0 text-accent/75\" />\n <UserName userId={esc.assigned_to} />\n </span>\n </PanelField>\n )}\n <PanelField label=\"Created\"><DateValue date={esc.created_at} /></PanelField>\n {(claimed || isTerminal) && esc.claimed_at && (\n <PanelField label=\"Claimed\"><DateValue date={esc.claimed_at} /></PanelField>\n )}\n {claimed && !isTerminal && esc.assigned_until && (\n <PanelField label=\"Time Remaining\"><CountdownTimer until={esc.assigned_until} /></PanelField>\n )}\n {esc.resolved_at && (\n <PanelField label=\"Completed\">\n <span className=\"text-status-success\"><DateValue date={esc.resolved_at} /></span>\n </PanelField>\n )}\n </dl>\n\n {/* Identifiers — builder-facing references, quietly below a divider */}\n {isBuilder && (\n <>\n <hr className=\"border-surface-border/60\" />\n <div className=\"space-y-3.5\">\n <CopyableId label=\"Escalation ID\" value={esc.id} />\n {esc.task_id && (\n <CopyableId label=\"Task ID\" value={esc.task_id} href={`/workflows/tasks/detail/${esc.task_id}`} />\n )}\n {esc.workflow_type && (\n <CopyableId label=\"Workflow Name\" value={esc.workflow_type} href={`/workflows/executions?entity=${encodeURIComponent(esc.workflow_type)}`} />\n )}\n {esc.workflow_id && (\n <CopyableId label=\"Workflow ID\" value={esc.workflow_id} href={`/workflows/executions/${esc.workflow_id}`} />\n )}\n {esc.task_queue && (\n <CopyableId label=\"Task Queue\" value={esc.task_queue} href={`/admin/controlplane?queue=${encodeURIComponent(esc.task_queue)}`} />\n )}\n {esc.origin_id && esc.origin_id !== esc.workflow_id && (\n <CopyableId label=\"Origin\" value={esc.origin_id} href={`/processes/detail/${esc.origin_id}`} />\n )}\n {esc.trace_id && (\n <CopyableId\n label=\"Trace\"\n value={esc.trace_id}\n href={traceUrl ? traceUrl.replace('{traceId}', esc.trace_id) : undefined}\n external\n />\n )}\n </div>\n </>\n )}\n </div>\n );\n}\n\nfunction ErrorsPanel({ errors, schema }: { errors: FieldError[]; schema?: Record<string, unknown> | null }) {\n const focusField = (field: string) => {\n const el = document.querySelector<HTMLElement>(`[data-field-key=\"${field}\"]`);\n if (!el) return;\n el.scrollIntoView({ behavior: 'smooth', block: 'center' });\n el.focus({ preventScroll: true });\n };\n\n if (errors.length === 0) {\n return <p className=\"text-xs text-text-tertiary italic\">No errors to display.</p>;\n }\n\n return (\n <div className=\"space-y-1\" role=\"alert\" aria-live=\"polite\">\n <p className=\"text-2xs font-semibold uppercase tracking-wider text-status-error mb-4\">\n {errors.length} {errors.length === 1 ? 'issue' : 'issues'} to resolve\n </p>\n <div className=\"space-y-1.5\">\n {errors.map(({ field, message }) => (\n <button\n key={field}\n onClick={() => focusField(field)}\n className=\"w-full text-left flex items-start gap-3 px-3 py-2.5 rounded hover:bg-status-error/5 transition-colors group\"\n >\n <AlertCircle className=\"w-3.5 h-3.5 mt-0.5 shrink-0 text-status-error/60 group-hover:text-status-error transition-colors\" />\n <div>\n <p className=\"text-2xs font-semibold text-text-primary leading-snug\">\n {deriveFieldLabel(field, (schema?.properties as Record<string, Record<string, unknown>> | undefined)?.[field])}\n </p>\n <p className=\"text-2xs text-text-tertiary group-hover:text-text-secondary transition-colors leading-snug mt-0.5\">\n {message}\n </p>\n </div>\n </button>\n ))}\n </div>\n <p className=\"text-2xs text-text-quaternary mt-4 px-3\">\n Click an issue to scroll to and focus the field.\n </p>\n </div>\n );\n}\n\n/**\n * The escalation detail side panel — a set of views beside the resolve form,\n * ordered by specificity:\n *\n * Help — the form's `x-lt-help` markdown ({{token}}-interpolated), or a\n * state-aware hint when the schema carries none\n * Details — status, role, claim provenance, timestamps, identifiers\n * AI Analysis — what triage diagnosed and corrected (when AI is enabled and\n * the payload carries triage data)\n * Metadata — the row's metadata values, the facts stamped at enqueue\n * Context — the expanded surface: input envelope, escalation context, and\n * resolver payload\n * Record — the raw escalation record (builders only)\n */\nexport function EscalationSidePanel({\n esc,\n schema,\n envelope,\n payload,\n resolver,\n triage,\n hasAI,\n claimed,\n claimedByMe,\n isTerminal,\n isBuilder,\n traceUrl,\n open,\n noGutter,\n formErrors,\n activePanel,\n onPanelChange,\n}: {\n esc: LTEscalationRecord;\n schema: Record<string, unknown> | null;\n envelope: Record<string, unknown> | null;\n payload: Record<string, unknown> | null;\n resolver: Record<string, unknown> | null;\n triage: Record<string, unknown> | null;\n hasAI: boolean;\n claimed: boolean;\n claimedByMe: boolean;\n isTerminal: boolean;\n isBuilder: boolean;\n traceUrl: string | null;\n open: boolean;\n /** Remove the left gutter so the panel background is flush with the content column (used in full-bleed iframe mode). */\n noGutter?: boolean;\n /** Structured form validation errors from the last submit attempt. When non-empty, the errors panel is available. */\n formErrors?: FieldError[];\n /** Controlled active panel view id. When provided, the panel uses this instead of internal state. */\n activePanel?: string;\n /** Called when the user changes the active panel view. */\n onPanelChange?: (id: string) => void;\n}) {\n const navigate = useNavigate();\n const ALL_VIEW_IDS = Object.values(ESCALATION_PANEL_VIEWS) as readonly string[];\n const [internalView, setInternalView] = useState<PanelViewId>(() => readPanelView(ALL_VIEW_IDS));\n\n const activeView = (activePanel as PanelViewId | undefined) ?? internalView;\n\n const handleViewChange = useCallback((id: string) => {\n try { localStorage.setItem(PANEL_VIEW_KEY, id); } catch {}\n setInternalView(id as PanelViewId);\n onPanelChange?.(id);\n }, [onPanelChange]);\n\n // Sync to controlled activePanel when it changes externally (e.g. page forces 'errors' after submit).\n useEffect(() => {\n if (activePanel && activePanel !== internalView) {\n setInternalView(activePanel as PanelViewId);\n }\n }, [activePanel]); // eslint-disable-line react-hooks/exhaustive-deps\n\n const helpMarkdown = useMemo(() => {\n const authored = buildHelpMarkdown(schema, {\n escalation: esc as unknown as Record<string, unknown>,\n metadata: esc.metadata ?? null,\n envelope,\n payload,\n resolver,\n });\n return authored ?? defaultHelpMarkdown({ isTerminal, status: esc.status, claimed, claimedByMe });\n }, [schema, esc, envelope, payload, resolver, isTerminal, claimed, claimedByMe]);\n\n // Relative links in help markdown navigate in-app instead of reloading.\n const handleHelpClick = useCallback((e: React.MouseEvent<HTMLDivElement>) => {\n const anchor = (e.target as HTMLElement).closest('a');\n const href = anchor?.getAttribute('href');\n if (href?.startsWith('/')) {\n e.preventDefault();\n navigate(href);\n }\n }, [navigate]);\n\n const views: SlidePanelView[] = [\n {\n id: ESCALATION_PANEL_VIEWS.HELP,\n icon: HelpCircle,\n label: 'Instructions',\n content: <MarkdownRenderer content={helpMarkdown} onClick={handleHelpClick} />,\n },\n {\n id: ESCALATION_PANEL_VIEWS.DETAILS,\n icon: Info,\n label: 'Details',\n content: <DetailsList esc={esc} claimed={claimed} isTerminal={isTerminal} isBuilder={isBuilder} traceUrl={traceUrl} />,\n },\n ...(hasAI && triage\n ? [{\n id: ESCALATION_PANEL_VIEWS.TRIAGE,\n icon: Sparkles,\n label: 'AI Analysis',\n content: <TriageContext triage={triage} payload={payload ?? {}} />,\n }]\n : []),\n {\n id: ESCALATION_PANEL_VIEWS.METADATA,\n icon: Tags,\n label: 'Metadata',\n content: <MetadataList metadata={esc.metadata} role={esc.role} />,\n },\n {\n id: ESCALATION_PANEL_VIEWS.CONTEXT,\n icon: Layers,\n label: 'Context',\n content: (\n <div className=\"space-y-5\">\n {envelope != null && <JsonViewer data={envelope} label=\"Input Envelope\" />}\n {payload != null && <JsonViewer data={payload} label=\"Escalation Context\" />}\n {resolver != null && <JsonViewer data={resolver} label=\"Resolver Payload\" />}\n {envelope == null && payload == null && resolver == null && (\n <p className=\"text-xs text-text-tertiary italic\">No context on this escalation.</p>\n )}\n </div>\n ),\n },\n ...(isBuilder\n ? [{\n id: ESCALATION_PANEL_VIEWS.RECORD,\n icon: Braces,\n label: 'Record',\n content: <JsonViewer data={esc} label=\"Escalation Record\" />,\n }]\n : []),\n ...(formErrors && formErrors.length > 0\n ? [{\n id: ESCALATION_PANEL_VIEWS.ERRORS,\n icon: (({ className }: { className?: string }) => (\n <AlertCircle className={`${className ?? ''} text-status-error`} />\n )) as SlidePanelView['icon'],\n label: 'Errors',\n content: <ErrorsPanel errors={formErrors} schema={schema} />,\n }]\n : []),\n ];\n\n return (\n <SlidePanel open={open} width={384} className=\"h-full\">\n {/* The breathing room collapses with the panel — it lives inside the\n animated width, so the closed state reclaims all of it. The column\n is fixed height (like the left nav): the sparkline row persists at\n the top and the active view scrolls independently beneath it. */}\n <div className={`h-full${noGutter ? '' : ' pl-6'}`}>\n {/* One tinted column, top to bottom — the sparkline lives inside it,\n hovering tight (2px y padding) above the icon row, centered at 80%\n so its edge labels never clip. The slim row drops the icons onto\n the same visual line as the page-title icons beside them; only the\n view content below scrolls. */}\n <div className=\"h-full flex flex-col bg-surface-hover\">\n <div className=\"shrink-0 pt-2 pb-0 flex justify-center\">\n <EscalationTimeline esc={esc} className=\"w-[80%]\" />\n </div>\n <div className=\"flex-1 min-h-0\">\n {/* No close button — the page-header panel icon owns dismissal. */}\n <SlidePanelViews\n views={views}\n activeId={activeView}\n onViewChange={handleViewChange}\n stickyClassName=\"h-full min-h-0\"\n />\n </div>\n </div>\n </div>\n </SlidePanel>\n );\n}\n","/**\n * Context-path resolution shared by every token that names a `\"domain.path\"`.\n *\n * A path may embed `{{domain.path}}` interpolation segments — the same\n * grammar as x-lt-help tokens — resolved against the live context before the\n * walk. This is what makes cascading selects work: a field can declare\n *\n * x-lt-options: \"lookup.geo.regions.{{resolver.country}}\"\n *\n * and its option list follows the submitter's country answer, re-resolved\n * locally on every edit. An unresolved segment means \"no concrete path yet\",\n * never a literal placeholder.\n */\nimport { getDeep } from './x-lt-bind';\n\nexport const INTERPOLATION_PATTERN = /\\{\\{\\s*([^{}]+?)\\s*\\}\\}/g;\n\n/** Whether a token embeds `{{domain.path}}` interpolation segments. */\nexport function hasInterpolation(token: unknown): token is string {\n return typeof token === 'string' && /\\{\\{[^{}]+\\}\\}/.test(token);\n}\n\n/** Resolve a concrete `\"domain.path\"` (x-lt-bind syntax, `a.b[0].c`) against the context. */\nexport function resolveCtxPath(\n path: string,\n ctx: Record<string, unknown> | undefined,\n): unknown {\n if (!ctx) return undefined;\n const dot = path.indexOf('.');\n const root = ctx[dot === -1 ? path : path.slice(0, dot)];\n if (dot === -1) return root;\n if (root === null || typeof root !== 'object') return undefined;\n return getDeep(root, path.slice(dot + 1));\n}\n\n/**\n * Interpolate every `{{domain.path}}` segment against the context. Returns\n * the concrete path, or null when any segment resolves to nothing (missing,\n * null, empty string) or to a non-scalar — an unanswered cascade parent\n * yields no path, so the dependent field offers nothing.\n */\nexport function interpolatePath(\n template: string,\n ctx: Record<string, unknown> | undefined,\n): string | null {\n let unresolved = false;\n const concrete = template.replace(INTERPOLATION_PATTERN, (_match, rawPath: string) => {\n const value = resolveCtxPath(rawPath, ctx);\n if (typeof value === 'string' && value.trim().length > 0) return value;\n if (typeof value === 'number' && Number.isFinite(value)) return String(value);\n unresolved = true;\n return '';\n });\n return unresolved ? null : concrete;\n}\n","/**\n * x-lt-options — a select's option list resolved from the escalation context.\n * The field-level token names a `\"domain.path\"`; the value at that path is an\n * array whose entries are scalars (strings or numbers) or `{ value, label }`\n * objects (`{ id, label }` accepted as an alias), so one static role form can\n * offer a different legal set per escalation (e.g. `[1..N]` where N rides the\n * envelope, or a versioned knowledge lookup under the `lookup` domain).\n *\n * x-lt-options \"domain.path\" or an ORDERED array of paths — e.g.\n * \"envelope.left_quantity_options\" or\n * [\"lookup.reasons.items\", \"envelope.reject_reason_items\"].\n * With an array, the first entry that resolves to options\n * wins, so lookup-backed and envelope-embedded rows render\n * the same shared schema interchangeably (a parked row\n * falls through to the envelope it already carries).\n * Paths may embed {{domain.path}} interpolation segments —\n * e.g. \"lookup.geo.regions.{{resolver.country}}\" — making\n * the option list follow another answer (cascading selects);\n * an entry whose interpolation cannot resolve falls through\n * to the next entry.\n *\n * Object entries separate what the submitter SEES from what the payload\n * STORES: the select renders the label and emits the value (a DB-backed pick\n * list showing text while storing its foreign key). A scalar entry is both.\n *\n * A static `enum` takes precedence when both are present — the same\n * static-over-dynamic rule as x-lt-minimum/x-lt-maximum. Resolution is a\n * tri-state:\n *\n * undefined — no dynamic contract: a plain path that resolves to nothing\n * (the field renders as its plain input; membership unenforced)\n * [] — a dynamic (interpolated) contract offering nothing YET: the\n * select renders disabled and a present value fails membership\n * options — the option list\n *\n * Malformed entries in a resolved array are dropped.\n */\nimport { hasInterpolation, interpolatePath, resolveCtxPath } from './ctx-path';\n\nexport const X_LT_OPTIONS = 'x-lt-options';\n\nexport type OptionValue = string | number;\n\n/** One resolved option: the payload value and the rendered label. */\nexport interface ResolvedOption {\n value: OptionValue;\n label: string;\n}\n\nfunction isScalar(v: unknown): v is OptionValue {\n return typeof v === 'string' || (typeof v === 'number' && Number.isFinite(v));\n}\n\n/** Normalize one array entry, mixed arrays resolving each entry independently. */\nfunction toOption(entry: unknown): ResolvedOption | null {\n if (isScalar(entry)) return { value: entry, label: String(entry) };\n if (entry && typeof entry === 'object' && !Array.isArray(entry)) {\n const o = entry as Record<string, unknown>;\n const value = o.value !== undefined ? o.value : o.id;\n if (isScalar(value) && typeof o.label === 'string' && o.label.length > 0) {\n return { value, label: o.label };\n }\n }\n return null;\n}\n\n/**\n * The field's effective option list: the static `enum` when present, else the\n * entries at the token's `\"domain.path\"`.\n */\nexport function resolveFieldOptions(\n fieldSchema: Record<string, unknown> | null | undefined,\n ctx: Record<string, unknown> | undefined,\n): ResolvedOption[] | undefined {\n if (!fieldSchema) return undefined;\n\n // Enum entries pass through verbatim as values (whatever their type), each\n // labeled by its string form — the legacy membership contract is unchanged.\n const staticEnum = fieldSchema.enum;\n if (Array.isArray(staticEnum) && staticEnum.length > 0) {\n return staticEnum.map((v) => ({ value: v as OptionValue, label: String(v) }));\n }\n\n const token = fieldSchema[X_LT_OPTIONS];\n const paths = (typeof token === 'string' ? [token] : Array.isArray(token) ? token : [])\n .filter((p): p is string => typeof p === 'string' && p.length > 0);\n if (paths.length === 0) return undefined;\n\n // Interpolated entries are a standing contract: when nothing resolves, the\n // field stays a (disabled) select and fails closed — a cascade child never\n // becomes free text. All-plain-path tokens keep the legacy undefined-on-miss\n // reading (the field falls back to its typed plain input).\n const miss = paths.some(hasInterpolation) ? ([] as ResolvedOption[]) : undefined;\n\n for (const sourcePath of paths) {\n let concrete = sourcePath;\n if (hasInterpolation(sourcePath)) {\n const resolved = interpolatePath(sourcePath, ctx);\n if (resolved === null) continue;\n concrete = resolved;\n }\n const cur = resolveCtxPath(concrete, ctx);\n if (!Array.isArray(cur)) continue;\n const options = cur.map(toOption).filter((o): o is ResolvedOption => o !== null);\n if (options.length > 0) return options;\n }\n return miss;\n}\n","import { resolveFieldOptions } from './x-lt-options';\nimport { hasInterpolation, interpolatePath, resolveCtxPath } from './ctx-path';\n\nexport interface FieldError { field: string; message: string }\n\ninterface ChecklistItem { id: string; label: string; required?: boolean }\n\n/**\n * Resolve a checklist widget's item definitions from its `x-lt-source` —\n * a \"domain.path\" or an ORDERED array of paths — against the escalation\n * context. With an array, the first entry that resolves to a non-empty item\n * list wins, so lookup-backed and envelope-embedded rows render the same\n * shared schema interchangeably. Paths may embed `{{domain.path}}`\n * interpolation segments (cascading sources); an entry that cannot resolve\n * falls through to the next. Nothing resolvable yields an empty list.\n */\nexport function resolveChecklistItems(\n source: unknown,\n ctx: Record<string, unknown> | undefined,\n): ChecklistItem[] {\n const paths = (typeof source === 'string' ? [source] : Array.isArray(source) ? source : [])\n .filter((p): p is string => typeof p === 'string' && p.length > 0);\n if (paths.length === 0 || !ctx) return [];\n for (const sourcePath of paths) {\n let concrete = sourcePath;\n if (hasInterpolation(sourcePath)) {\n const resolved = interpolatePath(sourcePath, ctx);\n if (resolved === null) continue;\n concrete = resolved;\n }\n const cur = resolveCtxPath(concrete, ctx);\n if (Array.isArray(cur) && cur.length > 0) return cur as ChecklistItem[];\n }\n return [];\n}\n\nexport const X_LT_DEFAULT_CHECKED = 'x-lt-default-checked';\n\n/**\n * The checklist's first-load default (`x-lt-default-checked`): every resolved\n * item starts checked, for affirm-then-exception flows where the submitter\n * unchecks what failed. Returns the all-checked answer map ONLY when the\n * field carries no answer yet — a saved or drafted map (any key, even\n * all-false) is never clobbered — and null otherwise: absent flag, existing\n * answer, or a source that resolves to no items. Declared on the widget\n * because the item set is runtime-sourced (envelope or lookup): a pure\n * escalation-minting step cannot enumerate the ids to seed formDefaults.\n */\nexport function resolveChecklistDefault(\n fieldSchema: Record<string, unknown> | null | undefined,\n currentValue: unknown,\n ctx?: Record<string, unknown>,\n): Record<string, boolean> | null {\n if (fieldSchema?.['x-lt-widget'] !== 'checklist') return null;\n if (fieldSchema[X_LT_DEFAULT_CHECKED] !== true) return null;\n if (\n currentValue && typeof currentValue === 'object' && !Array.isArray(currentValue)\n && Object.keys(currentValue).length > 0\n ) {\n return null;\n }\n const items = resolveChecklistItems(fieldSchema['x-lt-source'], ctx);\n if (items.length === 0) return null;\n return Object.fromEntries(items.map((i) => [i.id, true]));\n}\n\n/**\n * The checklist completion guard (`x-lt-require-all`): every rendered item must\n * be checked, except items whose definition carries `required: false` (the\n * explicit opt-out). Vacuous when the source resolves to no items — never\n * blocks on zero. Returns the panel message, or undefined when satisfied.\n * Stricter than (and composes with) the field-level required-array entry,\n * which remains the at-least-one check.\n */\nexport function validateRequireAll(\n value: unknown,\n fieldSchema: Record<string, unknown> | undefined,\n ctx?: Record<string, unknown>,\n): string | undefined {\n if (fieldSchema?.['x-lt-widget'] !== 'checklist') return undefined;\n if (fieldSchema['x-lt-require-all'] !== true) return undefined;\n\n const items = resolveChecklistItems(fieldSchema['x-lt-source'], ctx);\n const mandatory = items.filter((i) => i.required !== false);\n if (mandatory.length === 0) return undefined;\n\n const state = (typeof value === 'object' && value !== null && !Array.isArray(value))\n ? (value as Record<string, unknown>)\n : {};\n const incomplete = mandatory.filter((i) => !state[i.id]).length;\n if (incomplete === 0) return undefined;\n return `${incomplete} of ${mandatory.length} checks incomplete`;\n}\n\n/**\n * Runtime type check against the field's declared JSON Schema `type`. Guards\n * the payload contract for API-first callers (a form widget already produces\n * the right primitive; a script or agent submitting `\"1\"` for a number field\n * does not). Absent/empty values pass — presence is the required check's job.\n */\nexport function validateFieldType(\n value: unknown,\n fieldSchema: Record<string, unknown> | undefined,\n): string | undefined {\n const declared = fieldSchema?.type;\n if (typeof declared !== 'string') return undefined;\n if (value === undefined || value === null || value === '') return undefined;\n switch (declared) {\n case 'string':\n return typeof value === 'string' ? undefined : 'Expected text';\n case 'number':\n return typeof value === 'number' && Number.isFinite(value) ? undefined : 'Expected a number';\n case 'integer':\n return typeof value === 'number' && Number.isInteger(value) ? undefined : 'Expected a whole number';\n case 'boolean':\n return typeof value === 'boolean' ? undefined : 'Expected true or false';\n case 'array':\n return Array.isArray(value) ? undefined : 'Expected a list';\n case 'object':\n return typeof value === 'object' && !Array.isArray(value) ? undefined : 'Expected an object';\n default:\n return undefined;\n }\n}\n\n/**\n * Per-field JSON Schema validation — subset used by the resolver form.\n *\n * Returns a human-readable error string when the value fails a constraint,\n * or undefined when the value is valid. Callers are responsible for the\n * required check (empty-when-required) before calling this for constraint checks.\n *\n * `ctx` is optional context (ShowIfContext-shaped) used to resolve dynamic\n * constraint paths like `x-lt-minimum: \"envelope.min_score\"`.\n */\nexport function validateFieldConstraints(\n value: unknown,\n fieldSchema: Record<string, unknown> | undefined,\n ctx?: Record<string, unknown>,\n): string | undefined {\n if (!fieldSchema) return undefined;\n\n // Option membership — the form's select widget constrains choices; API-first\n // callers are unconstrained, so the effective option list is the contract:\n // the static enum, or the x-lt-options list resolved from context. The\n // submitted answer is the option VALUE (labels are presentation). An\n // interpolated list that currently offers nothing fails closed — a stale\n // cascade child value never submits.\n const allowed = resolveFieldOptions(fieldSchema, ctx);\n if (allowed !== undefined && value !== undefined && value !== null && value !== '') {\n if (allowed.length === 0) {\n return 'No valid options for this selection';\n }\n if (!allowed.some((o) => o.value === value)) {\n return `Must be one of: ${allowed.map((o) => String(o.value)).join(', ')}`;\n }\n }\n\n if (typeof value === 'string') {\n const s = value.trim();\n if (s === '') return undefined; // empty string: required check is the caller's job\n\n const minLength = resolveNumericConstraint(fieldSchema.minLength, fieldSchema['x-lt-min-length'], ctx);\n if (minLength !== undefined && s.length < minLength) {\n return `Minimum ${minLength} character${minLength === 1 ? '' : 's'}`;\n }\n\n const maxLength = resolveNumericConstraint(fieldSchema.maxLength, fieldSchema['x-lt-max-length'], ctx);\n if (maxLength !== undefined && s.length > maxLength) {\n return `Maximum ${maxLength} characters (${s.length} entered)`;\n }\n\n const pattern = fieldSchema.pattern as string | undefined;\n if (pattern) {\n try {\n if (!new RegExp(pattern).test(s)) {\n const patternError = fieldSchema['x-lt-pattern-error'] as string | undefined;\n return patternError ?? 'Invalid format';\n }\n } catch {\n // Malformed pattern in schema — silently skip\n }\n }\n\n const fmt = fieldSchema.format as string | undefined;\n if (fmt === 'email' && !/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(s)) {\n return 'Enter a valid email address';\n }\n if (fmt === 'uri' && !/^https?:\\/\\/.+/.test(s)) {\n return 'Enter a valid URL';\n }\n }\n\n if (typeof value === 'number') {\n const minimum = resolveNumericConstraint(fieldSchema.minimum, fieldSchema['x-lt-minimum'], ctx);\n const exclusiveMinimum = resolveNumericConstraint(fieldSchema.exclusiveMinimum, undefined, ctx);\n const maximum = resolveNumericConstraint(fieldSchema.maximum, fieldSchema['x-lt-maximum'], ctx);\n const exclusiveMaximum = resolveNumericConstraint(fieldSchema.exclusiveMaximum, undefined, ctx);\n\n if (minimum !== undefined && value < minimum) {\n return `Minimum value is ${minimum}`;\n }\n if (exclusiveMinimum !== undefined && value <= exclusiveMinimum) {\n return `Must be greater than ${exclusiveMinimum}`;\n }\n if (maximum !== undefined && value > maximum) {\n return `Maximum value is ${maximum}`;\n }\n if (exclusiveMaximum !== undefined && value >= exclusiveMaximum) {\n return `Must be less than ${exclusiveMaximum}`;\n }\n }\n\n return undefined;\n}\n\nfunction resolveNumericConstraint(\n staticVal: unknown,\n dynamicPath: unknown,\n ctx: Record<string, unknown> | undefined,\n): number | undefined {\n if (typeof staticVal === 'number') return staticVal;\n if (typeof dynamicPath === 'string' && ctx) {\n const dot = dynamicPath.indexOf('.');\n if (dot !== -1) {\n const domain = dynamicPath.slice(0, dot);\n const path = dynamicPath.slice(dot + 1);\n const domainObj = ctx[domain];\n if (domainObj && typeof domainObj === 'object') {\n const parts = path.split('.');\n let cur: unknown = domainObj;\n for (const p of parts) {\n cur = (cur as Record<string, unknown>)[p];\n if (cur === undefined) break;\n }\n if (typeof cur === 'number') return cur;\n if (typeof cur === 'string') {\n const n = Number(cur);\n if (!Number.isNaN(n)) return n;\n }\n }\n }\n }\n return undefined;\n}\n\n/** Full field error including required check then constraints. */\nexport function validateField(\n value: unknown,\n fieldSchema: Record<string, unknown> | undefined,\n isRequired: boolean,\n isTouched: boolean,\n ctx?: Record<string, unknown>,\n): string | undefined {\n if (!isTouched) return undefined;\n\n if (isRequired) {\n if (value === undefined || value === null) return 'Required';\n if (typeof value === 'boolean' && !value) return 'Required';\n if (typeof value === 'string' && value.trim() === '') return 'Required';\n if (typeof value === 'object' && !Array.isArray(value) && value !== null) {\n const vals = Object.values(value as Record<string, unknown>);\n if (vals.length === 0 || vals.every((v) => !v)) return 'Required';\n }\n }\n\n // Declared-type check runs before constraints: a mis-typed value would make\n // the numeric/string constraint branches silently inapplicable.\n const typeError = validateFieldType(value, fieldSchema);\n if (typeError) return typeError;\n\n // Checklist completion — the stricter guard runs regardless of the\n // required-array entry (which stays at-least-one when present).\n const requireAll = validateRequireAll(value, fieldSchema, ctx);\n if (requireAll) return requireAll;\n\n return validateFieldConstraints(value, fieldSchema, ctx);\n}\n","/**\n * x-lt-showIf — conditional field visibility. A form_schema property may\n * declare `x-lt-showIf: \"domain.path\"` to show the field only when the value\n * at that path is present and truthy. Prefix `!` to invert: show when absent\n * or falsy.\n *\n * Equality forms compare the resolved value's string form:\n * \"domain.path=VALUE\" — show when String(value) equals VALUE\n * \"domain.path!=VALUE\" — show when it does not\n * An absent value compares as the empty string, so `=X` is false and `!=X` is\n * true when the path is missing. VALUE is the raw remainder after the operator\n * (trimmed; no quoting). The truthy/! forms are unchanged.\n *\n * Domains follow the same `domain.path` convention as x-lt-help tokens:\n * metadata — the escalation row's metadata dict\n * payload — the escalation context payload (escalation_payload)\n * envelope — the workflow-sent input envelope\n * escalation — top-level escalation row fields\n * resolver — the submitted resolver payload\n *\n * A missing or non-string condition always shows the field (opt-in, safe default).\n */\nimport { getDeep } from './x-lt-bind';\nimport { HELP_DOMAINS, type HelpTokenContext } from './x-lt-help';\n\nexport type ShowIfContext = HelpTokenContext;\n\nfunction isTruthy(value: unknown): boolean {\n return value !== null && value !== undefined && value !== '' && value !== false && value !== 0;\n}\n\n/** The value's comparable string form; absent compares as the empty string. */\nfunction asComparable(value: unknown): string {\n if (value === null || value === undefined) return '';\n if (typeof value === 'object') return JSON.stringify(value);\n return String(value);\n}\n\nfunction resolvePath(expr: string, ctx: ShowIfContext): { known: boolean; value: unknown } {\n const dot = expr.indexOf('.');\n const domain = (dot === -1 ? expr : expr.slice(0, dot)) as (typeof HELP_DOMAINS)[number];\n if (!(HELP_DOMAINS as readonly string[]).includes(domain)) return { known: false, value: undefined };\n const root = ctx[domain];\n if (dot === -1) return { known: true, value: root };\n try {\n return { known: true, value: getDeep(root, expr.slice(dot + 1)) };\n } catch {\n return { known: true, value: undefined };\n }\n}\n\n/**\n * Evaluates an x-lt-showIf condition. Returns true when the field should be\n * shown. Returns true when condition is absent, non-string, or context is null.\n */\nexport function evaluateShowIf(condition: unknown, ctx: ShowIfContext | null | undefined): boolean {\n if (typeof condition !== 'string' || condition.length === 0) return true;\n if (!ctx) return true;\n const negate = condition.startsWith('!');\n const expr = negate ? condition.slice(1) : condition;\n\n // Equality forms — `!=` first so it never parses as `=` with a `!` in the path.\n const neqAt = expr.indexOf('!=');\n const eqAt = expr.indexOf('=');\n if (neqAt !== -1 || (eqAt !== -1 && eqAt !== neqAt + 1)) {\n const isNeq = neqAt !== -1 && (eqAt === -1 || neqAt < eqAt);\n const opAt = isNeq ? neqAt : eqAt;\n const path = expr.slice(0, opAt).trim();\n const expected = expr.slice(opAt + (isNeq ? 2 : 1)).trim();\n const { known, value } = resolvePath(path, ctx);\n if (!known) return true; // unknown domain — safe default, same as truthy form\n const matches = asComparable(value) === expected;\n const result = isNeq ? !matches : matches;\n return negate ? !result : result;\n }\n\n const { known, value } = resolvePath(expr, ctx);\n if (!known) return true;\n return negate ? !isTruthy(value) : isTruthy(value);\n}\n","/**\n * x-lt-require-any — \"at least one of this set\" as a root-schema token. A\n * form_schema declares groups of field names; a submission passes when every\n * group has a value in at least one member. The canonical case: a Left\n * quantity and a Right quantity where either satisfies, but blank-both fails.\n *\n * x-lt-require-any string[][] — e.g. [[\"left_quantity\", \"right_quantity\"]]\n *\n * Visibility rules compose: a member hidden by its `x-lt-showIf` (or naming\n * no schema property) can neither satisfy the group nor be demanded of the\n * submitter, and a group whose members are ALL hidden is waived. `false` and\n * `0` are answers; `''`, null, and undefined are not.\n */\n\nexport const X_LT_REQUIRE_ANY = 'x-lt-require-any';\n\n/**\n * The schema's require-any groups. Malformed declarations (non-array token,\n * non-array groups, non-string members) read as no groups — a bad token never\n * bricks submission.\n */\nexport function readRequireAnyGroups(\n schema: Record<string, unknown> | null | undefined,\n): string[][] {\n const raw = schema?.[X_LT_REQUIRE_ANY];\n if (!Array.isArray(raw)) return [];\n return raw\n .filter((group): group is unknown[] => Array.isArray(group))\n .map((group) => group.filter((m): m is string => typeof m === 'string' && m.length > 0))\n .filter((group) => group.length > 0);\n}\n\n/** Present = an actual answer: `false` and `0` count; `''`/null/undefined do not. */\nexport function hasRequireAnyValue(value: unknown): boolean {\n if (value === undefined || value === null) return false;\n if (typeof value === 'string') return value.trim().length > 0;\n return true;\n}\n","/**\n * x-lt-require-sum — \"these quantities must total at least N\" as a\n * root-schema token. Where x-lt-require-any asks that one member carry any\n * answer (so a count defaulting to `0` vacuously satisfies it), require-sum\n * reads the members as numbers and demands their sum reach a minimum. The\n * canonical case: a Left quantity and a Right quantity that both default to\n * `0`, where at least one side must be positive.\n *\n * x-lt-require-sum { fields: string[], minimum?: number }[]\n * — e.g. [{ \"fields\": [\"left_quantity\", \"right_quantity\"] }]\n *\n * `minimum` defaults to 1. Numbers contribute their value and numeric strings\n * coerce (the same reading as dynamic bounds); everything else contributes 0.\n * Visibility rules compose the same way as require-any: a member hidden by\n * its `x-lt-showIf` (or naming no schema property) contributes nothing and is\n * not demanded, and a group whose members are ALL hidden is waived.\n */\n\nexport const X_LT_REQUIRE_SUM = 'x-lt-require-sum';\n\nexport interface RequireSumGroup {\n fields: string[];\n minimum: number;\n}\n\n/**\n * The schema's require-sum groups. Malformed declarations (non-array token,\n * groups without a fields array, non-string members, non-numeric minimum)\n * read as no groups — a bad token never bricks submission.\n */\nexport function readRequireSumGroups(\n schema: Record<string, unknown> | null | undefined,\n): RequireSumGroup[] {\n const raw = schema?.[X_LT_REQUIRE_SUM];\n if (!Array.isArray(raw)) return [];\n const groups: RequireSumGroup[] = [];\n for (const entry of raw) {\n if (!entry || typeof entry !== 'object' || Array.isArray(entry)) continue;\n const { fields, minimum } = entry as Record<string, unknown>;\n if (!Array.isArray(fields)) continue;\n const members = fields.filter((m): m is string => typeof m === 'string' && m.length > 0);\n if (members.length === 0) continue;\n if (minimum !== undefined && typeof minimum !== 'number') continue;\n groups.push({ fields: members, minimum: typeof minimum === 'number' ? minimum : 1 });\n }\n return groups;\n}\n\n/** A member's numeric contribution: numbers as-is, numeric strings coerced, all else 0. */\nexport function requireSumContribution(value: unknown): number {\n if (typeof value === 'number' && Number.isFinite(value)) return value;\n if (typeof value === 'string' && value.trim() !== '') {\n const n = Number(value);\n if (!Number.isNaN(n)) return n;\n }\n return 0;\n}\n","/**\n * The full pre-submission validation pass over a resolver form schema — the\n * same pass on both sides of the wire. The dashboard runs it on the flat form\n * values before submitting; the API layer runs it on the submitted (bound,\n * nested) payload by inverting x-lt-bind first. Because both entry points\n * funnel into one loop, a payload that passes the client panel passes the\n * server gate, and a 422's violation list is exactly what the panel shows.\n *\n * Semantics per field:\n * - x-lt-showIf-hidden fields are skipped entirely (a field the submitter\n * cannot see never blocks submission)\n * - required (schema.required membership), with checklist/empty-object rules\n * - declared-type check (string/number/integer/boolean/array/object)\n * - enum membership\n * - x-lt-require-all against the checklist items resolved from context\n * - static + dynamic bounds (minimum/x-lt-minimum, lengths, patterns)\n *\n * Root-level x-lt-require-any groups run after the per-field pass: each group\n * needs a value in at least one visible member (all-hidden groups are waived).\n * x-lt-require-sum groups follow the same visibility rules but read members\n * as numbers: the group's visible members must sum to at least its minimum.\n *\n * The showIf/`resolver.*` domain is always the FLAT form representation, so a\n * condition like `resolver.approved` reads the same on both sides.\n */\nimport { type FieldError, validateField } from './field-validator';\nimport { evaluateShowIf, type ShowIfContext } from './x-lt-show-if';\nimport { mapPayloadToForm } from './x-lt-bind';\nimport { readRequireAnyGroups, hasRequireAnyValue } from './x-lt-require-any';\nimport { readRequireSumGroups, requireSumContribution } from './x-lt-require-sum';\n\nexport type { FieldError } from './field-validator';\n\n/**\n * The escalation-surface context the pass evaluates showIf conditions and\n * dynamic constraints against. `resolver` is supplied by the pass itself\n * (the flat form values under validation) — callers provide the rest.\n */\nexport type ResolverValidationContext = Omit<ShowIfContext, 'resolver'>;\n\n/**\n * Validate FLAT form values against the form schema. This is the dashboard's\n * entry point (the values the user edits, keyed by field name).\n */\nexport function validateResolverForm(\n schema: Record<string, unknown> | null | undefined,\n formValues: Record<string, unknown>,\n ctx?: ResolverValidationContext | null,\n): FieldError[] {\n if (!schema) return [];\n const properties = (schema.properties ?? {}) as Record<string, Record<string, unknown>>;\n const required = new Set((schema.required as string[] | undefined) ?? []);\n const liveCtx: ShowIfContext = {\n ...(ctx ?? {}),\n resolver: formValues as Record<string, unknown>,\n };\n\n const errors: FieldError[] = [];\n for (const [field, fieldSchema] of Object.entries(properties)) {\n if (!evaluateShowIf(fieldSchema['x-lt-showIf'], liveCtx)) continue;\n const err = validateField(\n formValues[field],\n fieldSchema,\n required.has(field),\n true,\n liveCtx as Record<string, unknown>,\n );\n if (err) errors.push({ field, message: err });\n }\n\n // Require-any groups: at least one VISIBLE member per group carries a value.\n // A member hidden by showIf (or naming no property) can neither satisfy nor\n // be demanded; an all-hidden group is waived.\n for (const group of readRequireAnyGroups(schema)) {\n const visible = group.filter(\n (k) => properties[k] && evaluateShowIf(properties[k]['x-lt-showIf'], liveCtx),\n );\n if (visible.length === 0) continue;\n if (visible.some((k) => hasRequireAnyValue(formValues[k]))) continue;\n const titles = visible.map((k) => (properties[k].title as string | undefined) ?? k);\n errors.push({\n field: visible[0],\n message: `Enter a value for at least one of: ${titles.join(', ')}`,\n });\n }\n\n // Require-sum groups: the numeric values of VISIBLE members must total at\n // least the group's minimum. A `0` is a real number here — unlike\n // require-any, defaulted-zero quantities do not satisfy the group.\n for (const group of readRequireSumGroups(schema)) {\n const visible = group.fields.filter(\n (k) => properties[k] && evaluateShowIf(properties[k]['x-lt-showIf'], liveCtx),\n );\n if (visible.length === 0) continue;\n const total = visible.reduce((sum, k) => sum + requireSumContribution(formValues[k]), 0);\n if (total >= group.minimum) continue;\n const titles = visible.map((k) => (properties[k].title as string | undefined) ?? k);\n errors.push({\n field: visible[0],\n message: `Combined value of ${titles.join(', ')} must be at least ${group.minimum}`,\n });\n }\n return errors;\n}\n\n/**\n * Validate a SUBMITTED resolver payload (the bound, nested shape the workflow\n * consumes) against the form schema. This is the API layer's entry point: the\n * payload is inverted through each field's x-lt-bind path back to the flat\n * form representation, then run through the same pass the client uses.\n */\nexport function validateResolverPayload(\n schema: Record<string, unknown> | null | undefined,\n payload: Record<string, unknown>,\n ctx?: ResolverValidationContext | null,\n): FieldError[] {\n if (!schema) return [];\n const formValues = mapPayloadToForm(payload, schema as Record<string, any>);\n return validateResolverForm(schema, formValues, ctx);\n}\n","import { mapFormToPayload } from './x-lt-bind';\nimport { validateResolverForm, type FieldError } from './field-validator';\nimport type { ShowIfContext } from './x-lt-show-if';\n\nexport interface ResolverPayloadResult {\n /** The resolver payload ready to submit — null when the JSON is unparseable or validation failed. */\n payload: Record<string, unknown> | null;\n /** Field errors against the embedded _form_schema (empty when the form is valid). */\n errors: FieldError[];\n /** Set when the edited JSON string itself is malformed. */\n parseError: string | null;\n}\n\n/**\n * Build the resolver payload from the form's edited JSON string.\n *\n * 1. Parse the JSON — a malformed string yields `parseError`.\n * 2. Validate every visible field against the embedded `_form_schema` — hidden\n * fields (x-lt-showIf falsy against the live context) are skipped, matching\n * the server's enforcement pass. Any failures yield `errors`.\n * 3. Strip the UI-only schema and map flat form fields into their nested shape\n * via x-lt-bind — the payload IS the payload.\n *\n * The single path shared by the footer's Submit button and the submit-on-claim\n * shortcut, so both produce identical payloads and identical error lists.\n */\nexport function buildResolverPayload(\n json: string,\n context?: ShowIfContext,\n): ResolverPayloadResult {\n let parsed: Record<string, unknown>;\n try {\n parsed = JSON.parse(json) as Record<string, unknown>;\n } catch {\n return { payload: null, errors: [], parseError: 'Invalid JSON' };\n }\n\n const schema = parsed._form_schema as Record<string, unknown> | undefined;\n if (schema) {\n const errors = validateResolverForm(schema, parsed, context);\n if (errors.length > 0) return { payload: null, errors, parseError: null };\n }\n\n const { _form_schema, ...formValues } = parsed;\n return {\n payload: mapFormToPayload(formValues, schema as Record<string, any> | undefined),\n errors: [],\n parseError: null,\n };\n}\n","import { useState, useCallback } from 'react';\nimport { buildResolverPayload } from '../../../lib/resolver-payload';\nimport { CountdownTimer } from '../../../components/common/display/CountdownTimer';\nimport { UserName } from '../../../components/common/display/UserName';\nimport { CustomDurationPicker } from '../../../components/common/form/CustomDurationPicker';\nimport { useClaimDurations } from '../../../hooks/useClaimDurations';\nimport type { EscalationActionBarProps } from './action-bar-types';\n\nexport type { ActionBarMode, ActiveView, EscalationActionBarProps } from './action-bar-types';\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\nexport function EscalationActionBar(props: EscalationActionBarProps) {\n const {\n mode, activeView, onActiveViewChange,\n onClaim, claimPending, claimNudge,\n workflowType, json, onResolve, resolvePending, resolveError,\n requestTriage, triageNotes,\n onRelease, releasePending,\n onCancel,\n assignedTo, assignedUntil,\n onSubmitAttempt,\n onValidationErrors,\n escalationContext,\n labels = {},\n submitBlocked,\n submitBlockedMessage,\n actingName,\n badgePrompt,\n canManage,\n onReassign,\n onUnassign,\n unassignPending,\n } = props;\n\n const claimDurations = useClaimDurations();\n const [duration, setDuration] = useState('30');\n const [customMinutes, setCustomMinutes] = useState(0);\n const [parseError, setParseError] = useState('');\n\n const isCustom = duration === 'custom';\n const onCustomChange = useCallback((m: number) => setCustomMinutes(m), []);\n\n // x-lt-submit-guard is owned by the page (it drives auto-resolve too); the bar\n // just reflects its block state. The gate applies to the form resolve only —\n // triage stays the escape hatch when the guarded work itself is the problem.\n const guardBlocksSubmit = !!submitBlocked && !requestTriage;\n\n if (mode === 'terminal') return null;\n\n const handleClaim = () => {\n const minutes = isCustom ? customMinutes : parseInt(duration);\n if (!minutes || minutes <= 0) return;\n onClaim(minutes);\n };\n\n const handleSubmitResolve = () => {\n setParseError('');\n\n // When triage is requested, ignore the form payload entirely.\n // Only the triage flag and notes matter — the form data (e.g.\n // approved: true) must NOT leak through, as it would confuse\n // the triage workflow into thinking the issue is already resolved.\n if (requestTriage) {\n const payload: Record<string, unknown> = {\n _lt: { needsTriage: true },\n };\n if (triageNotes.trim()) payload.notes = triageNotes.trim();\n onResolve(payload);\n return;\n }\n\n // Parse, validate against the embedded _form_schema, and map to the final\n // nested shape — the same pass the API layer runs on enforced roles, so the\n // panel and a server 422 report the identical list. Hidden fields (x-lt-showIf\n // falsy against the live context) are excluded from the required checks.\n const result = buildResolverPayload(json, escalationContext);\n if (result.parseError) {\n setParseError(result.parseError);\n return;\n }\n if (result.errors.length > 0) {\n // Field errors live in ONE surface: the errors panel, which opens on the\n // blocked submit and recomputes as the user fixes fields. A summary here\n // would go stale the moment a field is corrected — the footer keeps only\n // its own errors (bad JSON, server rejection).\n onSubmitAttempt?.();\n onValidationErrors?.(result.errors);\n return;\n }\n onResolve(result.payload!);\n };\n\n const tabClass = (active: boolean) =>\n `text-xs transition-colors ${active ? 'text-accent font-medium' : 'text-text-tertiary hover:text-accent'}`;\n\n return (\n // Flex-pinned at the bottom of the form column: full-bleed left into the\n // page gutter, ending at the side panel's edge on the right.\n <div className=\"shrink-0 h-[80px] bg-surface/95 backdrop-blur-sm border-t border-surface-border -ml-10 pl-10 pr-10 pt-3 pb-5\" data-testid=\"escalation-action-bar\">\n\n {/* ── Available: claim ── */}\n {mode === 'available' && (\n <div data-testid=\"claim-bar\">\n {/* Duration tab row */}\n <div className=\"flex items-center gap-4 mb-2\">\n {claimDurations.map((opt) => (\n <button\n key={opt.value}\n onClick={() => { setDuration(opt.value); setCustomMinutes(0); }}\n className={tabClass(!isCustom && duration === opt.value)}\n >\n {opt.label}\n </button>\n ))}\n <button\n onClick={() => setDuration('custom')}\n className={tabClass(isCustom)}\n >\n Other\n </button>\n </div>\n {/* Action row — right-aligned */}\n <div className=\"flex items-center gap-3\">\n {labels.cancel !== false && (\n <button\n onClick={onCancel}\n className=\"text-xs text-text-tertiary hover:text-status-error transition-colors\"\n >\n {labels.cancel ?? 'Cancel escalation'}\n </button>\n )}\n <div className=\"flex-1\" />\n {isCustom && (\n <CustomDurationPicker onChange={onCustomChange} compact autoFocus />\n )}\n <button\n // Keyed by the nudge count: each locked-form click remounts\n // the button, restarting the wiggle from the top.\n key={claimNudge}\n onClick={handleClaim}\n disabled={claimPending || (isCustom && customMinutes <= 0)}\n className={`btn-primary text-xs ${claimNudge ? 'animate-[field-shake_0.4s_ease-in-out]' : ''}`}\n data-testid=\"claim-button\"\n >\n {claimPending ? 'Claiming...' : (labels.claim ?? 'Claim')}\n </button>\n </div>\n </div>\n )}\n\n {/* ── Claimed by other ── */}\n {mode === 'claimed_by_other' && (\n <div className=\"flex items-center gap-4\" data-testid=\"claimed-other-bar\">\n <p className=\"text-sm text-text-secondary\">\n Claimed by <span className=\"font-medium text-text-primary\">{assignedTo ? <UserName userId={assignedTo} /> : 'unknown'}</span>\n </p>\n {assignedUntil && <CountdownTimer until={assignedUntil} />}\n {/* An expired badge grant on submit lands here: the acting state\n cleared, the server's answer surfaces, and a fresh scan retries. */}\n {resolveError && <span className=\"text-xs text-status-error\">{resolveError.message}</span>}\n {badgePrompt && (\n <p className=\"text-xs text-text-tertiary\" data-testid=\"badge-prompt\">\n If this is your claim, scan your badge.\n </p>\n )}\n {canManage && (\n <>\n <div className=\"flex-1\" />\n <button\n onClick={onReassign}\n className=\"text-xs text-text-tertiary hover:text-accent transition-colors\"\n data-testid=\"admin-reassign\"\n >\n Reassign…\n </button>\n <button\n onClick={onUnassign}\n disabled={unassignPending}\n className=\"text-xs text-text-tertiary hover:text-status-error transition-colors disabled:opacity-50\"\n data-testid=\"admin-unassign\"\n >\n {unassignPending ? 'Returning…' : 'Return to queue'}\n </button>\n </>\n )}\n </div>\n )}\n\n {/* ── Claimed by me ── */}\n {mode === 'claimed_by_me' && (\n <div data-testid=\"action-bar\">\n {/* Tab row */}\n <div className=\"flex items-center gap-4 mb-2\">\n <button\n onClick={() => onActiveViewChange('resolve')}\n className={tabClass(activeView === 'resolve')}\n >\n {workflowType ? 'Resolve' : 'Acknowledge'}\n </button>\n <button\n onClick={() => onActiveViewChange('release')}\n className={`text-xs transition-colors ${activeView === 'release' ? 'text-status-error font-medium' : 'text-text-tertiary hover:text-status-error'}`}\n >\n {labels.release ?? 'Release'}\n </button>\n {labels.cancel !== false && (\n <button\n onClick={onCancel}\n className=\"text-xs transition-colors text-text-tertiary hover:text-status-error\"\n >\n {labels.cancel ?? 'Cancel'}\n </button>\n )}\n </div>\n\n {/* ── Resolve controls ── */}\n {activeView === 'resolve' && (\n <div className=\"flex items-center gap-4\">\n {/* The badged person's claim: name the identity the submit acts as. */}\n {actingName && (\n <p className=\"text-sm text-text-secondary\" data-testid=\"acting-claim-note\">\n Claimed by you <span className=\"font-medium text-text-primary\">({actingName})</span>\n </p>\n )}\n {actingName && assignedUntil && <CountdownTimer until={assignedUntil} />}\n <div className=\"flex-1\" />\n {parseError && <span className=\"text-xs text-status-error\">{parseError}</span>}\n {resolveError && <span className=\"text-xs text-status-error\">{resolveError.message}</span>}\n {guardBlocksSubmit && submitBlockedMessage && (\n <span className=\"text-xs text-status-pending\" data-testid=\"submit-guard-message\">\n {submitBlockedMessage}\n </span>\n )}\n <button\n onClick={handleSubmitResolve}\n disabled={resolvePending || guardBlocksSubmit}\n className=\"btn-primary text-xs\"\n >\n {resolvePending\n ? (workflowType ? 'Submitting...' : 'Acknowledging...')\n : requestTriage ? 'Send to Triage'\n : (labels.submit ?? (workflowType ? 'Submit' : 'Acknowledge'))}\n </button>\n </div>\n )}\n\n {/* ── Release controls ── */}\n {activeView === 'release' && (\n <div className=\"flex items-center gap-3\">\n <span className=\"text-xs text-text-secondary\">Release back to pool?</span>\n <div className=\"flex-1\" />\n <button onClick={() => onActiveViewChange('resolve')} className=\"btn-secondary text-xs\">\n Back\n </button>\n <button\n onClick={onRelease}\n disabled={releasePending}\n className=\"btn-primary text-xs bg-status-error hover:bg-status-error/80\"\n >\n {releasePending ? 'Releasing...' : 'Yes, Release'}\n </button>\n </div>\n )}\n\n </div>\n )}\n </div>\n );\n}\n","import { useState } from 'react';\nimport { Link } from 'react-router-dom';\n\nimport { JsonViewer } from '../common/data/JsonViewer';\nimport { SimpleMarkdown } from '../common/display/SimpleMarkdown';\n\ninterface RoundsExhaustedContextProps {\n payload: Record<string, unknown>;\n isTerminal?: boolean;\n resolverPayload?: Record<string, unknown> | null;\n onRetryTriage?: () => void;\n isRetrying?: boolean;\n}\n\nfunction SectionLabel({ children }: { children: React.ReactNode }) {\n return (\n <p className=\"text-2xs font-semibold uppercase tracking-widest text-text-tertiary mb-1.5\">{children}</p>\n );\n}\n\nexport function RoundsExhaustedContext({ payload, isTerminal, resolverPayload, onRetryTriage, isRetrying }: RoundsExhaustedContextProps) {\n const title = payload.title as string | undefined;\n const summary = payload.summary as string | undefined;\n const diagnosis = payload.diagnosis as string | undefined;\n const toolCalls = payload.tool_calls_made as number | undefined;\n const result = payload.result as Record<string, unknown> | null | undefined;\n\n // Detect triage resolution\n const ltMeta = resolverPayload?._lt as Record<string, unknown> | undefined;\n const wasTriaged = ltMeta?.triaged === true;\n const triageWorkflowId = ltMeta?.triageWorkflowId as string | undefined;\n const isResolvedByTriage = isTerminal && wasTriaged;\n\n const [showResult, setShowResult] = useState(false);\n\n // Resolved by triage — show success state\n if (isResolvedByTriage) {\n return (\n <div className=\"rounded-md border border-status-success/30 bg-surface-raised\">\n {/* Header */}\n <div className=\"flex items-center justify-between px-4 py-3 border-b border-surface-border\">\n <div className=\"flex items-center gap-2\">\n <svg className=\"w-4 h-4 text-status-success shrink-0\" viewBox=\"0 0 16 16\" fill=\"currentColor\">\n <path d=\"M8 1a7 7 0 110 14A7 7 0 018 1zm3.36 4.65a.5.5 0 00-.72 0L7 9.29 5.36 7.65a.5.5 0 10-.72.7l2 2a.5.5 0 00.72 0l4-4a.5.5 0 000-.7z\" />\n </svg>\n <span className=\"text-xs font-medium text-status-success\">Resolved by AI Triage</span>\n </div>\n {typeof toolCalls === 'number' && (\n <span className=\"text-2xs font-mono px-2 py-0.5 rounded-full bg-status-success/10 text-status-success\">\n {toolCalls} tool calls used\n </span>\n )}\n </div>\n\n {/* Body */}\n <div className=\"px-4 py-4 space-y-4\">\n {title && (\n <p className=\"text-sm font-medium text-text-primary\">{title}</p>\n )}\n\n {diagnosis && (\n <div>\n <SectionLabel>Triage diagnosis</SectionLabel>\n <div className=\"text-xs text-text-primary leading-relaxed\">\n <SimpleMarkdown content={diagnosis} />\n </div>\n </div>\n )}\n\n <div className=\"flex items-center gap-3\">\n {triageWorkflowId && (\n <Link\n to={`/workflows/executions/${triageWorkflowId}`}\n className=\"text-2xs text-accent hover:underline\"\n >\n View triage execution\n </Link>\n )}\n </div>\n </div>\n </div>\n );\n }\n\n // Default: warning state\n return (\n <div className=\"rounded-md border border-status-warning/30 bg-surface-raised\">\n {/* Header */}\n <div className=\"flex items-center justify-between px-4 py-3 border-b border-surface-border\">\n <div className=\"flex items-center gap-2\">\n <svg className=\"w-4 h-4 text-status-warning shrink-0\" viewBox=\"0 0 16 16\" fill=\"currentColor\">\n <path d=\"M8 1a7 7 0 110 14A7 7 0 018 1zm0 3a.75.75 0 00-.75.75v3.5a.75.75 0 001.5 0v-3.5A.75.75 0 008 4zm0 7a.75.75 0 100-1.5.75.75 0 000 1.5z\" />\n </svg>\n <span className=\"text-xs font-medium text-status-warning\">Tool Rounds Exhausted</span>\n </div>\n {typeof toolCalls === 'number' && (\n <span className=\"text-2xs font-mono px-2 py-0.5 rounded-full bg-status-warning/10 text-status-warning\">\n {toolCalls} tool calls used\n </span>\n )}\n </div>\n\n {/* Body */}\n <div className=\"px-4 py-4 space-y-4\">\n {title && (\n <p className=\"text-sm font-medium text-text-primary\">{title}</p>\n )}\n\n {summary && (\n <div>\n <SectionLabel>What happened</SectionLabel>\n <div className=\"text-xs text-text-secondary leading-relaxed\">\n <SimpleMarkdown content={summary} />\n </div>\n </div>\n )}\n\n {diagnosis && (\n <div>\n <SectionLabel>What went wrong</SectionLabel>\n <div className=\"text-xs text-text-primary leading-relaxed\">\n <SimpleMarkdown content={diagnosis} />\n </div>\n </div>\n )}\n\n {result != null && (\n <div>\n <button\n onClick={() => setShowResult(!showResult)}\n className=\"flex items-center gap-1 text-2xs font-semibold uppercase tracking-widest text-text-tertiary hover:text-text-secondary transition-colors\"\n >\n <svg className={`w-3 h-3 transition-transform ${showResult ? 'rotate-90' : ''}`} viewBox=\"0 0 12 12\" fill=\"currentColor\">\n <path d=\"M4.5 2l4 4-4 4\" />\n </svg>\n Partial results\n </button>\n {showResult && (\n <div className=\"mt-2\">\n <JsonViewer data={result} defaultMode=\"tree\" />\n </div>\n )}\n </div>\n )}\n\n {onRetryTriage && !isTerminal && (\n <div className=\"pt-2\">\n <button\n onClick={onRetryTriage}\n disabled={isRetrying}\n className=\"inline-flex items-center gap-2 px-4 py-2 text-xs font-medium bg-accent text-text-inverse rounded-md hover:bg-accent/90 disabled:opacity-50 disabled:cursor-not-allowed transition-colors\"\n >\n <svg className=\"w-3.5 h-3.5\" viewBox=\"0 0 14 14\" fill=\"currentColor\">\n <path d=\"M7 1a6 6 0 100 12A6 6 0 007 1zm2.5 6.5l-3.5 2V5.5l3.5 2z\" />\n </svg>\n {isRetrying ? 'Sending to triage...' : 'Retry with AI Triage'}\n </button>\n </div>\n )}\n </div>\n </div>\n );\n}\n","import { useCallback, useEffect, useRef } from 'react';\nimport type { LTEscalationRecord } from '../../api/types';\n\n// ---------------------------------------------------------------------------\n// postMessage protocol types\n// ---------------------------------------------------------------------------\n\n/** Messages sent from the parent to the iframe. */\ntype ParentMessage =\n | { type: 'lt:init'; escalation: IframeEscalationData; schema: Record<string, unknown> }\n | { type: 'lt:requestSubmit' }\n | { type: 'lt:validate' };\n\n/** Messages received from the iframe. */\ntype ChildMessage =\n | { type: 'lt:ready' }\n | { type: 'lt:submit'; payload: Record<string, unknown> }\n | { type: 'lt:escalate'; target: string }\n | { type: 'lt:resize'; height: number };\n\n/**\n * Escalation context delivered to the iframe via `lt:init`. Includes the\n * full envelope and metadata so the embedded app has all the context it\n * needs to load the right session and submit a meaningful payload back.\n *\n * The iframe is origin-validated before any message is sent, so secrets in\n * the envelope only travel to the declared src origin.\n */\ninterface IframeEscalationData {\n id: string;\n type: string;\n subtype: string;\n description: string | null;\n status: string;\n priority: number;\n role: string;\n workflow_type: string | null;\n envelope: Record<string, unknown> | null;\n metadata: Record<string, unknown> | null;\n escalation_payload: Record<string, unknown> | null;\n}\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\ninterface IframeViewportProps {\n src: string;\n escalation: LTEscalationRecord;\n schema: Record<string, unknown>;\n onResolve: (payload: Record<string, unknown>) => void;\n onEscalate: (targetRole: string) => void;\n submitAttempted?: boolean;\n /** Fill the parent container edge-to-edge (absolute inset-0). Used for full-bleed iframe mode. */\n fill?: boolean;\n}\n\nfunction safeParse(s: string | null | undefined): Record<string, unknown> | null {\n if (!s) return null;\n try { return JSON.parse(s) as Record<string, unknown>; } catch { return null; }\n}\n\n/**\n * Renders a sandboxed iframe for fully custom HITL UIs.\n *\n * Protocol — parent → iframe:\n * `lt:init` escalation context (id, envelope, metadata, payload) + schema\n * `lt:requestSubmit` ask the iframe to trigger its own submit flow\n * `lt:validate` ask the iframe to report validation errors\n *\n * Protocol — iframe → parent:\n * `lt:ready` iframe loaded, ready to receive `lt:init`\n * `lt:submit` work complete; payload becomes the resolver payload\n * `lt:escalate` re-route to a different role\n * `lt:resize` resize the iframe height\n *\n * The iframe can detect it is embedded via `window !== window.top` and\n * opt in to postMessage communication instead of its own submit UX.\n */\nexport function IframeViewport({ src, escalation, schema, onResolve, onEscalate, submitAttempted, fill }: IframeViewportProps) {\n const iframeRef = useRef<HTMLIFrameElement>(null);\n const iframeOrigin = useRef<string>('');\n\n // Parse the allowed origin from the src URL\n useEffect(() => {\n try {\n const url = new URL(src);\n iframeOrigin.current = url.origin;\n } catch {\n iframeOrigin.current = '';\n }\n }, [src]);\n\n const sendInit = useCallback(() => {\n const iframe = iframeRef.current;\n if (!iframe?.contentWindow || !iframeOrigin.current) return;\n\n const data: IframeEscalationData = {\n id: escalation.id,\n type: escalation.type,\n subtype: escalation.subtype,\n description: escalation.description,\n status: escalation.status,\n priority: escalation.priority,\n role: escalation.role,\n workflow_type: escalation.workflow_type,\n envelope: safeParse(escalation.envelope),\n metadata: escalation.metadata ?? null,\n escalation_payload: safeParse(escalation.escalation_payload),\n };\n\n const message: ParentMessage = { type: 'lt:init', escalation: data, schema };\n iframe.contentWindow.postMessage(message, iframeOrigin.current);\n }, [escalation, schema]);\n\n // Listen for messages from the iframe\n useEffect(() => {\n const handler = (event: MessageEvent) => {\n if (event.origin !== iframeOrigin.current) return;\n\n const data = event.data as ChildMessage;\n if (!data || typeof data !== 'object' || typeof data.type !== 'string') return;\n\n switch (data.type) {\n case 'lt:ready':\n sendInit();\n break;\n case 'lt:submit':\n if (data.payload && typeof data.payload === 'object') {\n onResolve(data.payload);\n }\n break;\n case 'lt:escalate':\n if (typeof data.target === 'string' && data.target) {\n onEscalate(data.target);\n }\n break;\n case 'lt:resize': {\n const iframe = iframeRef.current;\n if (iframe && typeof data.height === 'number' && data.height > 0) {\n iframe.style.height = `${Math.min(data.height, 2000)}px`;\n }\n break;\n }\n }\n };\n\n window.addEventListener('message', handler);\n return () => window.removeEventListener('message', handler);\n }, [sendInit, onResolve, onEscalate]);\n\n // Forward lt:validate to iframe when the action bar triggers a submit attempt\n useEffect(() => {\n if (!submitAttempted) return;\n const iframe = iframeRef.current;\n if (iframe?.contentWindow && iframeOrigin.current) {\n iframe.contentWindow.postMessage({ type: 'lt:validate' } as ParentMessage, iframeOrigin.current);\n }\n }, [submitAttempted]);\n\n if (fill) {\n return (\n <div className=\"absolute inset-0 overflow-hidden\">\n <iframe\n ref={iframeRef}\n src={src}\n sandbox=\"allow-scripts allow-same-origin allow-forms allow-pointer-lock allow-downloads\"\n className=\"w-full h-full border-0 block\"\n title=\"HITL Viewport\"\n onLoad={sendInit}\n />\n </div>\n );\n }\n\n return (\n // bg-white stays literal: customer HTML iframes assume a white canvas.\n <div className=\"rounded-md border border-surface-border overflow-hidden bg-white\">\n <iframe\n ref={iframeRef}\n src={src}\n sandbox=\"allow-scripts allow-same-origin allow-forms allow-pointer-lock allow-downloads\"\n className=\"w-full border-0\"\n style={{ minHeight: '600px' }}\n title=\"HITL Viewport\"\n onLoad={sendInit}\n />\n </div>\n );\n}\n","import { useEffect, useState, type ReactNode } from 'react';\nimport { Lock } from 'lucide-react';\n\n/** Animation length; a fallback timer clears state where animationend never fires. */\nconst HINT_MS = 2600;\n\n/**\n * The locked form's interaction frame. A click reports the gesture (the page\n * nudges Claim) and answers right at the click point: a small toast pops in\n * above the cursor naming the state — \"Claim this escalation to edit the\n * form\", \"Claimed by …\", \"resolved\" — holds a beat, and drifts out. Children\n * arrive as a prop, so hint state re-renders only this frame, never the form\n * beneath it.\n */\nexport function LockedFormFrame({\n hint,\n onLockedClick,\n children,\n}: {\n hint?: ReactNode;\n onLockedClick?: () => void;\n children: ReactNode;\n}) {\n const [hintAt, setHintAt] = useState<{ x: number; y: number; n: number } | null>(null);\n\n useEffect(() => {\n if (!hintAt) return;\n const timer = setTimeout(() => setHintAt(null), HINT_MS);\n return () => clearTimeout(timer);\n }, [hintAt]);\n\n const handleClick = (e: React.MouseEvent) => {\n onLockedClick?.();\n if (hint) {\n // Keep the bubble on screen when the click hugs a viewport edge.\n const x = Math.min(Math.max(e.clientX, 96), window.innerWidth - 96);\n setHintAt((prev) => ({ x, y: e.clientY, n: (prev?.n ?? 0) + 1 }));\n }\n };\n\n return (\n <div className=\"pb-8 max-w-form\" onClick={handleClick} data-testid=\"locked-form-frame\">\n {children}\n {hint && hintAt && (\n <div\n // Keyed per click so a repeat click replays the pop at the new spot.\n key={hintAt.n}\n role=\"status\"\n className=\"fixed z-[60] pointer-events-none flex items-center gap-2 px-3 py-1.5 rounded-md bg-surface-raised border border-surface-border shadow-lg text-xs font-medium text-text-primary whitespace-nowrap animate-[click-hint_2.6s_ease-in-out_both]\"\n style={{ left: hintAt.x, top: hintAt.y - 12 }}\n onAnimationEnd={() => setHintAt(null)}\n data-testid=\"locked-form-hint\"\n >\n <Lock className=\"w-3.5 h-3.5 text-accent shrink-0\" strokeWidth={1.5} />\n {hint}\n </div>\n )}\n </div>\n );\n}\n","/**\n * Shared field chrome for the resolver form: label, helper, error, and the\n * input class recipes. One place styles every generated field.\n */\n\nexport function FieldLabel({ children, isRequired, htmlFor }: {\n children: React.ReactNode;\n isRequired?: boolean;\n htmlFor?: string;\n}) {\n // `block` is load-bearing: a <label> is inline by default, and the\n // label→instruction→control anatomy would then hold only by accident —\n // a full-width control wraps below, but a narrow control (number,\n // max-w-48) with no instruction line sits flush BESIDE the label. The\n // anatomy is a column; the label declares it.\n return (\n <label htmlFor={htmlFor} className=\"block text-2xs font-semibold uppercase tracking-wider text-text-secondary\">\n {children}\n {isRequired && <span className=\"text-status-error ml-0.5\">*</span>}\n </label>\n );\n}\n\nexport function FieldHelper({ id, children }: { id?: string; children: React.ReactNode }) {\n return (\n <p id={id} className=\"text-2xs text-text-tertiary mt-0.5 leading-snug\">\n {children}\n </p>\n );\n}\n\nexport function FieldError({ error, id }: { error?: string; id?: string }) {\n if (!error) return null;\n return (\n <p id={id} role=\"alert\" className=\"text-2xs text-status-error mt-1 animate-[field-error-in_0.3s_ease-out]\">\n {error}\n </p>\n );\n}\n\nexport function inputClass(hasError?: boolean): string {\n return hasError\n ? 'input text-sm w-full mt-1 border-status-error/50 focus:border-status-error animate-[field-shake_0.4s_ease-in-out]'\n : 'input text-sm w-full mt-1';\n}\n\n// Select shares the field recipe but adds the unified chevron (via .select).\n// Width follows the content, floored for presence and capped by the cell —\n// a one-word choice never stretches across the measure. The floor is\n// min(16rem, 100%): CSS lets min-width beat max-width, so a bare min-w-64\n// would overflow a cell narrower than 16rem — the cell always wins.\nexport function selectClass(hasError?: boolean): string {\n return hasError\n ? 'select text-sm mt-1 min-w-[min(16rem,100%)] max-w-full border-status-error/50 focus:border-status-error animate-[field-shake_0.4s_ease-in-out]'\n : 'select text-sm mt-1 min-w-[min(16rem,100%)] max-w-full';\n}\n","import { useCallback, useRef } from 'react';\nimport { deriveFieldLabel } from '../../../lib/derive-field-label';\nimport { FieldLabel } from '../resolver-form/FieldChrome';\n\ninterface FileUploadWidgetProps {\n fieldKey: string;\n value: string;\n onChange: (v: string) => void;\n schema?: Record<string, unknown>;\n isRequired?: boolean;\n}\n\n/**\n * File upload widget that reads a file via FileReader and stores\n * its base64 data URL in the form value.\n */\nexport function FileUploadWidget({ fieldKey, value, onChange, schema, isRequired }: FileUploadWidgetProps) {\n const inputRef = useRef<HTMLInputElement>(null);\n const accept = (schema?.accept as string) ?? undefined;\n const label = deriveFieldLabel(fieldKey, schema);\n const helperText = schema?.description as string | undefined;\n\n const handleFile = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (!file) return;\n const reader = new FileReader();\n reader.onload = () => {\n if (typeof reader.result === 'string') {\n onChange(reader.result);\n }\n };\n reader.readAsDataURL(file);\n }, [onChange]);\n\n const hasFile = value.startsWith('data:');\n\n return (\n <div>\n <FieldLabel isRequired={isRequired}>\n {label}\n </FieldLabel>\n {helperText && <p className=\"text-2xs text-text-tertiary mt-0.5\">{helperText}</p>}\n <div className=\"mt-1\">\n <input\n ref={inputRef}\n type=\"file\"\n accept={accept}\n onChange={handleFile}\n className=\"hidden\"\n />\n <button\n type=\"button\"\n onClick={() => inputRef.current?.click()}\n className=\"btn-secondary text-xs px-3 py-1.5\"\n >\n {hasFile ? 'Replace file' : 'Choose file'}\n </button>\n {hasFile && (\n <span className=\"ml-2 text-xs text-status-success\">File attached</span>\n )}\n </div>\n </div>\n );\n}\n","import { useCallback } from 'react';\nimport { deriveFieldLabel } from '../../../lib/derive-field-label';\nimport { FieldLabel } from '../resolver-form/FieldChrome';\n\ninterface CodeEditorWidgetProps {\n fieldKey: string;\n value: string;\n onChange: (v: string) => void;\n schema?: Record<string, unknown>;\n isRequired?: boolean;\n}\n\n/**\n * Monospace textarea with tab-key support for code input.\n */\nexport function CodeEditorWidget({ fieldKey, value, onChange, schema, isRequired }: CodeEditorWidgetProps) {\n const label = deriveFieldLabel(fieldKey, schema);\n const helperText = schema?.description as string | undefined;\n const language = (schema?.['x-lt-language'] as string) ?? '';\n\n const handleKeyDown = useCallback((e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === 'Tab') {\n e.preventDefault();\n const target = e.currentTarget;\n const start = target.selectionStart;\n const end = target.selectionEnd;\n const updated = value.substring(0, start) + ' ' + value.substring(end);\n onChange(updated);\n requestAnimationFrame(() => {\n target.selectionStart = target.selectionEnd = start + 2;\n });\n }\n }, [value, onChange]);\n\n return (\n <div>\n <FieldLabel isRequired={isRequired}>\n {label}\n {language && (\n <span className=\"ml-2 text-text-tertiary/60 normal-case font-normal\">{language}</span>\n )}\n </FieldLabel>\n {helperText && <p className=\"text-2xs text-text-tertiary mt-0.5\">{helperText}</p>}\n <textarea\n value={value}\n onChange={(e) => onChange(e.target.value)}\n onKeyDown={handleKeyDown}\n className=\"input w-full mt-1 font-mono text-xs leading-relaxed\"\n rows={10}\n spellCheck={false}\n />\n </div>\n );\n}\n","import { useCallback, useEffect, useRef, useState } from 'react';\nimport { deriveFieldLabel } from '../../../lib/derive-field-label';\nimport { FieldLabel } from '../resolver-form/FieldChrome';\n\ninterface SignatureWidgetProps {\n fieldKey: string;\n value: string;\n onChange: (v: string) => void;\n schema?: Record<string, unknown>;\n isRequired?: boolean;\n}\n\n/**\n * HTML5 Canvas signature pad. Outputs a PNG data URL.\n */\nexport function SignatureWidget({ fieldKey, value, onChange, schema, isRequired }: SignatureWidgetProps) {\n const canvasRef = useRef<HTMLCanvasElement>(null);\n const [isDrawing, setIsDrawing] = useState(false);\n const label = deriveFieldLabel(fieldKey, schema);\n const helperText = schema?.description as string | undefined;\n\n useEffect(() => {\n const canvas = canvasRef.current;\n if (!canvas) return;\n const ctx = canvas.getContext('2d');\n if (!ctx) return;\n ctx.lineWidth = 2;\n ctx.lineCap = 'round';\n // Deliberately unthemed: the signature is a captured document artifact —\n // the exported PNG must read like ink on paper regardless of theme.\n ctx.strokeStyle = '#1E1535';\n\n if (value && value.startsWith('data:')) {\n const img = new Image();\n img.onload = () => ctx.drawImage(img, 0, 0);\n img.src = value;\n }\n }, []); // eslint-disable-line react-hooks/exhaustive-deps\n\n const getPos = useCallback((e: React.MouseEvent<HTMLCanvasElement> | React.TouchEvent<HTMLCanvasElement>) => {\n const canvas = canvasRef.current!;\n const rect = canvas.getBoundingClientRect();\n // The backing store is a fixed 400×150 document; the element may display\n // at any width. Scale pointer coordinates into store space so the ink\n // lands under the cursor at every display size.\n const scaleX = rect.width > 0 ? canvas.width / rect.width : 1;\n const scaleY = rect.height > 0 ? canvas.height / rect.height : 1;\n if ('touches' in e) {\n return {\n x: (e.touches[0].clientX - rect.left) * scaleX,\n y: (e.touches[0].clientY - rect.top) * scaleY,\n };\n }\n return { x: (e.clientX - rect.left) * scaleX, y: (e.clientY - rect.top) * scaleY };\n }, []);\n\n const startDraw = useCallback((e: React.MouseEvent<HTMLCanvasElement> | React.TouchEvent<HTMLCanvasElement>) => {\n setIsDrawing(true);\n const ctx = canvasRef.current?.getContext('2d');\n if (!ctx) return;\n const pos = getPos(e);\n ctx.beginPath();\n ctx.moveTo(pos.x, pos.y);\n }, [getPos]);\n\n const draw = useCallback((e: React.MouseEvent<HTMLCanvasElement> | React.TouchEvent<HTMLCanvasElement>) => {\n if (!isDrawing) return;\n const ctx = canvasRef.current?.getContext('2d');\n if (!ctx) return;\n const pos = getPos(e);\n ctx.lineTo(pos.x, pos.y);\n ctx.stroke();\n }, [isDrawing, getPos]);\n\n const endDraw = useCallback(() => {\n setIsDrawing(false);\n const canvas = canvasRef.current;\n if (canvas) {\n onChange(canvas.toDataURL('image/png'));\n }\n }, [onChange]);\n\n const clear = useCallback(() => {\n const canvas = canvasRef.current;\n if (!canvas) return;\n const ctx = canvas.getContext('2d');\n if (!ctx) return;\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n onChange('');\n }, [onChange]);\n\n return (\n <div>\n <FieldLabel isRequired={isRequired}>\n {label}\n </FieldLabel>\n {helperText && <p className=\"text-2xs text-text-tertiary mt-0.5\">{helperText}</p>}\n {/* The pad holds its natural document proportion (25rem = the 400px\n backing store), never stretched to the measure — the exported PNG\n is the artifact. Narrower cells shrink it; the scaling in getPos\n keeps the ink under the cursor either way. */}\n <div className=\"mt-1 max-w-[25rem] border border-surface-border rounded-md overflow-hidden bg-white\">\n <canvas\n ref={canvasRef}\n width={400}\n height={150}\n className=\"w-full cursor-crosshair touch-none\"\n onMouseDown={startDraw}\n onMouseMove={draw}\n onMouseUp={endDraw}\n onMouseLeave={endDraw}\n onTouchStart={startDraw}\n onTouchMove={draw}\n onTouchEnd={endDraw}\n />\n </div>\n <button\n type=\"button\"\n onClick={clear}\n className=\"mt-1 text-2xs text-text-tertiary hover:text-accent transition-colors\"\n >\n Clear\n </button>\n </div>\n );\n}\n","import { deriveFieldLabel } from '../../../lib/derive-field-label';\nimport { FieldLabel } from '../resolver-form/FieldChrome';\n\ninterface RichTextWidgetProps {\n fieldKey: string;\n value: string;\n onChange: (v: string) => void;\n schema?: Record<string, unknown>;\n isRequired?: boolean;\n}\n\n/**\n * Rich text input — a tall textarea with formatting hints.\n * A full WYSIWYG editor can replace this in a future iteration.\n */\nexport function RichTextWidget({ fieldKey, value, onChange, schema, isRequired }: RichTextWidgetProps) {\n const label = deriveFieldLabel(fieldKey, schema);\n const helperText = schema?.description as string | undefined;\n\n return (\n <div>\n <FieldLabel isRequired={isRequired}>\n {label}\n </FieldLabel>\n {helperText && <p className=\"text-2xs text-text-tertiary mt-0.5\">{helperText}</p>}\n <textarea\n value={value}\n onChange={(e) => onChange(e.target.value)}\n className=\"input w-full mt-1 text-sm leading-relaxed\"\n rows={8}\n placeholder=\"Supports plain text. Markdown formatting is preserved.\"\n />\n </div>\n );\n}\n","import { useState } from 'react';\nimport { deriveFieldLabel } from '../../../lib/derive-field-label';\nimport { FieldLabel } from '../resolver-form/FieldChrome';\nimport { MarkdownRenderer } from '../../common/display/MarkdownRenderer';\n\ninterface MarkdownWidgetProps {\n fieldKey: string;\n value: string;\n onChange: (v: string) => void;\n schema?: Record<string, unknown>;\n isRequired?: boolean;\n}\n\n/**\n * Markdown field — the same renderer the docs drawer uses, so a versioned\n * form schema can carry page source. Two shapes:\n *\n * - `readOnly: true` → a content block. The field's markdown (typically the\n * schema `default`) renders as HTML with no input chrome — instructions,\n * SOPs, and context live in the form as authored, versioned pages.\n * - editable → a Write/Preview source editor. The submitted value is the\n * markdown source.\n */\nexport function MarkdownWidget({ fieldKey, value, onChange, schema, isRequired }: MarkdownWidgetProps) {\n const [tab, setTab] = useState<'write' | 'preview'>('write');\n const label = deriveFieldLabel(fieldKey, schema);\n const helperText = schema?.description as string | undefined;\n const isReadOnly = schema?.readOnly === true;\n\n if (isReadOnly) {\n // Pure content block — the markdown carries its own headings and structure.\n return <MarkdownRenderer content={value} className=\"my-1\" />;\n }\n\n return (\n <div>\n <div className=\"flex items-center justify-between\">\n <FieldLabel isRequired={isRequired}>\n {label}\n </FieldLabel>\n <div className=\"flex items-center gap-0.5\">\n {(['write', 'preview'] as const).map((t) => (\n <button\n key={t}\n type=\"button\"\n onClick={() => setTab(t)}\n className={`px-2 py-0.5 text-2xs rounded transition-colors ${\n tab === t\n ? 'bg-accent/10 text-accent font-semibold'\n : 'text-text-quaternary hover:text-text-secondary'\n }`}\n >\n {t === 'write' ? 'Write' : 'Preview'}\n </button>\n ))}\n </div>\n </div>\n {helperText && <p className=\"text-2xs text-text-tertiary mt-0.5\">{helperText}</p>}\n {tab === 'write' ? (\n <textarea\n value={value}\n onChange={(e) => onChange(e.target.value)}\n className=\"input w-full mt-1 text-sm font-mono leading-relaxed\"\n rows={10}\n placeholder=\"Write markdown — headings, lists, tables, code blocks, and links all render.\"\n />\n ) : (\n <div className=\"mt-1 px-3 py-2 border border-surface-border rounded min-h-[120px]\">\n {value.trim() ? (\n <MarkdownRenderer content={value} />\n ) : (\n <p className=\"text-xs text-text-quaternary italic\">Nothing to preview.</p>\n )}\n </div>\n )}\n </div>\n );\n}\n","import { useEffect } from 'react';\nimport { Check } from 'lucide-react';\n\nimport { deriveFieldLabel } from '../../../lib/derive-field-label';\nimport { resolveChecklistItems, resolveChecklistDefault } from '../../../lib/field-validator';\nimport type { ShowIfContext } from '../../../lib/x-lt-show-if';\nimport { FieldLabel, FieldHelper } from '../resolver-form/FieldChrome';\nimport type { WidgetProps } from './index';\n\ninterface ChecklistItem { id: string; label: string; required?: boolean }\n\n/** Labels at or under this length read as tags; longer ones read as sentences. */\nconst CHIP_LABEL_MAX = 28;\n\n/**\n * Checklist widget — a dynamic list of labeled checkboxes driven by runtime\n * data in the escalation context.\n *\n * Schema usage:\n * \"x-lt-widget\": \"checklist\"\n * \"x-lt-source\": \"envelope.checklist_items\" (any domain.path, or an\n * ordered array of paths — first source that resolves wins)\n * \"x-lt-variant\": \"chips\" | \"rows\" (optional; see geometry below)\n *\n * Item definitions: Array<{ id: string; label: string; required?: boolean }>\n *\n * GEOMETRY — item length and selection mode decide it:\n * - rows — one item per line. The shape for rituals: sentence-length\n * confirmations read top-down and are ticked deliberately.\n * `x-lt-require-all` always renders rows.\n * - chips — a wrapping cloud of selectable pills. The shape for tags:\n * short pick-any items (reject reasons, categories) flow horizontally,\n * thumb-sized, selection visible at a glance.\n * Explicit `x-lt-variant` wins; otherwise require-all → rows, else chips\n * when every label is ≤28 characters.\n *\n * \"x-lt-require-all\": true — completion guard: every item must be checked\n * before submission, except items whose definition carries required: false.\n *\n * \"x-lt-default-checked\": true — first-load default: an unanswered field\n * initializes to every item checked (affirm-then-exception: the submitter\n * unchecks what failed). A saved answer map is never clobbered.\n *\n * Value stored: Record<string, boolean> keyed by item id.\n */\nexport function ChecklistWidget({\n fieldKey,\n value,\n onChange,\n schema,\n escalationContext,\n isRequired,\n submitAttempted,\n error,\n}: WidgetProps & { escalationContext?: ShowIfContext }) {\n const requireAll = schema?.['x-lt-require-all'] === true;\n // The shared resolver serves render and enforcement alike — including\n // {{domain.path}} interpolation in the source path.\n const items: ChecklistItem[] = resolveChecklistItems(\n schema?.['x-lt-source'],\n escalationContext as Record<string, unknown> | undefined,\n );\n\n let state: Record<string, boolean> = {};\n try { if (value) state = JSON.parse(value) as Record<string, boolean>; } catch { /* start empty */ }\n\n // First-load default (x-lt-default-checked): the moment the source resolves\n // (a lookup arrives async), an unanswered field initializes to every item\n // checked. Keyed on the serialized default so it fires once per material\n // change and never against a saved answer map.\n const defaultJson = (() => {\n const d = resolveChecklistDefault(schema, state, escalationContext as Record<string, unknown> | undefined);\n return d ? JSON.stringify(d) : null;\n })();\n useEffect(() => {\n if (defaultJson) onChange(defaultJson);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [defaultJson]);\n\n const toggle = (id: string) => onChange(JSON.stringify({ ...state, [id]: !state[id] }));\n\n const title = deriveFieldLabel(fieldKey, schema);\n const helperText = schema?.description as string | undefined;\n\n if (items.length === 0) {\n return (\n <>\n <p className=\"text-xs text-text-tertiary italic mt-1\">\n No checklist items. None of the field's x-lt-source paths resolved on this escalation.\n </p>\n {error && (\n <p className=\"text-2xs text-status-error mt-1 animate-[field-error-in_0.3s_ease-out]\">\n {error}\n </p>\n )}\n </>\n );\n }\n\n const explicitVariant = schema?.['x-lt-variant'] as string | undefined;\n const variant = explicitVariant === 'chips' || explicitVariant === 'rows'\n ? explicitVariant\n : requireAll || items.some((i) => i.label.length > CHIP_LABEL_MAX)\n ? 'rows'\n : 'chips';\n\n const checkedCount = items.filter((item) => state[item.id]).length;\n // The click-to-focus anchor: the first unchecked mandatory item, so the\n // error panel lands the user on the next box to tick (first item when done).\n const focusId = (items.find((i) => !state[i.id] && i.required !== false) ?? items[0]).id;\n\n return (\n <div role=\"group\" aria-label={title} aria-required={isRequired || undefined} aria-invalid={error ? true : undefined}>\n <FieldLabel isRequired={isRequired}>{title}</FieldLabel>\n {helperText && <FieldHelper>{helperText}</FieldHelper>}\n {variant === 'chips' ? (\n <div className=\"flex flex-wrap gap-2 mt-2\">\n {items.map((item) => {\n const checked = state[item.id] ?? false;\n const showItemError = !checked && !!submitAttempted && checkedCount === 0 && (item.required || isRequired);\n return (\n // The pill IS the checkbox: the real input stays in the label\n // (sr-only) so native semantics and the focus anchor survive.\n // Selection is an act — it earns the solid accent.\n <label\n key={item.id}\n className={`inline-flex items-center gap-1.5 cursor-pointer select-none px-3.5 py-2 text-sm border transition-colors rounded-[var(--lt-radius-field)] ${\n checked\n ? 'bg-accent border-accent text-text-inverse'\n : showItemError\n ? 'bg-surface-field border-status-error/60 text-status-error'\n : 'bg-surface-field border-surface-field-border text-text-secondary hover:border-accent hover:text-text-primary'\n }`}\n >\n <input\n type=\"checkbox\"\n checked={checked}\n onChange={() => toggle(item.id)}\n className=\"sr-only\"\n data-testid={`checklist-item-${item.id}`}\n {...(item.id === focusId ? { 'data-field-key': fieldKey } : {})}\n />\n {checked && <Check className=\"w-3.5 h-3.5 shrink-0\" strokeWidth={2.5} />}\n {item.label}\n </label>\n );\n })}\n </div>\n ) : (\n <div className=\"space-y-2.5 mt-2\">\n {items.map((item) => {\n const checked = state[item.id] ?? false;\n // require-all: every unchecked mandatory item (required !== false) is an\n // error after a submit attempt, clearing live as each is checked.\n // At-least-one mode: highlight only while ZERO are checked — once any\n // item is confirmed the group requirement is met and highlights clear.\n const showItemError = !checked && !!submitAttempted && (\n requireAll\n ? item.required !== false\n : checkedCount === 0 && (item.required || isRequired)\n );\n return (\n <label\n key={item.id}\n className={`flex items-start gap-3 cursor-pointer group select-none rounded px-2 py-1 -mx-2 transition-colors ${\n showItemError ? 'bg-status-error/5' : 'hover:bg-surface-hover'\n }`}\n >\n <input\n type=\"checkbox\"\n checked={checked}\n onChange={() => toggle(item.id)}\n className={`mt-0.5 w-3.5 h-3.5 shrink-0 rounded ${showItemError ? 'accent-status-error' : 'accent-accent'}`}\n data-testid={`checklist-item-${item.id}`}\n {...(item.id === focusId ? { 'data-field-key': fieldKey } : {})}\n />\n <span className={`text-sm leading-snug transition-colors ${\n showItemError\n ? 'text-status-error'\n : 'text-text-secondary group-hover:text-text-primary'\n }`}>\n {item.label}\n {item.required && (\n <span className={`ml-0.5 text-2xs ${showItemError ? 'text-status-error' : 'text-text-quaternary'}`}>*</span>\n )}\n </span>\n </label>\n );\n })}\n </div>\n )}\n <p className=\"text-2xs text-text-quaternary mt-3 tabular-nums\">\n {variant === 'chips' ? (\n <>\n {checkedCount} selected\n {isRequired && checkedCount === 0 && !!submitAttempted && (\n <span className=\"ml-1 text-text-quaternary/60\">(check at least one)</span>\n )}\n </>\n ) : (\n <>\n {checkedCount} / {items.length} confirmed\n {requireAll ? (\n <span className=\"ml-1 text-text-quaternary/60\">\n (all required{items.some((i) => i.required === false) ? ' except optional' : ''})\n </span>\n ) : isRequired && checkedCount === 0 && !!submitAttempted && (\n <span className=\"ml-1 text-text-quaternary/60\">(at least one required)</span>\n )}\n </>\n )}\n </p>\n {error && (\n <p role=\"alert\" className=\"text-2xs text-status-error mt-1 animate-[field-error-in_0.3s_ease-out]\">\n {error}\n </p>\n )}\n </div>\n );\n}\n","import { useState } from 'react';\nimport { Paperclip, Download, ExternalLink } from 'lucide-react';\nimport type { WidgetProps } from './index';\n\n/**\n * Attachment widget — readOnly display of a binary value captured earlier\n * (typically by the file-upload widget): a data URL or a fetchable URL.\n * Declared as `x-lt-widget: \"attachment\"` (`\"image\"` is an accepted alias).\n *\n * Type dispatch keeps rendering safe:\n * image/* — inline constrained preview, click for full size (the <img>\n * context is script-inert, so data URLs are safe here)\n * everything else — a labeled open/download affordance, NEVER embedded as a\n * document (inlining arbitrary data: content is an XSS vector)\n */\n\ntype Kind =\n | { kind: 'none' }\n | { kind: 'image'; src: string }\n | { kind: 'file'; href: string; label: string; isData: boolean };\n\nconst IMAGE_EXT = /\\.(png|jpe?g|gif|webp|avif|bmp|svg)(\\?.*)?$/i;\n\nfunction classify(value: string): Kind {\n const v = value.trim();\n if (!v) return { kind: 'none' };\n\n const dataMime = /^data:([^;,]+)[;,]/.exec(v)?.[1]?.toLowerCase();\n if (dataMime) {\n if (dataMime.startsWith('image/')) return { kind: 'image', src: v };\n const label = dataMime === 'application/pdf' ? 'PDF' : dataMime;\n return { kind: 'file', href: v, label, isData: true };\n }\n\n if (/^https?:\\/\\//i.test(v)) {\n if (IMAGE_EXT.test(v)) return { kind: 'image', src: v };\n const ext = /\\.([a-z0-9]{2,5})(\\?.*)?$/i.exec(v)?.[1]?.toUpperCase();\n return { kind: 'file', href: v, label: ext ?? 'attachment', isData: false };\n }\n\n return { kind: 'none' };\n}\n\nexport function AttachmentWidget({ fieldKey, value, schema }: WidgetProps) {\n const [expanded, setExpanded] = useState(false);\n const att = classify(value ?? '');\n const label = fieldKey.replace(/[_-]/g, ' ');\n const helperText = schema?.description as string | undefined;\n\n const head = (\n <>\n <label className=\"text-2xs font-semibold uppercase tracking-widest text-text-tertiary\">\n {label}\n </label>\n {helperText && <p className=\"text-2xs text-text-tertiary mt-0.5\">{helperText}</p>}\n </>\n );\n\n if (att.kind === 'none') {\n return (\n <div>\n {head}\n <p className=\"text-xs text-text-quaternary italic mt-1\">No attachment</p>\n </div>\n );\n }\n\n if (att.kind === 'image') {\n return (\n <div>\n {head}\n <div className=\"mt-1\">\n <button\n type=\"button\"\n onClick={() => setExpanded(true)}\n className=\"block rounded-[0.125em] border border-surface-border overflow-hidden hover:border-accent transition-colors\"\n title=\"View full size\"\n >\n <img\n src={att.src}\n alt={fieldKey.replace(/[_-]/g, ' ')}\n className=\"max-h-48 max-w-full object-contain\"\n data-testid={`attachment-image-${fieldKey}`}\n />\n </button>\n {expanded && (\n <div\n className=\"fixed inset-0 z-[100] bg-text-primary/60 backdrop-blur-sm flex items-center justify-center p-8 cursor-zoom-out\"\n onClick={() => setExpanded(false)}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={`${label} — full size`}\n >\n <img src={att.src} alt={label} className=\"max-h-[90vh] max-w-[90vw] object-contain\" />\n </div>\n )}\n </div>\n </div>\n );\n }\n\n // Non-image: safe open/download only — the content is never embedded.\n return (\n <div>\n {head}\n <div className=\"mt-1\">\n <a\n href={att.href}\n {...(att.isData\n ? { download: `${fieldKey}.${att.label === 'PDF' ? 'pdf' : 'bin'}` }\n : { target: '_blank', rel: 'noopener noreferrer' })}\n className=\"inline-flex items-center gap-1.5 text-xs text-accent hover:text-accent-hover transition-colors\"\n data-testid={`attachment-link-${fieldKey}`}\n >\n <Paperclip className=\"w-3.5 h-3.5\" strokeWidth={1.5} />\n {att.isData ? `Download ${att.label}` : `Open ${att.label}`}\n {att.isData\n ? <Download className=\"w-3 h-3\" strokeWidth={1.5} />\n : <ExternalLink className=\"w-3 h-3\" strokeWidth={1.5} />}\n </a>\n </div>\n </div>\n );\n}\n","import { Link } from 'react-router-dom';\nimport { ExternalLink } from 'lucide-react';\nimport { interpolateHelp } from '../../../lib/x-lt-help';\nimport { FieldLabel, FieldHelper } from '../resolver-form/FieldChrome';\nimport type { WidgetProps } from './index';\n\n/**\n * Link widget — a named navigation link whose URL is a `{{domain.path}}`\n * template resolved at render time from the escalation context.\n *\n * Schema usage:\n * \"x-lt-widget\": \"link\"\n * \"x-lt-href\": \"/escalations/available?role=foo&facets={\\\"orderId\\\":\\\"{{metadata.orderId}}\\\"}\"\n * \"title\": \"Human-readable label\"\n * \"description\": \"One-line instruction text\"\n *\n * URL behaviour:\n * Paths starting with \"/\" navigate inside the dashboard (React Router <Link>).\n * Anything else opens in a new tab with rel=\"noreferrer\".\n *\n * This widget is display-only — it produces no resolver payload value and must\n * never appear in the schema's `required` array.\n */\nexport function LinkWidget({ fieldKey, schema, escalationContext }: WidgetProps) {\n const hrefTemplate = (schema?.['x-lt-href'] as string | undefined) ?? '';\n const href = hrefTemplate && escalationContext\n ? interpolateHelp(hrefTemplate, escalationContext)\n : hrefTemplate;\n\n const label = (schema?.title as string | undefined) ?? (schema?.description as string | undefined) ?? 'Open';\n const helperText = schema?.description as string | undefined;\n const isInternal = href.startsWith('/');\n const isEmpty = !href.trim();\n\n return (\n <div data-field-key={fieldKey}>\n <FieldLabel>{label}</FieldLabel>\n {helperText && <FieldHelper>{helperText}</FieldHelper>}\n <div className=\"mt-1\">\n {isEmpty ? (\n <span className=\"text-xs text-text-quaternary italic\">No link configured</span>\n ) : isInternal ? (\n <Link\n to={href}\n className=\"inline-flex items-center gap-1 text-xs text-accent hover:text-accent-hover transition-colors\"\n data-testid={`link-widget-${fieldKey}`}\n >\n {label}\n <ExternalLink className=\"w-3 h-3 shrink-0\" strokeWidth={1.5} />\n </Link>\n ) : (\n <a\n href={href}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"inline-flex items-center gap-1 text-xs text-accent hover:text-accent-hover transition-colors\"\n data-testid={`link-widget-${fieldKey}`}\n >\n {label}\n <ExternalLink className=\"w-3 h-3 shrink-0\" strokeWidth={1.5} />\n </a>\n )}\n </div>\n </div>\n );\n}\n","import { Link } from 'react-router-dom';\nimport { ArrowUpRight } from 'lucide-react';\n\n/**\n * The one affordance for opening an embedded row's detail page — a clear\n * icon-in-a-button, not a bare glyph, so the gesture reads as \"open this\". The\n * tooltip stays generic (\"View details\") rather than naming the record kind, so\n * the same control fits any embed. Non-focusable: the row/card click and the\n * canned actions carry the keyboard path; this is a pointer shortcut.\n */\nexport function OpenDetailButton({ to, className = '' }: { to: string; className?: string }) {\n return (\n <Link\n to={to}\n title=\"View details\"\n tabIndex={-1}\n className={`inline-flex items-center justify-center w-6 h-6 shrink-0 rounded border border-surface-border text-accent/70 hover:text-accent hover:border-accent/60 hover:bg-accent/5 transition-colors ${className}`}\n >\n <ArrowUpRight className=\"w-3.5 h-3.5\" strokeWidth={2} />\n <span className=\"sr-only\">View details</span>\n </Link>\n );\n}\n","import { OpenDetailButton } from './OpenDetailButton';\n\nimport { interpolateHelp } from '../../../lib/x-lt-help';\nimport { getDeep } from '../../../lib/x-lt-bind';\nimport { formatAgoCompact } from '../../../lib/format';\nimport { useEscalation } from '../../../api/escalations';\nimport { rowContext } from '../EscalationListView';\nimport { FieldLabel, FieldHelper } from '../resolver-form/FieldChrome';\nimport { StatusBadge } from '../../common/display/StatusBadge';\nimport type { WidgetProps } from './index';\nimport type { ShowIfContext } from '../../../lib/x-lt-show-if';\n\ninterface FieldDef { label: string; value: string; format?: string }\n\nconst EM_DASH = '—';\n\nfunction resolveSourceId(\n sourcePath: string | undefined,\n escalationContext: ShowIfContext | undefined,\n): string {\n if (!sourcePath || !escalationContext) return '';\n const dot = sourcePath.indexOf('.');\n if (dot === -1) return '';\n const domain = sourcePath.slice(0, dot) as keyof ShowIfContext;\n const path = sourcePath.slice(dot + 1);\n try {\n const v = getDeep(escalationContext[domain] as unknown, path);\n return typeof v === 'string' ? v : '';\n } catch {\n return '';\n }\n}\n\nfunction renderFieldValue(raw: string, format?: string): string {\n if (!raw || raw === EM_DASH) return EM_DASH;\n if (format === 'age') {\n const d = new Date(raw);\n return Number.isNaN(d.getTime()) ? raw : formatAgoCompact(raw);\n }\n return raw;\n}\n\n/**\n * Escalation widget — embeds a single escalation record inline in the form as\n * a compact card. The escalation ID is resolved from a `domain.path` declared\n * in `x-lt-source`; the card's detail rows are configured via `x-lt-fields`.\n *\n * Schema usage:\n * \"x-lt-widget\": \"escalation\"\n * \"x-lt-source\": \"metadata.parent_escalation_id\" (any domain.path → ID)\n * \"x-lt-fields\": [ (optional, any of escalation's data)\n * { \"label\": \"Order\", \"value\": \"{{metadata.orderId}}\" },\n * { \"label\": \"Decision\", \"value\": \"{{resolver.decision}}\" },\n * { \"label\": \"Age\", \"value\": \"{{escalation.created_at}}\", \"format\": \"age\" }\n * ]\n * \"title\": \"Card heading label\"\n * \"description\": \"One-line instruction text\"\n *\n * `x-lt-fields` token values resolve against the *embedded* escalation's own\n * context (its escalation row, metadata, envelope, payload, resolver) — not the\n * parent form's context. Same domain/path convention as x-lt-active.fields.\n *\n * Display-only — produces no resolver payload and must not appear in `required`.\n */\nexport function EscalationWidget({ fieldKey, schema, escalationContext }: WidgetProps) {\n const sourcePath = schema?.['x-lt-source'] as string | undefined;\n const fields = (schema?.['x-lt-fields'] as FieldDef[] | undefined) ?? [];\n const label = (schema?.title as string | undefined) ?? 'Linked escalation';\n const helperText = schema?.description as string | undefined;\n\n const id = resolveSourceId(sourcePath, escalationContext);\n const { data: esc, isLoading, isError } = useEscalation(id);\n\n return (\n <div data-field-key={fieldKey}>\n <FieldLabel>{label}</FieldLabel>\n {helperText && <FieldHelper>{helperText}</FieldHelper>}\n <div className=\"mt-1\">\n {!id || isError ? (\n <p className=\"text-xs text-text-quaternary italic\" data-testid={`escalation-widget-empty-${fieldKey}`}>\n No linked record\n </p>\n ) : isLoading ? (\n <EscalationCardSkeleton />\n ) : esc ? (\n <EscalationCard esc={esc} fields={fields} fieldKey={fieldKey} />\n ) : (\n <p className=\"text-xs text-text-quaternary italic\">No linked record</p>\n )}\n </div>\n </div>\n );\n}\n\nfunction EscalationCard({\n esc,\n fields,\n fieldKey,\n}: {\n esc: ReturnType<typeof useEscalation>['data'];\n fields: FieldDef[];\n fieldKey: string;\n}) {\n if (!esc) return null;\n const ctx = rowContext(esc);\n\n return (\n <div\n className=\"border-l-2 border-accent-faint pl-3 py-2 space-y-2\"\n data-testid={`escalation-widget-card-${fieldKey}`}\n >\n {/* Header: type + status */}\n <div className=\"flex items-center gap-2 flex-wrap\">\n <span className=\"text-2xs font-semibold uppercase tracking-wider text-text-secondary\">\n {esc.type}{esc.subtype && esc.subtype !== esc.type ? ` · ${esc.subtype}` : ''}\n </span>\n <StatusBadge status={esc.status} />\n </div>\n\n {/* Description */}\n {esc.description && (\n <p className=\"text-xs text-text-primary leading-snug\">{esc.description}</p>\n )}\n\n {/* x-lt-fields facts — same dictionary visual as DictionaryList */}\n {fields.length > 0 && (\n <dl className=\"grid grid-cols-[auto_1fr] gap-x-4 gap-y-0.5\">\n {fields.map((f) => {\n const raw = interpolateHelp(f.value, ctx);\n const display = renderFieldValue(raw, f.format);\n return (\n <div key={f.label} className=\"contents\">\n <dt className=\"text-2xs text-text-tertiary whitespace-nowrap\">{f.label}</dt>\n <dd className=\"text-2xs text-text-primary\">{display}</dd>\n </div>\n );\n })}\n </dl>\n )}\n\n {/* Footer: role, age, detail link */}\n <div className=\"flex items-center justify-between gap-2\">\n <span className=\"text-2xs text-text-quaternary\">\n {esc.role} · {formatAgoCompact(esc.created_at)}\n </span>\n <OpenDetailButton to={`/escalations/detail/${esc.id}`} />\n </div>\n </div>\n );\n}\n\nfunction EscalationCardSkeleton() {\n return (\n <div className=\"border-l-2 border-accent-faint pl-3 py-2 space-y-2 animate-pulse\">\n <div className=\"h-3 w-32 bg-surface-sunken rounded\" />\n <div className=\"h-3 w-48 bg-surface-sunken rounded\" />\n <div className=\"h-3 w-24 bg-surface-sunken rounded\" />\n </div>\n );\n}\n","import { interpolateHelp } from './x-lt-help';\nimport type { ShowIfContext } from './x-lt-show-if';\n\n/**\n * The embedded escalation query shape shared by `x-lt-query` (escalation-list\n * widget) and `x-lt-submit-guard.query` (form-level submit gate). String\n * values inside `facets` support `{{domain.path}}` token interpolation against\n * the host escalation's context. Isomorphic: the dashboard renders embeds from\n * it, and the API layer enforces the submit gate from the identical mapping.\n *\n * `assigned` is the ownership scope. Ownership is not a separate list — it is\n * one more dimension of the same faceted query language the escalation API\n * composes server-side (\"claimed\" is the implied status: pending, held, claim\n * window live):\n * - `\"me\"` — rows claimed by the viewing user (the walk case: I walk what I own)\n * - `\"any\"` — all matching rows regardless of claim state\n * - omitted — available rows only (unclaimed, or claim window lapsed)\n */\nexport interface EmbedQuery {\n role?: string;\n status?: string;\n facets?: Record<string, string>;\n limit?: number;\n assigned?: 'me' | 'any';\n /** Superseded by `assigned`; honored only when `assigned` is omitted. */\n available?: boolean;\n}\n\n/** Interpolate `{{domain.path}}` tokens in every string value of the facets map. */\nexport function resolveQueryFacets(\n facets: Record<string, string> | undefined,\n ctx: ShowIfContext,\n): Record<string, unknown> {\n if (!facets) return {};\n const resolved: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(facets)) {\n resolved[k] = typeof v === 'string' ? interpolateHelp(v, ctx) : v;\n }\n return resolved;\n}\n\n/** The escalation-query params an EmbedQuery resolves to — the exact input\n * shape of `useEscalations`, so every embed surface queries identically. */\nexport interface ScopedQueryParams {\n role?: string;\n status: string;\n facets: Record<string, unknown>;\n assigned_to?: string;\n available?: boolean;\n limit?: number;\n enabled: boolean;\n}\n\n/**\n * Resolve an EmbedQuery into concrete escalation-query params — the ONE\n * mapping every embed surface (escalation-list, x-lt-actions, x-lt-submit-guard)\n * consumes, so the visible rows and any count derived from the same query can\n * never disagree.\n *\n * Ownership scope translates into the faceted query language:\n * - `assigned: \"me\"` → `assigned_to = viewer AND available = false` — the\n * implied \"claimed\" status (pending + live claim window held by the viewer)\n * - `assigned: \"any\"` → no ownership constraint\n * - omitted → `available = true` (the unclaimed pool; a declared\n * legacy `available` value is honored)\n *\n * When `assigned: \"me\"` and no viewer id is supplied (a surface with no\n * resolving user, e.g. an MCP resolve), the scope cannot be evaluated —\n * `enabled` is false rather than silently widening to another scope.\n */\nexport function resolveScopedQuery(\n query: EmbedQuery,\n ctx: ShowIfContext,\n viewerId: string | undefined,\n): ScopedQueryParams {\n const facets = resolveQueryFacets(query.facets, ctx);\n const base: ScopedQueryParams = {\n role: query.role,\n status: query.status ?? 'pending',\n facets,\n limit: query.limit,\n enabled: !!(query.role || Object.keys(facets).length),\n };\n if (query.assigned === 'me') {\n return { ...base, assigned_to: viewerId, available: false, enabled: base.enabled && !!viewerId };\n }\n if (query.assigned === 'any') {\n return base;\n }\n return { ...base, available: query.available ?? true };\n}\n","import { useState } from 'react';\nimport { OpenDetailButton } from './OpenDetailButton';\nimport { interpolateHelp } from '../../../lib/x-lt-help';\nimport { formatAgoCompact } from '../../../lib/format';\nimport { rowContext } from '../EscalationListView';\nimport { useEscalations, useResolveEscalation } from '../../../api/escalations';\nimport { useAuth } from '../../../hooks/useAuth';\nimport { FieldLabel, FieldHelper } from '../resolver-form/FieldChrome';\nimport { resolveScopedQuery, type EmbedQuery } from '../../../lib/x-lt-query';\nimport { schemaNeedsEnvelope } from '../../../lib/schema-needs-envelope';\nimport type { WidgetProps } from './index';\nimport type { ShowIfContext } from '../../../lib/x-lt-show-if';\nimport type { LTEscalationRecord } from '../../../api/types';\n\ninterface ColumnDef { label: string; value: string; format?: string }\n\n/**\n * An inline row action: fires a canned resolve against the row through the\n * standard resolve endpoint — RBAC and enforce_schema validation apply\n * server-side exactly as a full-form resolve. String leaves inside\n * `resolverPayload` (and `confirm`) interpolate `{{domain.path}}` tokens\n * against the row's own context; booleans and numbers pass through typed.\n */\ninterface ActionDef {\n label: string;\n resolverPayload: Record<string, unknown>;\n /** Optional confirm prompt shown before firing; tokens interpolate per row. */\n confirm?: string;\n}\n\nconst DEFAULT_COLUMNS: ColumnDef[] = [\n { label: 'Description', value: '{{escalation.description}}' },\n { label: 'Role', value: '{{escalation.role}}' },\n { label: 'Age', value: '{{escalation.created_at}}', format: 'age' },\n];\n\nconst EM_DASH = '—';\n\nfunction renderValue(raw: string, format?: string): string {\n if (!raw || raw === EM_DASH) return EM_DASH;\n if (format === 'age') {\n const d = new Date(raw);\n return Number.isNaN(d.getTime()) ? raw : formatAgoCompact(raw);\n }\n return raw;\n}\n\n/** Deep-walk a payload template: string leaves interpolate `{{domain.path}}`\n * tokens against the row context; every other type passes through typed. */\nfunction interpolatePayload(value: unknown, ctx: ShowIfContext): unknown {\n if (typeof value === 'string') return interpolateHelp(value, ctx);\n if (Array.isArray(value)) return value.map((v) => interpolatePayload(v, ctx));\n if (value && typeof value === 'object') {\n return Object.fromEntries(\n Object.entries(value).map(([k, v]) => [k, interpolatePayload(v, ctx)]),\n );\n }\n return value;\n}\n\n/**\n * Escalation list widget — embeds a compact list of escalations inline in the\n * form, driven by a facet query declared in `x-lt-query`. String values inside\n * `x-lt-query.facets` support `{{domain.path}}` token interpolation.\n *\n * Schema usage:\n * \"x-lt-widget\": \"escalation-list\"\n * \"x-lt-query\": {\n * \"role\": \"rel-originator\",\n * \"facets\": { \"customerId\": \"{{metadata.customerId}}\" },\n * \"status\": \"pending\",\n * \"limit\": 5\n * }\n * \"x-lt-columns\": [ (optional)\n * { \"label\": \"Order\", \"value\": \"{{metadata.orderId}}\" },\n * { \"label\": \"Age\", \"value\": \"{{escalation.created_at}}\", \"format\": \"age\" }\n * ]\n * \"title\": \"List heading\"\n * \"description\": \"One-line instruction text\"\n * \"x-lt-actions\": [ (optional)\n * { \"label\": \"Bagged ✓\",\n * \"resolverPayload\": { \"approved\": true, \"checks\": { \"bagged\": true } },\n * \"confirm\": \"Bag {{metadata.orderId}}?\" }\n * ]\n *\n * Column `value` strings use the same `{{domain.path}}` token convention as\n * `x-lt-active.fields` and `x-lt-columns` in list schemas — tokens resolve\n * against each displayed escalation's own row context.\n *\n * When `x-lt-columns` is absent, falls back to three default columns:\n * description, role, age.\n *\n * Produces no resolver payload for the PARENT form and must not appear in\n * `required`. `x-lt-actions` buttons resolve the ROW through the standard\n * resolve endpoint — server-side RBAC and enforce_schema apply; a rejected\n * canned resolve surfaces its message inline and the row's detail link\n * remains the full-form path.\n */\nexport function EscalationListWidget({ fieldKey, schema, escalationContext }: WidgetProps) {\n const rawQuery = (schema?.['x-lt-query'] as EmbedQuery | undefined) ?? {};\n const columns = (schema?.['x-lt-columns'] as ColumnDef[] | undefined) ?? DEFAULT_COLUMNS;\n const actions = (schema?.['x-lt-actions'] as ActionDef[] | undefined) ?? [];\n const label = (schema?.title as string | undefined) ?? 'Related items';\n const helperText = schema?.description as string | undefined;\n\n const ctx = escalationContext ?? {};\n const { user } = useAuth();\n\n // ONE shared mapping (resolveScopedQuery) turns x-lt-query into concrete\n // escalation params — the same call x-lt-submit-guard makes, so the visible\n // rows and the guard's count evaluate the identical scope.\n const scoped = resolveScopedQuery(rawQuery, ctx, user?.userId);\n\n const { data, isLoading } = useEscalations({\n role: scoped.role,\n status: scoped.status,\n facets: scoped.facets,\n assigned_to: scoped.assigned_to,\n available: scoped.available,\n limit: scoped.limit ?? 5,\n enabled: scoped.enabled,\n include: schemaNeedsEnvelope({ columns, actions }) ? 'envelope' : undefined,\n });\n\n const escalations = data?.escalations ?? [];\n\n const resolve = useResolveEscalation();\n const [rowErrors, setRowErrors] = useState<Record<string, string>>({});\n const [pendingRow, setPendingRow] = useState<string | null>(null);\n\n const fireAction = async (esc: LTEscalationRecord, action: ActionDef) => {\n const rowCtx = rowContext(esc);\n if (action.confirm && !window.confirm(interpolateHelp(action.confirm, rowCtx))) return;\n setPendingRow(esc.id);\n setRowErrors((prev) => ({ ...prev, [esc.id]: '' }));\n try {\n await resolve.mutateAsync({\n id: esc.id,\n resolverPayload: interpolatePayload(action.resolverPayload, rowCtx) as Record<string, unknown>,\n });\n } catch (err) {\n setRowErrors((prev) => ({ ...prev, [esc.id]: (err as Error).message }));\n } finally {\n setPendingRow(null);\n }\n };\n\n return (\n <div data-field-key={fieldKey}>\n <FieldLabel>{label}</FieldLabel>\n {helperText && <FieldHelper>{helperText}</FieldHelper>}\n <div className=\"mt-1\" data-testid={`escalation-list-widget-${fieldKey}`}>\n {isLoading ? (\n <ListSkeleton columns={columns.length} />\n ) : (\n <EmbedTable\n escalations={escalations}\n columns={columns}\n fieldKey={fieldKey}\n actions={actions}\n onAction={fireAction}\n pendingRow={pendingRow}\n rowErrors={rowErrors}\n />\n )}\n </div>\n </div>\n );\n}\n\nfunction EmbedTable({\n escalations,\n columns,\n fieldKey,\n actions,\n onAction,\n pendingRow,\n rowErrors,\n}: {\n escalations: LTEscalationRecord[];\n columns: ColumnDef[];\n fieldKey: string;\n actions: ActionDef[];\n onAction: (esc: LTEscalationRecord, action: ActionDef) => void;\n pendingRow: string | null;\n rowErrors: Record<string, string>;\n}) {\n if (escalations.length === 0) {\n return (\n <p className=\"text-xs text-text-quaternary italic py-1\" data-testid={`escalation-list-empty-${fieldKey}`}>\n No items found\n </p>\n );\n }\n\n return (\n <table className=\"w-full text-xs border-collapse\" data-testid={`escalation-list-table-${fieldKey}`}>\n <thead>\n <tr className=\"border-b border-surface-border\">\n {columns.map((col) => (\n <th\n key={col.label}\n className=\"text-left text-2xs font-semibold uppercase tracking-wider text-text-tertiary pb-1 pr-3 last:pr-0\"\n >\n {col.label}\n </th>\n ))}\n {actions.length > 0 && <th className=\"w-px\" />}\n <th className=\"w-8\" />\n </tr>\n </thead>\n <tbody>\n {escalations.map((esc) => {\n const ctx = rowContext(esc);\n const error = rowErrors[esc.id];\n return (\n <tr\n key={esc.id}\n className=\"border-b border-surface-border/50 last:border-0 hover:bg-surface-sunken/50 transition-colors\"\n >\n {columns.map((col) => {\n const raw = interpolateHelp(col.value, ctx);\n const display = renderValue(raw, col.format);\n return (\n <td key={col.label} className=\"py-1 pr-3 last:pr-0 text-text-primary align-top\">\n {display}\n </td>\n );\n })}\n {actions.length > 0 && (\n <td className=\"py-1 pr-2 align-top whitespace-nowrap\">\n {actions.map((action) => (\n <button\n key={action.label}\n type=\"button\"\n onClick={() => onAction(esc, action)}\n disabled={pendingRow === esc.id}\n className=\"px-2 py-0.5 text-2xs font-medium text-accent border border-accent/40 rounded hover:bg-accent/10 disabled:opacity-40 disabled:cursor-default transition-colors ml-1 first:ml-0\"\n data-testid={`escalation-list-action-${esc.id}`}\n >\n {action.label}\n </button>\n ))}\n {error && (\n <p className=\"text-2xs text-status-error mt-0.5 whitespace-normal max-w-[16rem]\" data-testid={`escalation-list-action-error-${esc.id}`}>\n {error}\n </p>\n )}\n </td>\n )}\n <td className=\"py-1 pl-2 align-top\">\n <OpenDetailButton to={`/escalations/detail/${esc.id}`} />\n </td>\n </tr>\n );\n })}\n </tbody>\n </table>\n );\n}\n\nfunction ListSkeleton({ columns }: { columns: number }) {\n return (\n <div className=\"space-y-1.5 animate-pulse\">\n {[0, 1, 2].map((i) => (\n <div key={i} className=\"flex gap-4\">\n {Array.from({ length: columns }, (_, j) => (\n <div key={j} className=\"h-3 bg-surface-sunken rounded flex-1\" />\n ))}\n </div>\n ))}\n </div>\n );\n}\n","import type { ComponentType } from 'react';\nimport { FileUploadWidget } from './FileUploadWidget';\nimport { CodeEditorWidget } from './CodeEditorWidget';\nimport { SignatureWidget } from './SignatureWidget';\nimport { RichTextWidget } from './RichTextWidget';\nimport { MarkdownWidget } from './MarkdownWidget';\nimport { ChecklistWidget } from './ChecklistWidget';\nimport { AttachmentWidget } from './AttachmentWidget';\nimport { LinkWidget } from './LinkWidget';\nimport { EscalationWidget } from './EscalationWidget';\nimport { EscalationListWidget } from './EscalationListWidget';\nimport type { ShowIfContext } from '../../../lib/x-lt-show-if';\n\nexport interface WidgetProps {\n fieldKey: string;\n value: string;\n onChange: (v: string) => void;\n schema?: Record<string, unknown>;\n /** Escalation context — used by widgets that read from envelope/metadata/payload at render time. */\n escalationContext?: ShowIfContext;\n /** Whether this field is listed in the schema's required array. */\n isRequired?: boolean;\n /** Whether the user has attempted to submit — triggers required/validation display in widgets. */\n submitAttempted?: boolean;\n /** Validation error to display inside the widget. */\n error?: string;\n}\n\n/**\n * Registry of custom widgets referenced via `x-lt-widget` in JSON Schema.\n * String-typed fields receive value directly; object-typed fields are\n * JSON-serialized into the widget and parsed back on change (see FieldRow).\n */\nexport const WIDGET_MAP: Record<string, ComponentType<WidgetProps>> = {\n 'file-upload': FileUploadWidget,\n 'code-editor': CodeEditorWidget,\n 'signature': SignatureWidget,\n 'rich-text': RichTextWidget,\n 'markdown': MarkdownWidget,\n 'checklist': ChecklistWidget,\n // Attachment renders a captured binary (data URL / fetchable URL): images\n // inline, everything else as a safe open/download link. \"image\" is an alias\n // so schemas can name the constrained intent.\n 'attachment': AttachmentWidget,\n 'image': AttachmentWidget,\n // Embed and navigation — display-only; produce no resolver payload.\n 'link': LinkWidget,\n 'escalation': EscalationWidget,\n 'escalation-list': EscalationListWidget,\n};\n","import { WIDGET_MAP } from '../widgets';\nimport { type ShowIfContext } from '../../../lib/x-lt-show-if';\nimport { resolveFieldOptions } from '../../../lib/x-lt-options';\nimport { deriveFieldLabel } from '../../../lib/derive-field-label';\nimport { FieldLabel, FieldHelper, FieldError, inputClass, selectClass } from './FieldChrome';\nimport { type JsonValue } from './form-cells';\n\n/**\n * Field row — renders the appropriate input per JSON type and schema hints.\n * The `data-field-key` attribute and `lt-field-*` ids are load-bearing: the\n * errors panel scroll-and-focus and the test suite target them.\n */\nexport function FieldRow({ fieldKey, value, onChange, onBlur, schema, isRequired, isReadOnly, error, escalationContext, submitAttempted }: {\n fieldKey: string;\n value: JsonValue;\n onChange: (v: JsonValue) => void;\n onBlur?: () => void;\n schema?: Record<string, any> | null;\n isRequired?: boolean;\n isReadOnly?: boolean;\n error?: string;\n escalationContext?: ShowIfContext;\n submitAttempted?: boolean;\n}) {\n const fieldSchema = schema?.properties?.[fieldKey] as Record<string, any> | undefined;\n const label = deriveFieldLabel(fieldKey, fieldSchema);\n const widgetName = fieldSchema?.['x-lt-widget'] as string | undefined;\n\n // Accessible wiring shared by every input branch: explicit label-for-input\n // association, and error/helper text linked via aria-describedby.\n const fieldId = `lt-field-${fieldKey}`;\n const errorId = `${fieldId}-error`;\n const helpId = `${fieldId}-help`;\n // The instruction line renders on EVERY editable input, in one fixed\n // anatomy: label, instruction, control. No input goes without.\n const helperText = typeof fieldSchema?.description === 'string' && fieldSchema.description.length > 0\n ? fieldSchema.description\n : undefined;\n const hasHelper = helperText !== undefined;\n const describedBy = error ? errorId : hasHelper ? helpId : undefined;\n const ariaProps = {\n id: fieldId,\n 'aria-required': isRequired || undefined,\n 'aria-invalid': error ? true : undefined,\n 'aria-describedby': describedBy,\n } as const;\n\n // Some widgets dispatch ahead of the read-only branch: a readOnly markdown\n // field is a CONTENT BLOCK (renders its source as HTML), a readOnly\n // attachment/image renders the captured binary, and embed widgets (link,\n // escalation, escalation-list) render their own display — never static text.\n const isMarkdown = widgetName === 'markdown' && typeof value === 'string';\n const isAttachment = (widgetName === 'attachment' || widgetName === 'image') && typeof value === 'string';\n const hasRegisteredWidget = !!(widgetName && widgetName in WIDGET_MAP);\n\n // Read-only fields display as static text, unless a widget handles the rendering.\n if (isReadOnly && !isMarkdown && !isAttachment && !hasRegisteredWidget) {\n const displayValue = value === null ? 'null'\n : typeof value === 'object' ? JSON.stringify(value, null, 2)\n : String(value);\n return (\n <div>\n <FieldLabel isRequired={isRequired}>{label}</FieldLabel>\n <p className=\"text-sm text-text-secondary mt-0.5 whitespace-pre-wrap\">{displayValue}</p>\n </div>\n );\n }\n\n // Custom widget via x-lt-widget.\n // The widget interface always deals in strings; FieldRow owns the\n // object ↔ string boundary, decided by the DECLARED type — never the\n // runtime value. An object-typed field (checklist) stores an object in\n // the form data on every change, so a stray string value (an old draft,\n // an empty init) heals on the next interaction instead of sticking.\n if (widgetName && widgetName in WIDGET_MAP) {\n const Widget = WIDGET_MAP[widgetName];\n // A require-all checklist is required by definition — its label carries\n // the asterisk like any other required input.\n const widgetRequired = isRequired || fieldSchema?.['x-lt-require-all'] === true;\n const widgetProps = { fieldKey, schema: fieldSchema, escalationContext, isRequired: widgetRequired, submitAttempted, error };\n if (fieldSchema?.type === 'object') {\n const raw = typeof value === 'string'\n ? value\n : typeof value === 'object' && value !== null && !Array.isArray(value)\n ? JSON.stringify(value)\n : '';\n return (\n <Widget\n {...widgetProps}\n value={raw}\n onChange={(next) => { try { onChange(JSON.parse(next) as JsonValue); } catch { onChange(next); } }}\n />\n );\n }\n if (typeof value === 'string') {\n return <Widget {...widgetProps} value={value} onChange={(v) => onChange(v)} />;\n }\n if (typeof value === 'object' && value !== null && !Array.isArray(value)) {\n return (\n <Widget\n {...widgetProps}\n value={JSON.stringify(value)}\n onChange={(raw) => { try { onChange(JSON.parse(raw) as JsonValue); } catch { onChange(raw); } }}\n />\n );\n }\n }\n\n // Select — the option list is the schema's static enum, or the x-lt-options\n // list resolved from the escalation context (one static role form, per-row\n // legal options). Dispatched by SCHEMA, not runtime value: a number-typed\n // count seeded to its 0 default must render as a select, not a number input.\n // An interpolated list that resolves to nothing yet (a cascade child whose\n // parent is unanswered) renders as a DISABLED select — it enables and\n // populates the moment the parent answer lands.\n const selectOptions = resolveFieldOptions(fieldSchema, escalationContext as Record<string, unknown> | undefined);\n if (selectOptions && (value === null || typeof value === 'string' || typeof value === 'number')) {\n const current = value === null ? '' : String(value);\n // A value outside the option list (empty init, stale draft, options that\n // shrank per-row) renders an explicit disabled \"Choose…\" placeholder: the\n // decision is the user's, never an implicit first option. Once chosen\n // there is no way back to unchosen.\n const hasCurrent = selectOptions.some((opt) => String(opt.value) === current);\n return (\n <div>\n <FieldLabel isRequired={isRequired} htmlFor={fieldId}>{label}</FieldLabel>\n {helperText && <FieldHelper id={helpId}>{helperText}</FieldHelper>}\n <select\n value={hasCurrent ? current : ''}\n disabled={selectOptions.length === 0}\n onChange={(e) => {\n // The submitted answer is the option VALUE (labels are\n // presentation), emitted with its own type so a numeric option\n // stays a number.\n const picked = selectOptions.find((opt) => String(opt.value) === e.target.value);\n onChange(picked ? picked.value : e.target.value);\n }}\n onBlur={onBlur}\n data-field-key={fieldKey}\n className={selectClass(!!error)}\n {...ariaProps}\n >\n {!hasCurrent && <option value=\"\" disabled>Choose…</option>}\n {selectOptions.map((opt) => (\n <option key={String(opt.value)} value={String(opt.value)}>{opt.label}</option>\n ))}\n </select>\n <FieldError error={error} id={errorId} />\n </div>\n );\n }\n\n // Boolean → checkbox\n if (typeof value === 'boolean') {\n return (\n <div>\n <label className=\"flex items-center gap-2 cursor-pointer\">\n <input\n type=\"checkbox\"\n checked={value}\n onChange={(e) => { onChange(e.target.checked); onBlur?.(); }}\n className=\"w-3.5 h-3.5 rounded accent-accent\"\n data-field-key={fieldKey}\n {...ariaProps}\n />\n <span className=\"text-2xs font-semibold uppercase tracking-wider text-text-secondary\">\n {label}\n {isRequired && <span className=\"text-status-error ml-0.5\">*</span>}\n </span>\n </label>\n {helperText && <FieldHelper id={helpId}>{helperText}</FieldHelper>}\n <FieldError error={error} id={errorId} />\n </div>\n );\n }\n\n // Number — numbers are short; the input holds a hand-sized width instead\n // of stretching to the measure.\n if (typeof value === 'number') {\n return (\n <div>\n <FieldLabel isRequired={isRequired} htmlFor={fieldId}>{label}</FieldLabel>\n {helperText && <FieldHelper id={helpId}>{helperText}</FieldHelper>}\n <input\n type=\"number\"\n value={value}\n onChange={(e) => onChange(parseFloat(e.target.value) || 0)}\n onBlur={onBlur}\n step=\"any\"\n data-field-key={fieldKey}\n className={`${inputClass(!!error)} max-w-48`}\n {...ariaProps}\n />\n <FieldError error={error} id={errorId} />\n </div>\n );\n }\n\n // String\n if (typeof value === 'string') {\n const isPassword = fieldSchema?.format === 'password';\n\n if (isPassword) {\n return (\n <div>\n <FieldLabel isRequired={isRequired} htmlFor={fieldId}>{label}</FieldLabel>\n {helperText && <FieldHelper id={helpId}>{helperText}</FieldHelper>}\n <input\n type=\"password\"\n value={value}\n onChange={(e) => onChange(e.target.value)}\n onBlur={onBlur}\n data-field-key={fieldKey}\n className={inputClass(!!error)}\n autoComplete=\"off\"\n {...ariaProps}\n />\n <FieldError error={error} id={errorId} />\n </div>\n );\n }\n\n // Format-based input types. Width follows the content the format expects:\n // emails and urls are prose-length and fill the cell; dates are fixed-\n // length values and hold a hand-sized width, like numbers.\n const format = fieldSchema?.format as string | undefined;\n const FORMAT_INPUT_TYPES: Record<string, string> = {\n date: 'date',\n 'date-time': 'datetime-local',\n email: 'email',\n uri: 'url',\n };\n const FORMAT_WIDTH: Record<string, string> = {\n date: 'max-w-48',\n 'date-time': 'max-w-64',\n };\n if (format && format in FORMAT_INPUT_TYPES) {\n return (\n <div>\n <FieldLabel isRequired={isRequired} htmlFor={fieldId}>{label}</FieldLabel>\n {helperText && <FieldHelper id={helpId}>{helperText}</FieldHelper>}\n <input\n type={FORMAT_INPUT_TYPES[format]}\n value={value}\n onChange={(e) => onChange(e.target.value)}\n onBlur={onBlur}\n data-field-key={fieldKey}\n className={`${inputClass(!!error)} ${FORMAT_WIDTH[format] ?? ''}`}\n {...ariaProps}\n />\n <FieldError error={error} id={errorId} />\n </div>\n );\n }\n\n // Explicit textarea format or long content\n if (format === 'textarea' || value.length > 80) {\n // Resolve effective maxLength for live counter — static schema wins, then dynamic path\n const staticMax = fieldSchema?.maxLength as number | undefined;\n const dynamicMaxPath = fieldSchema?.['x-lt-max-length'] as string | undefined;\n let resolvedMax: number | undefined = staticMax;\n if (resolvedMax === undefined && dynamicMaxPath && escalationContext) {\n const dot = dynamicMaxPath.indexOf('.');\n if (dot !== -1) {\n const domain = dynamicMaxPath.slice(0, dot);\n const path = dynamicMaxPath.slice(dot + 1);\n const domainObj = (escalationContext as Record<string, unknown>)[domain];\n if (domainObj && typeof domainObj === 'object') {\n let cur: unknown = domainObj;\n for (const p of path.split('.')) {\n cur = (cur as Record<string, unknown>)[p];\n if (cur === undefined) break;\n }\n if (typeof cur === 'number') resolvedMax = cur;\n else if (typeof cur === 'string') { const n = Number(cur); if (!Number.isNaN(n)) resolvedMax = n; }\n }\n }\n }\n const isOverMax = resolvedMax !== undefined && value.length > resolvedMax;\n\n return (\n <div>\n <FieldLabel isRequired={isRequired} htmlFor={fieldId}>{label}</FieldLabel>\n {helperText && <FieldHelper id={helpId}>{helperText}</FieldHelper>}\n <textarea\n value={value}\n onChange={(e) => { onChange(e.target.value); onBlur?.(); }}\n onBlur={onBlur}\n data-field-key={fieldKey}\n className={`${inputClass(!!error)} leading-relaxed`}\n rows={Math.min(6, Math.max(3, Math.ceil(value.length / 60)))}\n {...ariaProps}\n />\n {resolvedMax !== undefined && (\n <p className={`text-2xs mt-0.5 text-right tabular-nums ${isOverMax ? 'text-status-error font-medium' : 'text-text-quaternary'}`}>\n {value.length} / {resolvedMax}\n </p>\n )}\n <FieldError error={error} id={errorId} />\n </div>\n );\n }\n\n return (\n <div>\n <FieldLabel isRequired={isRequired} htmlFor={fieldId}>{label}</FieldLabel>\n {helperText && <FieldHelper id={helpId}>{helperText}</FieldHelper>}\n <input\n type=\"text\"\n value={value}\n onChange={(e) => onChange(e.target.value)}\n onBlur={onBlur}\n data-field-key={fieldKey}\n className={inputClass(!!error)}\n {...ariaProps}\n />\n <FieldError error={error} id={errorId} />\n </div>\n );\n }\n\n // Null\n if (value === null) {\n return (\n <div>\n <FieldLabel isRequired={isRequired}>{label}</FieldLabel>\n <p className=\"text-xs text-text-tertiary italic mt-1\">null</p>\n </div>\n );\n }\n\n // Array of primitives\n if (Array.isArray(value)) {\n return (\n <div>\n <FieldLabel isRequired={isRequired}>{label}</FieldLabel>\n <div className=\"flex flex-wrap gap-1.5 mt-1\">\n {value.map((item, i) => (\n <span\n key={i}\n className=\"px-2 py-0.5 text-2xs font-mono bg-surface-sunken rounded text-text-secondary\"\n >\n {String(item)}\n </span>\n ))}\n </div>\n </div>\n );\n }\n\n // Nested object → recursive\n if (typeof value === 'object') {\n const entries = Object.entries(value);\n return (\n <div>\n <FieldLabel isRequired={isRequired}>{label}</FieldLabel>\n <div className=\"ml-4 mt-2 pl-4 border-l border-accent-faint space-y-3\">\n {entries.map(([k, v]) => (\n <FieldRow\n key={k}\n fieldKey={k}\n value={v}\n onChange={(updated) => onChange({ ...value, [k]: updated })}\n />\n ))}\n </div>\n </div>\n );\n }\n\n return null;\n}\n","import { Fragment } from 'react';\nimport { type JsonValue } from './form-cells';\n\nexport interface DictionaryItem {\n key: string;\n label: string;\n value: JsonValue;\n}\n\n/**\n * Dense definition-list display for read-only label/value facts — the compact\n * alternative to full-height field rows. Labels sit beside values in a\n * max-content column so a run of short facts reads like a spec sheet, not a\n * form.\n *\n * The poster child of the responsive doctrine: geometry follows the\n * CONTAINER. The same pairs render as two pairs per row (≥ @dict-pairs),\n * one label|value pair per row (≥ @dict-inline), or label stacked over\n * value below that — however narrow a side panel squeezes the form.\n * Two-column mode fills ROW BY ROW, so the author's ordering controls\n * pairing (Left Qty beside Right Qty, Left first) in every geometry.\n */\nexport function DictionaryList({ items, columns = 1 }: {\n items: DictionaryItem[];\n columns?: number;\n}) {\n if (items.length === 0) return null;\n\n const gridCols = columns >= 2 && items.length > 1\n ? 'grid-cols-1 @dict-inline:grid-cols-[max-content_1fr] @dict-pairs:grid-cols-[max-content_1fr_max-content_1fr]'\n : 'grid-cols-1 @dict-inline:grid-cols-[max-content_1fr]';\n\n return (\n <div className=\"@container\">\n <dl className={`grid ${gridCols} items-baseline gap-x-6 @dict-pairs:gap-x-8 gap-y-1.5`}>\n {items.map(({ key, label, value }) => (\n <Fragment key={key}>\n {/* Stacked geometry clusters each label with its value. */}\n <dt className=\"text-2xs font-semibold uppercase tracking-wide text-text-secondary mt-2 first:mt-0 @dict-inline:mt-0\">\n {label}\n </dt>\n <dd className=\"text-sm text-text-primary break-words min-w-0\" data-field-key={key}>\n {formatDictionaryValue(value)}\n </dd>\n </Fragment>\n ))}\n </dl>\n </div>\n );\n}\n\nfunction formatDictionaryValue(value: JsonValue): string {\n if (value === null || value === undefined || value === '') return '—';\n if (typeof value === 'boolean') return value ? 'Yes' : 'No';\n if (typeof value === 'object') return JSON.stringify(value);\n return String(value);\n}\n","/**\n * Layout cell partitioning for the schema-driven resolver form.\n *\n * A section's fields render as a sequence of cells:\n * - `dictionary` — consecutive read-only facts merged into one dense\n * definition list (`x-lt-display: \"dictionary\"` at field, section, or\n * schema level)\n * - `column-group` — consecutive fields sharing an `x-lt-column-group` name,\n * rendered as an inner two-column grid inside one cell of a two-column\n * layout (the 2×2 nesting level)\n * - `field` — everything else, one input per cell\n */\n\nexport type JsonValue =\n | string\n | number\n | boolean\n | null\n | JsonValue[]\n | { [key: string]: JsonValue };\n\nexport type FormEntry = [string, JsonValue];\n\nexport interface SectionOptions {\n display?: string;\n columns?: number;\n}\n\nexport type FormCell =\n | { kind: 'field'; entry: FormEntry }\n | { kind: 'dictionary'; entries: FormEntry[] }\n | { kind: 'column-group'; name: string; entries: FormEntry[] };\n\nconst DICTIONARY = 'dictionary';\n\n/** Widgets that render content blocks even when readOnly — never dictionary rows. */\nconst CONTENT_WIDGETS = new Set(['markdown', 'attachment', 'image']);\n\nexport function sectionOptionsFor(\n formSchema: Record<string, any> | null | undefined,\n sectionName: string | null,\n): SectionOptions | undefined {\n if (!sectionName) return undefined;\n const all = formSchema?.['x-lt-section-options'] as Record<string, SectionOptions> | undefined;\n const opts = all?.[sectionName];\n return opts && typeof opts === 'object' ? opts : undefined;\n}\n\n/**\n * A field renders as a dictionary row when it is read-only, is not a content\n * widget, and dictionary display is requested at the nearest level:\n * field `x-lt-display` > section options > schema-root `x-lt-display`.\n */\nexport function isDictionaryField(\n formSchema: Record<string, any> | null | undefined,\n sectionName: string | null,\n key: string,\n): boolean {\n const fieldSchema = formSchema?.properties?.[key] as Record<string, unknown> | undefined;\n if (fieldSchema?.readOnly !== true) return false;\n const widget = fieldSchema?.['x-lt-widget'];\n if (typeof widget === 'string' && CONTENT_WIDGETS.has(widget)) return false;\n\n const fieldDisplay = fieldSchema?.['x-lt-display'];\n if (typeof fieldDisplay === 'string') return fieldDisplay === DICTIONARY;\n const sectionDisplay = sectionOptionsFor(formSchema, sectionName)?.display;\n if (typeof sectionDisplay === 'string') return sectionDisplay === DICTIONARY;\n return formSchema?.['x-lt-display'] === DICTIONARY;\n}\n\nexport function partitionCells(\n entries: FormEntry[],\n formSchema: Record<string, any> | null | undefined,\n sectionName: string | null,\n layout: string | undefined,\n): FormCell[] {\n const cells: FormCell[] = [];\n for (const entry of entries) {\n const [key] = entry;\n const last = cells[cells.length - 1];\n\n if (isDictionaryField(formSchema, sectionName, key)) {\n if (last?.kind === 'dictionary') {\n last.entries.push(entry);\n } else {\n cells.push({ kind: 'dictionary', entries: [entry] });\n }\n continue;\n }\n\n const fieldSchema = formSchema?.properties?.[key] as Record<string, unknown> | undefined;\n const groupName = fieldSchema?.['x-lt-column-group'];\n if (layout === 'two-column' && typeof groupName === 'string' && groupName.trim()) {\n if (last?.kind === 'column-group' && last.name === groupName) {\n last.entries.push(entry);\n } else {\n cells.push({ kind: 'column-group', name: groupName, entries: [entry] });\n }\n continue;\n }\n\n cells.push({ kind: 'field', entry });\n }\n return cells;\n}\n","import { type ReactNode } from 'react';\nimport { deriveFieldLabel } from '../../../lib/derive-field-label';\nimport { DictionaryList } from './DictionaryList';\nimport {\n partitionCells,\n sectionOptionsFor,\n type FormEntry,\n type JsonValue,\n} from './form-cells';\n\n/**\n * One visual section of the resolver form: optional named chrome (accent rule,\n * sunken band, section header), then the section's fields laid out as cells —\n * dictionary runs, 2×2 column groups, and single fields.\n */\nexport function SectionGroup({ name, entries, formSchema, layout, renderField }: {\n name: string | null;\n entries: FormEntry[];\n formSchema: Record<string, any> | null;\n layout: string | undefined;\n renderField: (entry: FormEntry) => ReactNode;\n}) {\n const cells = partitionCells(entries, formSchema, name, layout);\n const options = sectionOptionsFor(formSchema, name);\n const dictionaryColumns = options?.columns ?? (layout === 'two-column' ? 2 : 1);\n\n const dictionaryItems = (dictEntries: FormEntry[]) =>\n dictEntries.map(([key, value]: [string, JsonValue]) => ({\n key,\n label: deriveFieldLabel(key, formSchema?.properties?.[key] as Record<string, unknown> | undefined),\n value,\n }));\n\n const renderCells = () =>\n cells.map((cell, i) => {\n if (cell.kind === 'dictionary') {\n return (\n <div key={`dict-${i}`} className={layout === 'two-column' ? 'col-span-full' : ''}>\n <DictionaryList items={dictionaryItems(cell.entries)} columns={dictionaryColumns} />\n </div>\n );\n }\n if (cell.kind === 'column-group') {\n // One cell of the outer two-column grid holding its own two columns —\n // the single extra nesting level (2×2). The cell is its own container:\n // it measures the half-width it actually gets, not the section.\n return (\n <div key={`group-${cell.name}-${i}`} className=\"@container\">\n <div className=\"grid grid-cols-1 @grp-cols:grid-cols-2 gap-x-4 gap-y-5\">\n {cell.entries.map((entry) => renderField(entry))}\n </div>\n </div>\n );\n }\n return renderField(cell.entry);\n });\n\n return (\n <div\n className={name\n // Sections are distinct surfaces on the page wash — white paper in\n // light themes, the deeper well at night — with field wells stepping\n // away from them. Theme-driven, never a hardcoded hex.\n ? 'border border-surface-border bg-surface-sunken rounded-[var(--lt-radius-section)] p-4 animate-[section-enter_0.25s_ease-out]'\n : ''}\n >\n {name && (\n <p className=\"mb-4 text-[1.40625rem] font-semibold tracking-wider text-heading [font-variant-caps:small-caps]\">\n {name}\n </p>\n )}\n {layout === 'two-column' ? (\n // Geometry follows the container: the grid splits when the SECTION\n // is wide enough, whatever the viewport says.\n <div className=\"@container\">\n <div className=\"grid grid-cols-1 @form-cols:grid-cols-2 gap-x-col-gap gap-y-5\">\n {renderCells()}\n </div>\n </div>\n ) : (\n <div className=\"space-y-5\">\n {renderCells()}\n </div>\n )}\n </div>\n );\n}\n","import { useState, useEffect, useCallback, type ReactNode } from 'react';\nimport { LockedFormFrame } from './LockedFormFrame';\nimport { HelpCircle } from 'lucide-react';\nimport { evaluateShowIf, type ShowIfContext } from '../../../lib/x-lt-show-if';\nimport { validateField } from '../../../lib/field-validator';\nimport { FieldRow } from './FieldRow';\nimport { SectionGroup } from './SectionGroup';\nimport { type FormEntry, type JsonValue } from './form-cells';\n\n/**\n * Renders a JSON object as an editable form with typed inputs.\n *\n * - Strings → text input (textarea if > 80 chars)\n * - Booleans → toggle switch\n * - Numbers → number input\n * - Null → disabled placeholder\n * - Objects → nested section\n * - Arrays of strings → tag display\n * - Keys starting with `_` → hidden (preserved in output)\n *\n * Calls `onChange` with the full JSON string on every edit.\n */\nexport function ResolverForm({ value, onChange, disabled, submitAttempted, escalationContext, onOpenHelp, onDisabledClick, disabledHint }: {\n value: string;\n onChange: (json: string) => void;\n disabled?: boolean;\n submitAttempted?: boolean;\n escalationContext?: ShowIfContext;\n /** Opens the Instructions panel view; renders a help icon when the schema carries authored help. */\n onOpenHelp?: () => void;\n /** Fires when the user clicks the locked form — the page points them at Claim. */\n onDisabledClick?: () => void;\n /** Cursor-following hint over the locked form naming the state or gesture. */\n disabledHint?: ReactNode;\n}) {\n const [data, setData] = useState<Record<string, JsonValue>>({});\n const [hidden, setHidden] = useState<Record<string, JsonValue>>({});\n const [formSchema, setFormSchema] = useState<Record<string, any> | null>(null);\n const [parseError, setParseError] = useState(false);\n const [touched, setTouched] = useState<Set<string>>(new Set());\n\n // Parse incoming JSON\n useEffect(() => {\n try {\n const parsed = JSON.parse(value);\n if (typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed)) {\n const visible: Record<string, JsonValue> = {};\n const internal: Record<string, JsonValue> = {};\n for (const [k, v] of Object.entries(parsed)) {\n if (k.startsWith('_')) {\n internal[k] = v as JsonValue;\n } else {\n visible[k] = v as JsonValue;\n }\n }\n setData(visible);\n setHidden(internal);\n setFormSchema(\n internal._form_schema && typeof internal._form_schema === 'object'\n ? internal._form_schema as Record<string, any>\n : null,\n );\n setParseError(false);\n }\n } catch {\n setParseError(true);\n }\n }, [value]);\n\n const emitChange = useCallback((updated: Record<string, JsonValue>) => {\n setData(updated);\n onChange(JSON.stringify({ ...updated, ...hidden }, null, 2));\n }, [hidden, onChange]);\n\n const updateField = useCallback((key: string, val: JsonValue) => {\n emitChange({ ...data, [key]: val });\n }, [data, emitChange]);\n\n const markTouched = useCallback((key: string) => {\n setTouched((prev) => {\n if (prev.has(key)) return prev;\n const next = new Set(prev);\n next.add(key);\n return next;\n });\n }, []);\n\n if (parseError) {\n return (\n <p className=\"text-xs text-status-error\">\n Unable to parse resolver data as form. Use the JSON editor below.\n </p>\n );\n }\n\n const allEntries = Object.entries(data);\n if (allEntries.length === 0) {\n return (\n <p className=\"text-xs text-text-tertiary italic\">\n No resolver fields defined.\n </p>\n );\n }\n\n // Field ordering via x-lt-order\n const fieldOrder = formSchema?.['x-lt-order'] as string[] | undefined;\n const ordered = fieldOrder\n ? [...allEntries].sort((a, b) => {\n const ai = fieldOrder.indexOf(a[0]);\n const bi = fieldOrder.indexOf(b[0]);\n return (ai === -1 ? Infinity : ai) - (bi === -1 ? Infinity : bi);\n })\n : allEntries;\n\n // Merge current form data into the resolver domain so x-lt-showIf: 'resolver.field'\n // reacts to live edits — the parent context only carries the saved row state.\n const liveCtx: ShowIfContext = { ...(escalationContext ?? {}), resolver: data as Record<string, unknown> };\n\n // Conditional visibility via x-lt-showIf and x-lt-hide-if-empty\n const entries = ordered.filter(([key, val]) => {\n const fieldSchema = formSchema?.properties?.[key] as Record<string, unknown> | undefined;\n if (!evaluateShowIf(fieldSchema?.['x-lt-showIf'], liveCtx)) return false;\n if (fieldSchema?.['x-lt-hide-if-empty'] === true) {\n const isEmpty = val === null || val === undefined || val === '' || val === false || val === 0;\n if (isEmpty) return false;\n }\n return true;\n });\n\n const requiredFields = new Set(formSchema?.required as string[] ?? []);\n const layout = formSchema?.['x-lt-layout'] as string | undefined;\n const schemaTitle = formSchema?.title as string | undefined;\n const schemaDescription = formSchema?.description as string | undefined;\n const hasAuthoredHelp =\n typeof formSchema?.['x-lt-help'] === 'string' || typeof formSchema?.['x-lt-context'] === 'string';\n\n // Group entries by x-lt-section for labeled visual grouping.\n // Fields without x-lt-section or with an empty value form an unnamed group.\n type Section = { name: string | null; entries: FormEntry[] };\n const sectionGroups: Section[] = [];\n for (const entry of entries) {\n const [key] = entry;\n const fieldSchema = formSchema?.properties?.[key] as Record<string, unknown> | undefined;\n const sectionName = (fieldSchema?.['x-lt-section'] as string | undefined)?.trim() || null;\n const last = sectionGroups[sectionGroups.length - 1];\n if (!last || last.name !== sectionName) {\n sectionGroups.push({ name: sectionName, entries: [entry] });\n } else {\n last.entries.push(entry);\n }\n }\n\n const renderField = ([key, val]: FormEntry) => {\n const fieldSchema = formSchema?.properties?.[key] as Record<string, unknown> | undefined;\n const isReadOnly = fieldSchema?.readOnly === true;\n const span = (fieldSchema?.['x-lt-span'] as number) ?? 1;\n const isReq = requiredFields.has(key);\n const isTouched = touched.has(key) || !!submitAttempted;\n\n const error = validateField(val, fieldSchema, isReq, isTouched, liveCtx as Record<string, unknown>);\n\n return (\n <div\n key={key}\n className={`animate-[field-enter_0.2s_ease-out] ${layout === 'two-column' && span >= 2 ? 'col-span-full' : ''}`}\n >\n <FieldRow\n fieldKey={key}\n value={val}\n onChange={(v) => updateField(key, v)}\n onBlur={() => markTouched(key)}\n schema={formSchema}\n isRequired={isReq}\n isReadOnly={isReadOnly}\n error={error}\n escalationContext={liveCtx}\n submitAttempted={!!submitAttempted}\n />\n </div>\n );\n };\n\n // A locked form stays fully readable — no fade. `inert` (not just\n // pointer-events) locks the body for keyboard and assistive-tech users —\n // fields leave the tab order entirely — and makes it transparent to hit\n // testing, so a click anywhere on the locked form lands on the frame,\n // which reports the interaction and carries the cursor hint.\n // max-w-form: the form holds a readable measure on any monitor.\n const body = (\n <div\n className={disabled ? 'pointer-events-none' : undefined}\n inert={disabled || undefined}\n aria-disabled={disabled || undefined}\n >\n {schemaTitle && (\n <div className=\"mb-1 flex items-center gap-1.5\">\n <h3 className=\"heading-3\">{schemaTitle}</h3>\n {hasAuthoredHelp && onOpenHelp && (\n <button\n type=\"button\"\n onClick={onOpenHelp}\n title=\"Open instructions\"\n aria-label=\"Open instructions\"\n className=\"p-1 rounded-md text-text-tertiary hover:text-accent hover:bg-surface-hover transition-colors\"\n >\n <HelpCircle className=\"w-4 h-4\" strokeWidth={1.5} />\n </button>\n )}\n </div>\n )}\n {schemaDescription && (\n <p className=\"text-sm text-text-secondary leading-relaxed mb-6\">{schemaDescription}</p>\n )}\n\n <div className=\"space-y-8\">\n {sectionGroups.map((group, i) => (\n <SectionGroup\n key={group.name ?? `__s${i}`}\n name={group.name}\n entries={group.entries}\n formSchema={formSchema}\n layout={layout}\n renderField={renderField}\n />\n ))}\n </div>\n </div>\n );\n\n if (disabled) {\n return (\n <LockedFormFrame hint={disabledHint} onLockedClick={onDisabledClick}>\n {body}\n </LockedFormFrame>\n );\n }\n return <div className=\"pb-8 max-w-form\">{body}</div>;\n}\n","import { ResolverForm } from '../../../components/escalation/ResolverForm';\nimport type { ShowIfContext } from '../../../lib/x-lt-show-if';\n\nexport function ResolverSection({\n json,\n onJsonChange,\n requestTriage,\n onRequestTriageChange,\n triageNotes,\n onTriageNotesChange,\n disabled = false,\n submitAttempted = false,\n showTriage = false,\n escalationContext,\n onOpenHelp,\n onDisabledClick,\n disabledHint,\n}: {\n json: string;\n onJsonChange: (v: string) => void;\n requestTriage: boolean;\n onRequestTriageChange: (v: boolean) => void;\n triageNotes: string;\n onTriageNotesChange: (v: string) => void;\n disabled?: boolean;\n submitAttempted?: boolean;\n showTriage?: boolean;\n escalationContext?: ShowIfContext;\n /** Opens the Instructions side-panel view (help icon beside the form title). */\n onOpenHelp?: () => void;\n /** Fires when the user clicks the locked (unclaimed) form. */\n onDisabledClick?: () => void;\n /** Cursor-following hint over the locked form. */\n disabledHint?: React.ReactNode;\n}) {\n return (\n <>\n {/* Triage callout */}\n {showTriage && (\n <div className=\"flex items-center justify-between mb-3\">\n {requestTriage ? (\n <button\n onClick={() => onRequestTriageChange(false)}\n className=\"group flex items-center gap-2 text-left\"\n data-testid=\"triage-cancel\"\n >\n <span className=\"flex items-center justify-center w-5 h-5 rounded-full bg-accent/10 text-accent shrink-0\">\n <svg className=\"w-3 h-3\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </span>\n <span className=\"text-xs text-text-secondary group-hover:text-text-primary transition-colors\">\n AI Triage active.{' '}\n <span className=\"text-accent group-hover:underline\">Cancel</span>\n </span>\n </button>\n ) : (\n <button\n onClick={() => onRequestTriageChange(true)}\n className=\"group flex items-center gap-2.5 text-left my-4\"\n data-testid=\"triage-callout\"\n >\n <span className=\"flex items-center justify-center w-6 h-6 rounded-full bg-accent/10 text-accent shrink-0 animate-[triage-glow_6s_ease-in-out_infinite]\">\n <svg className=\"w-3.5 h-3.5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M9.663 17h4.674M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z\" />\n </svg>\n </span>\n <span className=\"text-sm text-text-secondary group-hover:text-text-primary transition-colors\">\n This form doesn't capture the issue?{' '}\n <span className=\"text-accent group-hover:underline\">Request AI Triage</span>\n </span>\n </button>\n )}\n </div>\n )}\n\n <div className=\"relative min-h-[200px]\">\n {/* Form controls */}\n <div className={requestTriage ? 'pointer-events-none select-none' : ''}>\n <ResolverForm value={json} onChange={onJsonChange} disabled={disabled} submitAttempted={submitAttempted} escalationContext={escalationContext} onOpenHelp={onOpenHelp} onDisabledClick={onDisabledClick} disabledHint={disabledHint} />\n </div>\n\n {/* Triage overlay — occludes the form when AI Triage is checked */}\n {requestTriage && (\n <div\n className=\"absolute inset-0 z-10 flex flex-col bg-surface/90 backdrop-blur-[2px] rounded-md border border-accent/20 p-5\"\n data-testid=\"triage-overlay\"\n >\n <p className=\"text-xs text-text-secondary mb-3 leading-relaxed\">\n The resolution form will not be submitted. Describe the issue\n so AI triage can diagnose and fix it using available tools.\n The corrected result will come back as a new escalation for\n your review.\n </p>\n <textarea\n value={triageNotes}\n onChange={(e) => onTriageNotesChange(e.target.value)}\n placeholder=\"e.g. Content is in Spanish — needs translation to English before review...\"\n className=\"input text-xs w-full flex-1 min-h-[80px] resize-none\"\n autoFocus\n data-testid=\"triage-notes\"\n />\n </div>\n )}\n </div>\n </>\n );\n}\n","import { Link } from 'react-router-dom';\nimport { KeyRound, MonitorPlay } from 'lucide-react';\nimport { RoundsExhaustedContext } from '../../../components/escalation/RoundsExhaustedContext';\nimport { IframeViewport } from '../../../components/escalation/IframeViewport';\nimport { ResolverForm } from '../../../components/escalation/ResolverForm';\nimport { mapPayloadToForm } from '../../../lib/x-lt-bind';\nimport type { ShowIfContext } from '../../../lib/x-lt-show-if';\nimport { ResolverSection } from './ResolverSection';\nimport type { ActiveView } from './EscalationActionBar';\nimport type { LTEscalationRecord } from '../../../api/types';\n\n/**\n * Expands `{key}` tokens in a viewport src URL using values from the\n * escalation's payload, envelope, and metadata — merged in that order so\n * escalation_payload values win over envelope, and envelope wins over metadata.\n *\n * This mirrors how the existing form schemas map envelope/metadata values into\n * default field values, but applied to the iframe src URL.\n */\nexport function expandViewportSrc(src: string, esc: LTEscalationRecord): string {\n if (!src.includes('{')) return src;\n try {\n const parse = (s: string | null | undefined): Record<string, unknown> => {\n if (!s) return {};\n try { return JSON.parse(s) as Record<string, unknown>; } catch { return {}; }\n };\n const merged = {\n ...(esc.metadata ?? {}),\n ...parse(esc.envelope),\n ...parse(esc.escalation_payload),\n };\n return src.replace(/\\{([^}]+)\\}/g, (_, key) =>\n Object.prototype.hasOwnProperty.call(merged, key) ? String(merged[key]) : `{${key}}`\n );\n } catch {\n return src;\n }\n}\n\nfunction parseJson(s: string | null | undefined): Record<string, unknown> | null {\n if (!s) return null;\n try { return JSON.parse(s) as Record<string, unknown>; } catch { return null; }\n}\n\nexport function buildShowIfContext(\n esc: LTEscalationRecord,\n lookup?: Record<string, unknown> | null,\n): ShowIfContext {\n return {\n escalation: esc as unknown as Record<string, unknown>,\n metadata: esc.metadata ?? null,\n envelope: parseJson(esc.envelope),\n payload: parseJson(esc.escalation_payload),\n resolver: null,\n ...(lookup ? { lookup } : {}),\n };\n}\n\ninterface EscalationContextProps {\n isRoundsExhausted: boolean;\n payloadObj: Record<string, unknown> | null;\n isTerminal: boolean;\n resolverPayload: Record<string, unknown> | null;\n onRetryTriage: () => Promise<void>;\n isRetrying: boolean;\n}\n\nexport function EscalationContextBlocks({\n isRoundsExhausted,\n payloadObj,\n isTerminal,\n resolverPayload,\n onRetryTriage,\n isRetrying,\n}: EscalationContextProps) {\n return (\n <>\n {/* Rounds-exhausted structured context */}\n {isRoundsExhausted && payloadObj && (\n <div className=\"mt-8\">\n <RoundsExhaustedContext\n payload={payloadObj}\n isTerminal={isTerminal}\n resolverPayload={resolverPayload}\n onRetryTriage={onRetryTriage}\n isRetrying={isRetrying}\n />\n </div>\n )}\n\n {/* Missing credential context */}\n {payloadObj?.category === 'missing_credential' && (\n <div className=\"mt-8 bg-status-warning/10 border border-status-warning/30 rounded-md px-5 py-4 flex items-start gap-3\">\n <KeyRound size={20} className=\"text-status-warning mt-0.5 shrink-0\" />\n <div>\n <p className=\"text-sm font-medium text-text-primary mb-1\">Missing Credential</p>\n <p className=\"text-xs text-text-secondary mb-3\">\n This workflow requires a <span className=\"font-medium capitalize\">{String(payloadObj.provider)}</span> credential\n to continue. Register one and then resolve this escalation to retry.\n </p>\n <Link\n to=\"/credentials\"\n className=\"btn-primary text-xs inline-flex items-center gap-1.5\"\n >\n <KeyRound size={12} />\n Go to Credentials\n </Link>\n </div>\n </div>\n )}\n </>\n );\n}\n\ninterface FormSectionProps {\n esc: LTEscalationRecord;\n resolverPayload: unknown;\n isTerminal: boolean;\n claimedByMe: boolean;\n activeView: ActiveView;\n metadataFormSchema: unknown;\n /** The resolved form schema (metadata-embedded, role-owned, or workflow fallback). */\n effectiveSchema: Record<string, unknown> | null;\n /** Resolved versioned knowledge lookups — the form's `lookup.*` context domain. */\n lookup?: Record<string, unknown> | null;\n json: string;\n onJsonChange: (v: string) => void;\n requestTriage: boolean;\n onRequestTriageChange: (v: boolean) => void;\n triageNotes: string;\n onTriageNotesChange: (v: string) => void;\n onResolve?: (payload: Record<string, unknown>) => void;\n onEscalate?: (targetRole: string) => void;\n onClaim?: () => void;\n submitAttempted?: boolean;\n isCertified?: boolean;\n hasAI?: boolean;\n /** Opens the Instructions side-panel view (form help icon). */\n onOpenHelp?: () => void;\n /** Fires when the user clicks the locked (unclaimed) form. */\n onDisabledClick?: () => void;\n /** Cursor-following hint over the locked form. */\n disabledHint?: React.ReactNode;\n}\n\n/**\n * The form area — the page's single, direct surface: the resolve form (or a\n * custom iframe viewport), shown even before claiming and enabled by the\n * claim. Terminal escalations render the submitted resolution read-only.\n * Everything else about the record lives in the side panel.\n */\nexport function EscalationFormSection({\n esc,\n resolverPayload,\n isTerminal,\n claimedByMe,\n activeView,\n metadataFormSchema,\n effectiveSchema,\n lookup,\n json,\n onJsonChange,\n requestTriage,\n onRequestTriageChange,\n triageNotes,\n onTriageNotesChange,\n onResolve,\n onEscalate,\n onClaim,\n submitAttempted,\n isCertified,\n hasAI,\n onOpenHelp,\n onDisabledClick,\n disabledHint,\n}: FormSectionProps) {\n const schema = effectiveSchema;\n const showIfCtx = buildShowIfContext(esc, lookup);\n\n // Terminal: show the submitted resolution read-only. The stored payload is\n // the NESTED shape (mapped through x-lt-bind on submit) — reverse-map it\n // back to flat form fields so the resolution renders as the same two-column\n // form it was filled in on, not as raw payload sections.\n if (isTerminal) {\n if (resolverPayload == null) return null;\n const payload = typeof resolverPayload === 'object' && resolverPayload !== null\n ? resolverPayload as Record<string, unknown>\n : {};\n const formSchema = (effectiveSchema ?? (metadataFormSchema as Record<string, any> | null));\n const value = formSchema?.properties\n ? { ...mapPayloadToForm(payload, formSchema), _form_schema: formSchema }\n : payload;\n return (\n <div className=\"mt-3\">\n <ResolverForm\n value={JSON.stringify(value, null, 2)}\n onChange={() => {}}\n disabled\n escalationContext={showIfCtx}\n disabledHint={disabledHint}\n />\n </div>\n );\n }\n\n if (activeView !== 'resolve' || !(esc.workflow_type || effectiveSchema)) return null;\n\n const viewport = schema?.['x-lt-viewport'] as { type?: string; src?: string } | undefined;\n const isIframeViewport = viewport?.type === 'iframe' && !!viewport.src && onResolve && onEscalate;\n\n if (isIframeViewport && !claimedByMe) {\n return (\n <button\n onClick={() => onClaim?.()}\n disabled={!onClaim}\n className=\"flex flex-col items-center justify-center min-h-[55vh] w-full gap-3 text-center group disabled:opacity-50 disabled:cursor-default\"\n >\n <MonitorPlay className=\"w-10 h-10 text-text-tertiary group-hover:text-accent transition-colors\" strokeWidth={1} />\n <p className=\"text-base font-medium text-text-primary group-hover:text-accent transition-colors\">Claim to launch the editor</p>\n </button>\n );\n }\n\n const resolvedSrc = isIframeViewport ? expandViewportSrc(viewport!.src!, esc) : '';\n\n return (\n <div className=\"mt-3\">\n {isIframeViewport ? (\n <IframeViewport\n src={resolvedSrc}\n escalation={esc}\n schema={schema!}\n onResolve={onResolve!}\n onEscalate={onEscalate!}\n submitAttempted={submitAttempted}\n />\n ) : (\n <ResolverSection\n json={json}\n onJsonChange={onJsonChange}\n requestTriage={requestTriage}\n onRequestTriageChange={onRequestTriageChange}\n triageNotes={triageNotes}\n onTriageNotesChange={onTriageNotesChange}\n disabled={!claimedByMe}\n submitAttempted={submitAttempted}\n showTriage={!!isCertified && !!hasAI}\n escalationContext={showIfCtx}\n onOpenHelp={onOpenHelp}\n onDisabledClick={onDisabledClick}\n disabledHint={disabledHint}\n />\n )}\n </div>\n );\n}\n","import { useState, useCallback } from 'react';\nimport { Modal } from '../../../components/common/modal/Modal';\nimport { CustomDurationPicker } from '../../../components/common/form/CustomDurationPicker';\nimport { CountdownTimer } from '../../../components/common/display/CountdownTimer';\nimport { useClaimDurations } from '../../../hooks/useClaimDurations';\n\ninterface ClaimExpiryModalProps {\n open: boolean;\n /** ISO timestamp the claim expires at — drives the live countdown. */\n assignedUntil: string;\n onClose: () => void;\n onExtend: (durationMinutes: number) => void;\n isPending: boolean;\n}\n\n/**\n * Shown when the user's claim enters the warning window before expiry.\n * Extending re-claims with a fresh duration (an idempotent TTL extension for\n * the same assignee). Dismissing lets the claim lapse — the form locks at\n * expiry and edits are kept as a local draft.\n */\nexport function ClaimExpiryModal({ open, assignedUntil, onClose, onExtend, isPending }: ClaimExpiryModalProps) {\n const claimDurations = useClaimDurations();\n const [claimDuration, setClaimDuration] = useState('30');\n const [customMinutes, setCustomMinutes] = useState(0);\n\n const isCustom = claimDuration === 'custom';\n const effectiveMinutes = isCustom ? customMinutes : parseInt(claimDuration);\n const onCustomChange = useCallback((m: number) => setCustomMinutes(m), []);\n\n return (\n <Modal open={open} onClose={onClose} title=\"Claim Expiring\">\n <div className=\"space-y-4\">\n <p className=\"text-sm text-text-secondary\">\n Your claim on this escalation expires in{' '}\n <CountdownTimer until={assignedUntil} />. When it lapses, the form\n locks and the item returns to the queue — your edits are kept as a\n draft. Extend to keep working.\n </p>\n <select\n value={claimDuration}\n onChange={(e) => { setClaimDuration(e.target.value); setCustomMinutes(0); }}\n className=\"select w-full text-sm\"\n aria-label=\"Extension duration\"\n >\n {claimDurations.map((opt) => (\n <option key={opt.value} value={opt.value}>{opt.label}</option>\n ))}\n <option value=\"custom\">Other...</option>\n </select>\n {isCustom && (\n <CustomDurationPicker onChange={onCustomChange} autoFocus />\n )}\n <div className=\"flex justify-end gap-3 pt-2\">\n <button onClick={onClose} className=\"btn-secondary text-xs\">\n Dismiss\n </button>\n <button\n onClick={() => onExtend(effectiveMinutes)}\n className=\"btn-primary text-xs\"\n disabled={isPending || !effectiveMinutes || effectiveMinutes <= 0}\n >\n {isPending ? 'Extending...' : 'Extend Claim'}\n </button>\n </div>\n </div>\n </Modal>\n );\n}\n","import { useEffect, useState } from 'react';\n\n/** How long before claim expiry the extend prompt appears. */\nexport const CLAIM_WARNING_MS = 90_000;\n\nexport interface ClaimClock {\n /** The claim window has lapsed (`assigned_until` is in the past). */\n expired: boolean;\n /** Inside the warning window before expiry — time to offer an extension. */\n expiringSoon: boolean;\n /** Milliseconds until expiry; 0 when expired or when there is no claim. */\n msRemaining: number;\n}\n\n/**\n * Re-renders the consumer exactly when a claim crosses its warning threshold\n * and again when it expires, so claim-derived UI state (form lock, extend\n * dialog) reacts to the clock. Two one-shot timeouts per claim window — no\n * per-second interval. Timers reset whenever `assignedUntil` changes (a claim\n * extension moves the expiry forward and restarts the cycle).\n */\nexport function useClaimClock(\n assignedUntil: string | null | undefined,\n warningMs: number = CLAIM_WARNING_MS,\n): ClaimClock {\n const [, forceTick] = useState(0);\n\n useEffect(() => {\n if (!assignedUntil) return;\n const remaining = new Date(assignedUntil).getTime() - Date.now();\n if (remaining <= 0) return;\n const tick = () => forceTick((t) => t + 1);\n const timers: number[] = [];\n const untilWarning = remaining - warningMs;\n if (untilWarning > 0) timers.push(window.setTimeout(tick, untilWarning));\n timers.push(window.setTimeout(tick, remaining));\n return () => timers.forEach((t) => window.clearTimeout(t));\n }, [assignedUntil, warningMs]);\n\n if (!assignedUntil) return { expired: false, expiringSoon: false, msRemaining: 0 };\n const msRemaining = Math.max(0, new Date(assignedUntil).getTime() - Date.now());\n return {\n expired: msRemaining <= 0,\n expiringSoon: msRemaining > 0 && msRemaining <= warningMs,\n msRemaining,\n };\n}\n","/**\n * Local draft persistence for the resolver form. Edits are saved per\n * escalation while the user works and restored when they return — a lapsed\n * claim or an accidental navigation never loses typed input. The draft is\n * cleared when the escalation reaches a terminal state through this client\n * (resolved, acknowledged, or cancelled).\n */\n\nconst DRAFT_KEY_PREFIX = 'lt:escalation:draft:';\n\nfunction draftKey(escalationId: string): string {\n return `${DRAFT_KEY_PREFIX}${escalationId}`;\n}\n\nexport function readDraft(escalationId: string): string | null {\n try {\n return localStorage.getItem(draftKey(escalationId));\n } catch {\n return null;\n }\n}\n\nexport function saveDraft(escalationId: string, json: string): void {\n try {\n localStorage.setItem(draftKey(escalationId), json);\n } catch {\n /* storage unavailable or full — drafts are best-effort */\n }\n}\n\nexport function clearDraft(escalationId: string): void {\n try {\n localStorage.removeItem(draftKey(escalationId));\n } catch {\n /* storage unavailable — nothing to clear */\n }\n}\n","/**\n * x-lt-transition — post-submit hand-off UX. A form_schema may declare, at its\n * schema root, that submitting one of its escalations should pause on a wait\n * screen instead of returning to the previous page — because a follow-on\n * escalation is about to be born assigned to the submitter (a chained hand-off).\n *\n * x-lt-transition boolean — opt in to the wait screen\n * x-lt-transition-message markdown — shown on the wait screen\n * x-lt-transition-max-wait-seconds number — how long to wait for the\n * follow-on before running the fallback\n * query (clamped to a sane range)\n *\n * These tokens control ONLY the UX. Navigation to the follow-on is driven by the\n * engine's born-assigned `claimed` event (assigned_to + parent_id +\n * assigned_at_creation); the schema carries no navigation target and no metadata\n * is used.\n */\n\nexport const X_LT_TRANSITION = 'x-lt-transition';\nexport const X_LT_TRANSITION_MESSAGE = 'x-lt-transition-message';\nexport const X_LT_TRANSITION_MAX_WAIT_SECONDS = 'x-lt-transition-max-wait-seconds';\nexport const X_LT_TRANSITION_DONE = 'x-lt-transition-done';\n\nconst DEFAULT_MESSAGE = 'Submitted. Preparing your next step…';\nconst DEFAULT_MAX_WAIT_SECONDS = 30;\nconst MIN_MAX_WAIT_SECONDS = 5;\nconst MAX_MAX_WAIT_SECONDS = 300;\n\nexport interface TransitionConfig {\n /** Markdown shown on the wait screen. */\n message: string;\n /** Seconds to wait for the follow-on before the fallback query runs. */\n maxWaitSeconds: number;\n}\n\nfunction clampWaitSeconds(value: unknown): number {\n const n = typeof value === 'number' ? value : Number(value);\n if (!Number.isFinite(n) || n <= 0) return DEFAULT_MAX_WAIT_SECONDS;\n return Math.min(MAX_MAX_WAIT_SECONDS, Math.max(MIN_MAX_WAIT_SECONDS, Math.round(n)));\n}\n\n/**\n * The schema's transition config, or null when the schema does not opt in.\n * `x-lt-transition` must be truthy; message and max-wait fall back to defaults.\n */\nexport function readTransitionConfig(\n schema: Record<string, unknown> | null | undefined,\n): TransitionConfig | null {\n if (!schema || !schema[X_LT_TRANSITION]) return null;\n const rawMessage = schema[X_LT_TRANSITION_MESSAGE];\n const message =\n typeof rawMessage === 'string' && rawMessage.trim().length > 0 ? rawMessage : DEFAULT_MESSAGE;\n return { message, maxWaitSeconds: clampWaitSeconds(schema[X_LT_TRANSITION_MAX_WAIT_SECONDS]) };\n}\n\n/**\n * Where to go when this step ends without a further hand-off — the terminal\n * step of a chain (submitting it), or a transition step whose follow-on never\n * arrives (the wait times out). Independent of `x-lt-transition`, so a terminal\n * form can declare it without opting into the wait screen.\n *\n * The value is an href template using the same `{{domain.path}}` syntax and\n * routing conventions as `x-lt-href` (see LinkWidget): an internal path\n * (`/escalations/available?role=…`) navigates in-app; anything else opens\n * externally. A page reached via a forward transition can't rely on\n * `history.back()`, so this states the destination explicitly. Returns the raw\n * template (interpolate it against the escalation context before navigating),\n * or null when absent.\n */\nexport function readTransitionDone(\n schema: Record<string, unknown> | null | undefined,\n): string | null {\n const raw = schema?.[X_LT_TRANSITION_DONE];\n return typeof raw === 'string' && raw.trim().length > 0 ? raw : null;\n}\n","/**\n * x-lt-submit-on-claim — a one-gesture claim. A form_schema may declare, at its\n * schema root, that claiming one of its escalations should also resolve it in\n * the same gesture, submitting whatever the form currently holds (its seeded\n * defaults). The person clicks Claim once and the work item advances — no\n * second Submit step.\n *\n * x-lt-submit-on-claim boolean — opt in to claim-and-submit\n *\n * It is opt-in and defaults off. Pair it with `x-lt-labels` to rename the Claim\n * button (\"Claim and Submit\") so the single gesture reads honestly. When the\n * seeded defaults fail validation the claim still lands; the page drops into the\n * normal claimed state with the field errors surfaced, so the person finishes\n * the form by hand.\n */\n\nexport const X_LT_SUBMIT_ON_CLAIM = 'x-lt-submit-on-claim';\n\n/**\n * Whether the schema opts into claim-and-submit. Truthy `x-lt-submit-on-claim`\n * turns it on; anything else (absent, false) leaves the standard two-step claim\n * then submit.\n */\nexport function readSubmitOnClaim(\n schema: Record<string, unknown> | null | undefined,\n): boolean {\n return !!schema?.[X_LT_SUBMIT_ON_CLAIM];\n}\n","/**\n * x-lt-submit-guard — a query precondition on the resolve. A form_schema may\n * declare, at its root, that the escalation cannot be resolved while an embedded\n * escalation query still returns rows: the parent references a set of children\n * (commonly claimed by the same person) that must all be completed first, a\n * to-do list that empties as children resolve.\n *\n * \"x-lt-submit-guard\": {\n * \"query\": { \"role\": \"print-harvest\", \"status\": \"pending\",\n * \"assigned\": \"me\",\n * \"facets\": { \"walkId\": \"{{metadata.walkId}}\" } },\n * \"mustBeEmpty\": true, // the only mode today; defaults true\n * \"message\": \"{{count}} plates still pending — bag them before closing.\",\n * \"autoResolveWhenEmpty\": true // auto-submit the parent once empty\n * }\n *\n * The gate is isomorphic. The dashboard disables the submit while the query\n * returns rows (UI honesty), and the API layer enforces the same precondition\n * for `enforce_schema` roles so a raw-API resolve is rejected too. Only a\n * confirmed empty result (a successful read with zero rows) clears the gate — a\n * 403 or any error never does.\n *\n * `autoResolveWhenEmpty` closes the loop: the moment the query is confirmed\n * empty, the claimed parent auto-submits — checked on page-load and after each\n * inline child-resolve — so a set of escalations completes with no extra click.\n */\nimport type { EmbedQuery } from './x-lt-query';\n\nexport const X_LT_SUBMIT_GUARD = 'x-lt-submit-guard';\n\nexport interface SubmitGuardDef {\n query: EmbedQuery;\n /** The gate condition; defaults to true (the only supported mode today). */\n mustBeEmpty?: boolean;\n /** Shown beside the disabled submit. `{{count}}` and `{{domain.path}}` tokens interpolate. */\n message?: string;\n /** When true, auto-submit the claimed parent the moment the query is confirmed empty. */\n autoResolveWhenEmpty?: boolean;\n}\n\nexport const SUBMIT_GUARD_DEFAULT_MESSAGE = '{{count}} related items are still pending';\n\n/** The schema's submit-guard, or undefined when it declares none. */\nexport function readSubmitGuard(\n schema: Record<string, unknown> | null | undefined,\n): SubmitGuardDef | undefined {\n const raw = schema?.[X_LT_SUBMIT_GUARD];\n if (!raw || typeof raw !== 'object' || Array.isArray(raw)) return undefined;\n const guard = raw as SubmitGuardDef;\n if (!guard.query || typeof guard.query !== 'object') return undefined;\n return guard;\n}\n\n/**\n * Whether a guard blocks the resolve given the query's row count. `mustBeEmpty`\n * defaults to true, so any matching row blocks. A pure decision — the caller\n * supplies the count from a confirmed read (never an error/loading state).\n */\nexport function guardBlocks(count: number, guard: SubmitGuardDef | undefined): boolean {\n return !!guard && guard.mustBeEmpty !== false && count > 0;\n}\n","import { useEscalations } from '../api/escalations';\nimport { useAuth } from './useAuth';\nimport { interpolateHelp } from '../lib/x-lt-help';\nimport { resolveScopedQuery } from '../lib/x-lt-query';\nimport { SUBMIT_GUARD_DEFAULT_MESSAGE, type SubmitGuardDef } from '../lib/x-lt-submit-guard';\nimport type { ShowIfContext } from '../lib/x-lt-show-if';\n\nexport type { SubmitGuardDef } from '../lib/x-lt-submit-guard';\n\n/**\n * The `x-lt-submit-guard` gate on the resolve button. While the embedded query\n * still returns rows the submit stays disabled and `message` renders the live\n * count; the moment the last row resolves, the existing socket-invalidation\n * path refires the query and the button lights up. No polling.\n *\n * Only a CONFIRMED empty read clears the gate — a successful query returning\n * zero rows. Loading, an error, or a 403 never clear it: the button stays\n * disabled until the guard can prove there is nothing left. `confirmedEmpty`\n * is the same signal the page's auto-resolve waits on.\n *\n * The server enforces the identical precondition for `enforce_schema` roles\n * (services/escalation/submit-guard.ts), so a raw-API resolve is rejected too.\n */\nexport interface SubmitGuardState {\n blocked: boolean;\n count: number;\n message: string;\n /** True only on a successful read with zero rows — never while loading or errored. */\n confirmedEmpty: boolean;\n}\n\nexport function useSubmitGuard(\n guard: SubmitGuardDef | undefined,\n ctx: ShowIfContext | undefined,\n): SubmitGuardState {\n const { user } = useAuth();\n\n // The SAME mapping the escalation-list embed uses (resolveScopedQuery) —\n // including the `assigned` ownership scope — so the guard's count always\n // matches the rows a same-query embed renders.\n const scoped = resolveScopedQuery(guard?.query ?? {}, ctx ?? {}, user?.userId);\n\n const { data, isSuccess } = useEscalations({\n role: scoped.role,\n status: scoped.status,\n facets: scoped.facets,\n assigned_to: scoped.assigned_to,\n available: scoped.available,\n limit: 1, // the gate needs only the total; rows are irrelevant\n enabled: !!guard && scoped.enabled,\n });\n\n // A guard whose scope cannot be evaluated (no role/facets, or `assigned:'me'`\n // with no viewer) is inert — it neither blocks nor auto-resolves. When the\n // scope IS evaluable, only a successful empty read clears the gate.\n const active = !!guard && guard.mustBeEmpty !== false && scoped.enabled;\n const count = data?.total ?? 0;\n const confirmedEmpty = active && isSuccess && count === 0;\n const blocked = active && !confirmedEmpty;\n\n // {{count}} is a local token — substitute it BEFORE the domain pass, which\n // replaces unknown domains with the missing-value dash. While blocked without\n // a confirmed count (loading/error), a count message would lie, so show a\n // neutral checking line instead.\n let message = '';\n if (blocked) {\n if (count > 0) {\n const template = guard?.message ?? SUBMIT_GUARD_DEFAULT_MESSAGE;\n message = interpolateHelp(template.replace(/\\{\\{count\\}\\}/g, String(count)), ctx ?? {});\n } else {\n message = 'Checking related items…';\n }\n }\n\n return { blocked, count, message, confirmedEmpty };\n}\n","import { createPortal } from 'react-dom';\nimport { MarkdownRenderer } from '../common/display/MarkdownRenderer';\n\ninterface TransitionWaitModalProps {\n open: boolean;\n /** Markdown shown while the follow-on is being prepared. */\n message: string;\n}\n\n/**\n * The hand-off bridge. After the viewer submits an escalation whose form opted\n * in via `x-lt-transition`, this holds the screen while the workflow creates and\n * assigns the next step. It is intentionally NOT dismissible — there is no wrong\n * button to press; either the follow-on arrives (useFollowMyClaims navigates and\n * this unmounts) or the detail page's timeout resolves it. Centered at every\n * breakpoint: a full-width sheet on narrow screens, a centered card on wide.\n */\nexport function TransitionWaitModal({ open, message }: TransitionWaitModalProps) {\n if (!open) return null;\n\n return createPortal(\n <div className=\"fixed inset-0 z-50 flex items-center justify-center px-4\">\n <div className=\"absolute inset-0 bg-text-primary/40 backdrop-blur-sm\" />\n <div\n role=\"status\"\n aria-live=\"polite\"\n className=\"relative w-full max-w-sm bg-surface-raised border border-surface-border rounded-lg shadow-xl px-6 py-7 text-center\"\n >\n <div className=\"flex justify-center mb-4\" aria-hidden=\"true\">\n <span className=\"inline-block w-7 h-7 rounded-full border-2 border-surface-border border-t-accent animate-spin\" />\n </div>\n <div className=\"text-sm text-text-secondary [&_p]:m-0 [&_p+p]:mt-2\">\n <MarkdownRenderer content={message} />\n </div>\n </div>\n </div>,\n document.body,\n );\n}\n","import { useState, useEffect, useMemo, useRef } from 'react';\nimport { useParams, useNavigate, useLocation } from 'react-router-dom';\nimport { useQueryClient } from '@tanstack/react-query';\nimport { useAuth } from '../../../hooks/useAuth';\nimport { useAccess } from '../../../hooks/useAccess';\nimport { useActingIdentity } from '../../../hooks/useActingIdentity';\nimport { useScanEnabled } from '../../../hooks/useScanInput';\nimport {\n useEscalation,\n useEscalationLookups,\n useClaimEscalation,\n useResolveEscalation,\n useEscalateToRole,\n useCancelEscalation,\n useBulkAssignEscalations,\n useBulkUnassignEscalations,\n} from '../../../api/escalations';\nimport { BulkAssignModal } from '../../../components/common/modal/BulkAssignModal';\nimport { ApiError } from '../../../api/client';\nimport { isValidationErrorBody } from '../../../lib/validation';\nimport { ConfirmCancelModal } from '../../../components/common/modal/ConfirmCancelModal';\nimport { ScanConfirmModal } from '../../../components/scan/ScanConfirmModal';\nimport { PageHeader } from '../../../components/common/layout/PageHeader';\nimport { ListToolbar } from '../../../components/common/data/ListToolbar';\nimport { isEffectivelyClaimed } from '../../../lib/escalation';\nimport { mapPayloadToForm } from '../../../lib/x-lt-bind';\nimport { useWorkflowConfigs } from '../../../api/workflows';\nimport { useSettings } from '../../../api/settings';\nimport { getAiOverride } from '../../../lib/view-as';\nimport { useEscalationDetailEvents } from '../../../hooks/useEventHooks';\nimport { PanelRightClose, PanelRightOpen, RotateCcw, X } from 'lucide-react';\nimport { EscalationSidePanel, ESCALATION_PANEL_VIEWS } from '../../../components/escalation/EscalationSidePanel';\nimport { EscalationActionBar } from './EscalationActionBar';\nimport type { ActionBarMode, ActiveView } from './EscalationActionBar';\nimport { UserName } from '../../../components/common/display/UserName';\nimport type { FieldError } from '../../../lib/field-validator';\nimport { validateResolverForm } from '../../../lib/field-validator';\nimport { EscalationContextBlocks, EscalationFormSection, expandViewportSrc, buildShowIfContext } from './EscalationDetailSections';\nimport { IframeViewport } from '../../../components/escalation/IframeViewport';\nimport { ClaimExpiryModal } from './ClaimExpiryModal';\nimport { useClaimClock } from '../../../hooks/useClaimClock';\nimport { readDraft, saveDraft, clearDraft } from '../../../lib/draft-store';\nimport { readTransitionConfig, readTransitionDone } from '../../../lib/x-lt-transition';\nimport { readSubmitOnClaim } from '../../../lib/x-lt-submit-on-claim';\nimport { readFooterLabels } from '../../../lib/x-lt-labels';\nimport { readSubmitGuard } from '../../../lib/x-lt-submit-guard';\nimport { useSubmitGuard } from '../../../hooks/useSubmitGuard';\nimport { buildResolverPayload } from '../../../lib/resolver-payload';\nimport { interpolateHelp } from '../../../lib/x-lt-help';\nimport { TransitionWaitModal } from '../../../components/escalation/TransitionWaitModal';\nimport { apiFetch } from '../../../api/client';\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nconst PANEL_OPEN_KEY = 'lt:escalation:panel:open';\n\nfunction readPanelOpen(): boolean {\n try {\n const v = localStorage.getItem(PANEL_OPEN_KEY);\n return v === null ? true : v === 'true';\n } catch {\n return true;\n }\n}\n\nfunction savePanelOpen(open: boolean): void {\n try { localStorage.setItem(PANEL_OPEN_KEY, String(open)); } catch {}\n}\n\nfunction safeParse(value: string | null | undefined): unknown {\n if (!value) return null;\n try {\n return JSON.parse(value);\n } catch {\n return value;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Main page\n// ---------------------------------------------------------------------------\n\nexport function EscalationDetailPage() {\n // The detail route reuses this element across navigations to other\n // escalations (same route pattern, different :id). Keying the view by id\n // tears down and rebuilds ALL local state — the seeded form json, the\n // one-shot init ref, submit flags — so nothing rendered for one escalation\n // can survive into, or act on, another.\n const { id } = useParams<{ id: string }>();\n return <EscalationDetailView key={id} id={id!} />;\n}\n\nfunction EscalationDetailView({ id }: { id: string }) {\n const { user, isSuperAdmin, hasRoleType } = useAuth();\n // Claim overrides (reassign / return to queue) are management verbs.\n const canManage = isSuperAdmin || hasRoleType('admin');\n const { identity: acting } = useActingIdentity();\n const scanEnabled = useScanEnabled();\n // The badge grant outranks the session: whoever badged in owns the claim\n // comparisons here, and the mutations they fire ride the acting header so\n // the server attributes them to the same person.\n const effectiveActorId = acting?.actorId ?? user?.userId;\n const navigate = useNavigate();\n const location = useLocation();\n const queryClient = useQueryClient();\n const { data: esc, isLoading, refetch, isFetching } = useEscalation(id);\n useEscalationDetailEvents(id);\n // Versioned knowledge lookups pinned on the row's envelope — one immutable\n // batch fetch, folded into the form context as the `lookup.*` domain.\n // Cascade levels resolve locally from this data; no network during edits.\n const hasLookupRefs = useMemo(() => {\n if (!esc?.envelope) return false;\n try {\n const parsed = JSON.parse(esc.envelope);\n return Array.isArray(parsed?.lookups) && parsed.lookups.length > 0;\n } catch {\n return false;\n }\n }, [esc?.envelope]);\n const { data: lookupData } = useEscalationLookups(id, hasLookupRefs);\n const lookupCtx = useMemo(() => {\n if (!lookupData?.lookups?.length) return null;\n return Object.fromEntries(\n lookupData.lookups.filter((l) => !l.missing).map((l) => [l.as ?? l.key, l.data]),\n );\n }, [lookupData]);\n const claim = useClaimEscalation();\n const resolve = useResolveEscalation();\n const escalate = useEscalateToRole();\n const cancel = useCancelEscalation();\n const bulkAssign = useBulkAssignEscalations();\n const bulkUnassign = useBulkUnassignEscalations();\n const [cancelModalOpen, setCancelModalOpen] = useState(false);\n const [reassignModalOpen, setReassignModalOpen] = useState(false);\n const { data: workflowConfigs } = useWorkflowConfigs();\n const { data: settings } = useSettings();\n\n const { isBuilder } = useAccess();\n\n const wfConfig = workflowConfigs?.find((c) => c.workflow_type === esc?.workflow_type);\n const traceUrl = settings?.telemetry?.traceUrl ?? null;\n const [activeView, setActiveView] = useState<ActiveView>('resolve');\n const [json, setJson] = useState('{}');\n\n const [sidePanelOpen, setSidePanelOpen] = useState<boolean>(readPanelOpen);\n\n const [requestTriage, setRequestTriage] = useState(false);\n const [triageNotes, setTriageNotes] = useState('');\n const [submitAttempted, setSubmitAttempted] = useState(false);\n const [formErrors, setFormErrors] = useState<FieldError[]>([]);\n // Bumped on every click on the locked (unclaimed) form; each bump replays\n // the claim button's wiggle — the answer to \"why can't I type here.\"\n const [claimNudge, setClaimNudge] = useState(0);\n const [panelActiveView, setPanelActiveView] = useState<string | undefined>(undefined);\n // Set after a successful resolve when the form opted into a hand-off\n // (x-lt-transition). Holds the screen on a wait modal instead of returning to\n // the list; the global useFollowMyClaims navigates to the born-assigned\n // follow-on when its `claimed` event arrives. The timeout below is the\n // fallback for the SDK's at-most-once delivery (a dropped event); `doneDest`\n // is where to land if the follow-on never comes (an x-lt-transition-done URL).\n const [waiting, setWaiting] = useState<{ message: string; maxWaitSeconds: number; doneDest: string | null } | null>(null);\n\n // Auto-start (list-driven claim-and-submit): a list row launched with the\n // `autoStart` intent (x-lt-row-action submitOnClaim) claims and submits this\n // escalation without a second gesture, then transitions on to the follow-on.\n // `autoStarting` masks the brief form render with the wait screen; the ref\n // holds the latest handler (assigned in the render body, where the handlers\n // are defined) so the effect below can fire it exactly once.\n const [autoStarting, setAutoStarting] = useState(false);\n const autoStartFiredRef = useRef(false);\n const autoStartActionRef = useRef<(() => void) | null>(null);\n\n // Auto-resolve-when-empty (x-lt-submit-guard.autoResolveWhenEmpty): the moment\n // the guard query is confirmed empty, the claimed parent submits itself. Fires\n // once; the effect re-checks on page-load and after each inline child-resolve\n // (the guard query is socket-invalidated, so it refetches with no polling).\n const autoResolveFiredRef = useRef(false);\n const autoResolveActionRef = useRef<(() => void) | null>(null);\n\n // Claim clock: re-renders at the warning threshold (extend prompt) and at\n // expiry (isEffectivelyClaimed flips false on that render — the form locks\n // and the action bar returns to its available state). Dismissal is keyed by\n // the assigned_until value so an ignored prompt stays away for that claim\n // window but returns after an extension starts a new one.\n const claimClock = useClaimClock(esc?.assigned_until);\n const [extendDismissedUntil, setExtendDismissedUntil] = useState<string | null>(null);\n\n // Recompute form errors in real-time once the user has attempted a submit.\n // This keeps the errors sidebar in sync as the user fixes (or breaks) fields.\n useEffect(() => {\n if (!submitAttempted || !esc) return;\n try {\n const payload = JSON.parse(json) as Record<string, unknown>;\n const schema = payload._form_schema as Record<string, unknown> | undefined;\n if (!schema) { setFormErrors([]); return; }\n setFormErrors(validateResolverForm(schema, payload, buildShowIfContext(esc, lookupCtx)));\n } catch { /* leave errors unchanged on parse failure */ }\n }, [json, submitAttempted, esc]);\n // Schema resolution, most specific first:\n // 1. metadata.form_schema — a full form embedded on the row (legacy records)\n // 2. esc.form_schema — the role's form the single-escalation GET already\n // JOINed in, resolved to the row's pinned version (metadata.schema_version)\n // or the role's latest when unpinned. No second call.\n // 3. workflow-level resolver_schema (legacy fallback)\n const metadataFormSchema = (esc?.metadata as any)?.form_schema ?? null;\n const resolverSchema =\n (esc?.form_schema ?? wfConfig?.resolver_schema ?? null) as Record<string, any> | null;\n const effectiveSchema = metadataFormSchema ?? resolverSchema;\n\n // Footer configuration — root tokens on the form schema. `x-lt-submit-on-claim`\n // folds claim and submit into one gesture; `x-lt-labels` renames the action\n // controls (e.g. a \"Claim and Submit\" button when both are set).\n const submitOnClaim = readSubmitOnClaim(effectiveSchema as Record<string, unknown> | null);\n const footerLabels = readFooterLabels(effectiveSchema as Record<string, unknown> | null);\n\n // x-lt-submit-guard — the query precondition. The page owns it (not the action\n // bar) because it also drives auto-resolve-when-empty. Inert until the row\n // loads; the hook self-disables when the schema declares no guard.\n const submitGuardDef = readSubmitGuard(effectiveSchema as Record<string, unknown> | null);\n const submitGuard = useSubmitGuard(submitGuardDef, esc ? buildShowIfContext(esc, lookupCtx) : undefined);\n\n // Initialize json from the form exactly once. Fields are seeded in priority order:\n // metadata (facts stamped at enqueue) → envelope.formDefaults (workflow overrides)\n // → schema default. formDefaults always wins over metadata so the workflow can\n // override a metadata fact when needed. Subsequent esc refetches must NOT reset\n // user edits. The form arrives embedded on esc, so nothing else to await.\n const jsonInitialized = useRef(false);\n const initialJsonRef = useRef<string | null>(null);\n useEffect(() => {\n if (jsonInitialized.current) return;\n const formSchema = metadataFormSchema ?? (resolverSchema?.properties ? resolverSchema : null);\n if (formSchema?.properties) {\n jsonInitialized.current = true;\n const seeded = safeParse(esc?.envelope) as Record<string, any> | null;\n const formDefaults = seeded?.formDefaults;\n const mergedPrefill: Record<string, any> = {\n ...(esc?.metadata ?? {}),\n ...(typeof formDefaults === 'object' && formDefaults !== null ? formDefaults : {}),\n };\n const prefill = mapPayloadToForm(mergedPrefill, formSchema);\n const initial: Record<string, any> = { _form_schema: formSchema };\n for (const [key, def] of Object.entries(formSchema.properties)) {\n const fieldDef = def as Record<string, any>;\n // The zero value follows the declared type: an object field (e.g. a\n // checklist) starts as {} — never '' — so its value round-trips as\n // an object from the first interaction.\n const zero = fieldDef.type === 'object' ? {} : '';\n initial[key] = prefill[key] ?? fieldDef.default ?? zero;\n }\n initialJsonRef.current = JSON.stringify(initial, null, 2);\n // A saved draft (typed input from an earlier visit or a lapsed claim)\n // wins over the seeded defaults. The schema is always taken fresh —\n // a draft never resurrects a stale form definition.\n const terminal = esc?.status === 'resolved' || esc?.status === 'cancelled';\n const draft = !terminal && esc?.id ? readDraft(esc.id) : null;\n const draftObj = draft ? (safeParse(draft) as Record<string, any> | null) : null;\n if (draftObj && typeof draftObj === 'object' && !Array.isArray(draftObj)) {\n setJson(JSON.stringify({ ...draftObj, _form_schema: formSchema }, null, 2));\n } else {\n setJson(initialJsonRef.current);\n }\n } else if (effectiveSchema) {\n jsonInitialized.current = true;\n setJson(JSON.stringify(effectiveSchema, null, 2));\n }\n }, [effectiveSchema, metadataFormSchema, resolverSchema, esc?.envelope, esc?.metadata, esc?.id, esc?.status]);\n\n // Persist edits as a local draft (debounced). Best-effort insurance against\n // a lapsed claim or accidental navigation. Pristine defaults are not saved,\n // and reverting to them removes the stored draft; a terminal outcome\n // through this client clears it too (see handleResolve / handleConfirmCancel).\n useEffect(() => {\n if (!jsonInitialized.current || initialJsonRef.current === null || !esc?.id) return;\n if (esc.status !== 'pending') return;\n const escalationId = esc.id;\n const timer = window.setTimeout(() => {\n if (json === initialJsonRef.current) clearDraft(escalationId);\n else saveDraft(escalationId, json);\n }, 400);\n return () => window.clearTimeout(timer);\n }, [json, esc?.id, esc?.status]);\n\n // Hand-off fallback. The follow-on's `claimed` event normally arrives and\n // useFollowMyClaims navigates (this view unmounts, clearing the timer). SDK\n // delivery is at-most-once, so if that event was dropped, on timeout we query\n // the child of this escalation assigned to the viewer — precise, no heuristic\n // — and land on it; only if none exists do we return to the list.\n useEffect(() => {\n if (!waiting) return;\n const timer = window.setTimeout(async () => {\n try {\n const params = new URLSearchParams({\n parent_id: id,\n assigned_to: effectiveActorId ?? '',\n status: 'pending',\n limit: '1',\n });\n const res = await apiFetch<{ escalations: Array<{ id: string; parent_id?: string }> }>(`/escalations?${params}`);\n const child = res?.escalations?.[0];\n // Guard the correlation on the row itself, so a query path that does not\n // filter by parent_id (self-scope search) can never land a wrong child.\n if (child?.id && child.parent_id === id) {\n setWaiting(null);\n navigate(`/escalations/detail/${child.id}`);\n return;\n }\n } catch { /* fall through to the declared destination / previous page */ }\n setWaiting(null);\n queryClient.resetQueries({ queryKey: ['escalations'] });\n queryClient.resetQueries({ queryKey: ['escalationStats'] });\n // No follow-on arrived: prefer the form's declared destination over\n // history.back() (which is wrong for a page reached via a transition).\n const dest = waiting.doneDest;\n if (dest) {\n if (dest.startsWith('/')) navigate(dest);\n else window.location.assign(dest);\n } else {\n navigate(-1);\n }\n }, waiting.maxWaitSeconds * 1000);\n return () => window.clearTimeout(timer);\n }, [waiting, id, effectiveActorId, navigate, queryClient]);\n\n // Fire the list-driven auto-start once. The escalation must be loaded, still\n // claimable (pending, no live claim), and — when it carries a form — seeded so\n // its defaults are ready to submit. The one-shot ref survives refetches; the\n // action ref holds the current handler closure (assigned in the render body,\n // after the handlers are defined).\n useEffect(() => {\n if (autoStartFiredRef.current) return;\n if (!(location.state as { autoStart?: boolean } | null)?.autoStart) return;\n if (!esc || esc.status !== 'pending' || isEffectivelyClaimed(esc)) return;\n // The seeded defaults land in `json` one render after the schema resolves;\n // an unseeded '{}' would submit an empty payload, so wait for the real form.\n if (json === '{}') return;\n autoStartFiredRef.current = true;\n autoStartActionRef.current?.();\n }, [esc, json, location.state]);\n\n // Auto-resolve the claimed parent once the submit guard confirms its children\n // are gone. Only the claimant closes it, and only when the parent's own form\n // has seeded — the action ref (below) revalidates before submitting.\n useEffect(() => {\n if (autoResolveFiredRef.current) return;\n if (!submitGuardDef?.autoResolveWhenEmpty || !submitGuard.confirmedEmpty) return;\n if (!esc || esc.status !== 'pending' || !isEffectivelyClaimed(esc)) return;\n if (esc.assigned_to !== effectiveActorId) return;\n if (json === '{}') return;\n autoResolveFiredRef.current = true;\n autoResolveActionRef.current?.();\n }, [submitGuard.confirmedEmpty, submitGuardDef, esc, json, effectiveActorId]);\n\n const isRoundsExhausted = esc?.subtype === 'rounds_exhausted';\n\n if (isLoading) {\n return (\n <div className=\"animate-pulse space-y-8\">\n <div className=\"h-8 bg-surface-sunken rounded w-64\" />\n <div className=\"h-32 bg-surface-sunken rounded w-full\" />\n </div>\n );\n }\n\n if (!esc) {\n return <p className=\"text-sm text-text-secondary\">Escalation not found.</p>;\n }\n\n const claimed = isEffectivelyClaimed(esc);\n const claimedByMe = claimed && esc.assigned_to === effectiveActorId;\n const claimedByOther = claimed && !claimedByMe;\n const isTerminal = esc.status === 'resolved' || esc.status === 'cancelled';\n\n const iframeViewport = (effectiveSchema as any)?.['x-lt-viewport'] as { type?: string; src?: string } | undefined;\n const isIframeMode = iframeViewport?.type === 'iframe' && !!iframeViewport?.src && claimedByMe && !isTerminal;\n\n const escalationPayload = safeParse(esc.escalation_payload);\n const resolverPayload = safeParse(esc.resolver_payload);\n const envelopeObj = safeParse(esc.envelope) as Record<string, any> | null;\n const isCertified = !!(envelopeObj?.metadata?.certified);\n const aiOverride = getAiOverride();\n const hasAI = aiOverride !== null ? aiOverride : !!(settings as any)?.ai?.enabled;\n\n const payloadObj = (typeof escalationPayload === 'object' && escalationPayload !== null && !Array.isArray(escalationPayload))\n ? escalationPayload as Record<string, unknown>\n : null;\n const triageData = payloadObj?._triage as Record<string, unknown> | undefined;\n const resolverObj = (typeof resolverPayload === 'object' && resolverPayload !== null && !Array.isArray(resolverPayload))\n ? resolverPayload as Record<string, unknown>\n : null;\n\n const actionBarMode: ActionBarMode = isTerminal\n ? 'terminal'\n : claimedByMe\n ? 'claimed_by_me'\n : claimedByOther\n ? 'claimed_by_other'\n : 'available';\n\n // The locked form's cursor hint — names the state or the unlocking gesture\n // (in the role's own vocabulary) at the exact point of interaction.\n const lockedFormHint: React.ReactNode =\n actionBarMode === 'available'\n ? `${typeof footerLabels.claim === 'string' ? footerLabels.claim : 'Claim'} this escalation to edit the form`\n : actionBarMode === 'claimed_by_other'\n ? <>Claimed by {esc.assigned_to ? <UserName userId={esc.assigned_to} /> : 'another user'}</>\n : esc.status === 'cancelled'\n ? 'This escalation is cancelled'\n : esc.status === 'resolved'\n ? 'This escalation is resolved — the submitted values are shown'\n : null;\n\n // Every mutation below targets the mount-fixed route id, never esc.id.\n // The two are equal for the life of this keyed view, but binding to the\n // prop makes it impossible for an in-flight render against refreshed\n // query data to redirect an action at a different escalation.\n const handleClaim = (durationMinutes: number) => {\n claim.mutate({ id, durationMinutes });\n };\n\n const goBack = () => {\n queryClient.resetQueries({ queryKey: ['escalations'] });\n queryClient.resetQueries({ queryKey: ['escalationStats'] });\n navigate(-1);\n };\n\n // The declared x-lt-transition-done destination for this form, interpolated\n // against the escalation context ({{metadata.account}} etc.), or null.\n const resolveDoneDest = (): string | null => {\n const tmpl = readTransitionDone(effectiveSchema as Record<string, unknown> | null);\n if (!tmpl) return null;\n return interpolateHelp(tmpl, buildShowIfContext(esc, lookupCtx)) || null;\n };\n\n // Navigate to a resolved destination — internal path in-app, else external —\n // refreshing the queue caches first (as goBack does).\n const navigateDone = (dest: string) => {\n queryClient.resetQueries({ queryKey: ['escalations'] });\n queryClient.resetQueries({ queryKey: ['escalationStats'] });\n if (dest.startsWith('/')) navigate(dest);\n else window.location.assign(dest);\n };\n\n const handleResolve = async (payload: Record<string, unknown>) => {\n try {\n await resolve.mutateAsync({ id, resolverPayload: payload });\n } catch (err) {\n // Server-side schema enforcement (enforce_schema roles) — the 422 body\n // carries the same field-error list the pre-submission pass produces;\n // route it into the same errors panel.\n if (err instanceof ApiError && isValidationErrorBody(err.body)) {\n setSubmitAttempted(true);\n setFormErrors(err.body.violations);\n setPanelActiveView(ESCALATION_PANEL_VIEWS.ERRORS);\n return;\n }\n throw err;\n }\n clearDraft(id);\n // Hand-off resolution, in order:\n // 1. x-lt-transition → hold on the wait screen while the born-assigned\n // follow-on is prepared (doneDest is where to land if it never comes).\n // 2. x-lt-transition-done → an explicit destination. A terminal chain step\n // was reached by a forward navigation, so history.back() is wrong; go\n // where the form says (a canonical page or a rich worklist URL).\n // 3. neither → return to the previous page.\n const transition = readTransitionConfig(effectiveSchema as Record<string, unknown> | null);\n const doneDest = resolveDoneDest();\n if (transition) {\n setWaiting({ ...transition, doneDest });\n return;\n }\n if (doneDest) {\n navigateDone(doneDest);\n return;\n }\n goBack();\n };\n\n // x-lt-submit-on-claim: claim, then immediately resolve with whatever the form\n // holds (its seeded defaults). The two are distinct operations — the row must\n // be claimed by me before the server accepts the resolve — so they run in\n // sequence. If the defaults fail validation the claim still stands; the page\n // drops into the normal claimed state with the errors surfaced so the person\n // finishes by hand. Wired to the Claim button only; extend and the locked-form\n // nudge keep the plain claim.\n const handleClaimAndSubmit = async (durationMinutes: number) => {\n try {\n await claim.mutateAsync({ id, durationMinutes });\n } catch {\n return; // claim.error surfaces through the action bar\n }\n // A submit guard defers the auto-submit: land the person on the claimed\n // parent with its children to work; the auto-resolve effect closes it once\n // they clear (pair submitOnClaim with autoResolveWhenEmpty for full flow).\n if (submitGuard.blocked) return;\n const result = buildResolverPayload(json, buildShowIfContext(esc, lookupCtx));\n if (result.parseError) return; // seeded form is malformed — leave it claimed\n if (result.errors.length > 0) {\n setSubmitAttempted(true);\n setFormErrors(result.errors);\n setSidePanelOpen(true);\n savePanelOpen(true);\n setPanelActiveView(ESCALATION_PANEL_VIEWS.ERRORS);\n return;\n }\n await handleResolve(result.payload!);\n };\n\n // The list-driven auto-start: mask the form with the wait screen, then run the\n // same claim-and-submit the manual button runs. On success the transition (or\n // goBack) takes over; on a validation miss the mask drops to reveal the\n // claimed form and its errors. Reassigned each render so the pre-return effect\n // fires the latest closure.\n autoStartActionRef.current = async () => {\n const dm = (location.state as { durationMinutes?: number } | null)?.durationMinutes;\n setAutoStarting(true);\n await handleClaimAndSubmit(typeof dm === 'number' && dm > 0 ? dm : 30);\n setAutoStarting(false);\n };\n\n // Auto-resolve-when-empty: submit the parent's seeded payload once the guard\n // clears. Revalidates first — if the parent's own form is incomplete, leave it\n // for the person rather than auto-closing an invalid record.\n autoResolveActionRef.current = () => {\n const result = buildResolverPayload(json, buildShowIfContext(esc, lookupCtx));\n if (result.parseError || result.errors.length > 0) return;\n handleResolve(result.payload!);\n };\n\n const handleEscalate = async (targetRole: string) => {\n if (!targetRole) return;\n await escalate.mutateAsync({ id, targetRole });\n goBack();\n };\n\n const handleRetryTriage = async () => {\n if (!claimedByMe) {\n await claim.mutateAsync({ id, durationMinutes: 30 });\n }\n const diagnosis = (payloadObj?.diagnosis as string) || esc.description || '';\n await resolve.mutateAsync({\n id,\n resolverPayload: { _lt: { needsTriage: true }, notes: diagnosis },\n });\n goBack();\n };\n\n const handleRelease = async () => {\n await claim.mutateAsync({ id, durationMinutes: 0 });\n goBack();\n };\n\n const handleConfirmCancel = async () => {\n await cancel.mutateAsync(id);\n clearDraft(id);\n setCancelModalOpen(false);\n goBack();\n };\n\n // One panel entry in the header: the toggle. Authored help stays reachable\n // through the form title's help icon and the panel's own Help tab.\n const headerActions = (\n <div className=\"flex items-center gap-2\">\n <ListToolbar\n onRefresh={() => refetch()}\n isFetching={isFetching}\n apiPath={`/escalations/${esc.id}`}\n standalone\n />\n <button\n onClick={() => setSidePanelOpen((prev) => { savePanelOpen(!prev); return !prev; })}\n className=\"ml-2 text-accent/60 hover:text-accent transition-colors\"\n title={sidePanelOpen ? 'Hide side panel' : 'Show side panel'}\n >\n {sidePanelOpen\n ? <PanelRightClose className=\"w-5 h-5\" strokeWidth={1.5} />\n : <PanelRightOpen className=\"w-5 h-5\" strokeWidth={1.5} />}\n </button>\n </div>\n );\n\n return (\n // Two fixed-height columns, like the left nav: the form column scrolls\n // independently and the side panel keeps its own scroll. Negative margins\n // let the panel span the full middle row (header to event feed, flush\n // right); the left column re-adds those gutters for its own content.\n <div className=\"flex-1 min-h-0 min-w-0 flex items-stretch -mt-8 -mr-page-x -mb-16\">\n <div className=\"flex-1 min-w-0 flex flex-col min-h-0\">\n {isIframeMode ? (\n // Full-bleed iframe mode: no header, no padding, -ml-page-x cancels the shell gutter.\n // Release, Cancel, and panel toggle float at top-right over the iframe.\n <div className=\"relative flex-1 min-h-0 -ml-page-x\">\n <div className=\"absolute top-3 right-3 z-50 flex items-center gap-0.5 bg-surface/90 backdrop-blur-sm rounded-lg px-1.5 py-1 shadow-sm border border-surface-border/40\">\n {[\n {\n onClick: handleRelease,\n disabled: claim.isPending,\n label: footerLabels.release ?? 'Release',\n hoverClass: 'hover:text-accent',\n icon: <RotateCcw className=\"w-4 h-4\" strokeWidth={1.5} />,\n },\n ...(footerLabels.cancel === false ? [] : [{\n onClick: () => setCancelModalOpen(true),\n disabled: false,\n label: footerLabels.cancel ?? 'Cancel',\n hoverClass: 'hover:text-status-error',\n icon: <X className=\"w-4 h-4\" strokeWidth={1.5} />,\n }]),\n {\n onClick: () => setSidePanelOpen((prev) => { savePanelOpen(!prev); return !prev; }),\n disabled: false,\n label: sidePanelOpen ? 'Hide panel' : 'Show panel',\n hoverClass: 'hover:text-accent',\n icon: sidePanelOpen\n ? <PanelRightClose className=\"w-4 h-4\" strokeWidth={1.5} />\n : <PanelRightOpen className=\"w-4 h-4\" strokeWidth={1.5} />,\n },\n ].map(({ onClick, disabled, label, hoverClass, icon }) => (\n <div key={label} className=\"relative group/tip\">\n <button\n onClick={onClick}\n disabled={disabled}\n className={`text-text-tertiary ${hoverClass} transition-colors disabled:opacity-40 disabled:cursor-default p-1.5 rounded-md`}\n >\n {icon}\n </button>\n <span className=\"pointer-events-none absolute top-full left-1/2 -translate-x-1/2 mt-1.5 px-2 py-0.5 rounded text-2xs bg-surface-sunken text-text-primary whitespace-nowrap opacity-0 group-hover/tip:opacity-100 transition-opacity\">\n {label}\n </span>\n </div>\n ))}\n </div>\n <IframeViewport\n src={expandViewportSrc(iframeViewport!.src!, esc)}\n escalation={esc}\n schema={effectiveSchema!}\n onResolve={handleResolve}\n onEscalate={handleEscalate}\n submitAttempted={submitAttempted}\n fill\n />\n </div>\n ) : (\n <>\n {/* The description IS the title — the page opens with what to do. It\n shares the row with the toolbar and panel toggle, truncating to\n make room. */}\n <div className=\"shrink-0 pt-8 pr-page-x\">\n <PageHeader title={esc.description || 'Escalation'} actions={headerActions} />\n </div>\n\n {/* Independently scrolling form column */}\n <div className=\"flex-1 min-h-0 overflow-y-auto pr-page-x\">\n <EscalationContextBlocks\n isRoundsExhausted={isRoundsExhausted}\n payloadObj={payloadObj}\n isTerminal={isTerminal}\n resolverPayload={resolverPayload as Record<string, unknown> | null}\n onRetryTriage={handleRetryTriage}\n isRetrying={claim.isPending || resolve.isPending}\n />\n\n <EscalationFormSection\n esc={esc}\n resolverPayload={resolverPayload}\n isTerminal={isTerminal}\n claimedByMe={claimedByMe}\n activeView={activeView}\n lookup={lookupCtx}\n metadataFormSchema={metadataFormSchema}\n effectiveSchema={effectiveSchema as Record<string, unknown> | null}\n json={json}\n onJsonChange={setJson}\n requestTriage={requestTriage}\n onRequestTriageChange={setRequestTriage}\n triageNotes={triageNotes}\n onTriageNotesChange={setTriageNotes}\n onResolve={handleResolve}\n onEscalate={handleEscalate}\n onClaim={() => handleClaim(30)}\n submitAttempted={submitAttempted}\n isCertified={isCertified}\n hasAI={hasAI}\n onOpenHelp={() => {\n setSidePanelOpen(true);\n savePanelOpen(true);\n setPanelActiveView(ESCALATION_PANEL_VIEWS.HELP);\n }}\n onDisabledClick={() => setClaimNudge((n) => n + 1)}\n disabledHint={lockedFormHint}\n />\n\n <div className=\"h-10\" />\n </div>\n </>\n )}\n\n {!isIframeMode && <EscalationActionBar\n escalationContext={buildShowIfContext(esc, lookupCtx)}\n mode={actionBarMode}\n activeView={activeView}\n onActiveViewChange={setActiveView}\n onClaim={submitOnClaim ? handleClaimAndSubmit : handleClaim}\n claimPending={claim.isPending || (submitOnClaim && resolve.isPending)}\n claimNudge={claimNudge}\n workflowType={esc.workflow_type}\n json={json}\n onResolve={handleResolve}\n resolvePending={resolve.isPending || resolve.isSuccess}\n resolveError={resolve.error as Error | null}\n requestTriage={requestTriage}\n triageNotes={triageNotes}\n onRelease={handleRelease}\n releasePending={claim.isPending}\n onCancel={() => setCancelModalOpen(true)}\n assignedTo={esc.assigned_to}\n assignedUntil={esc.assigned_until}\n actingName={acting && claimedByMe ? acting.displayName : null}\n badgePrompt={scanEnabled && !acting && claimedByOther}\n onSubmitAttempt={() => setSubmitAttempted(true)}\n onValidationErrors={(errors) => {\n setFormErrors(errors);\n setSidePanelOpen(true);\n savePanelOpen(true);\n setPanelActiveView(ESCALATION_PANEL_VIEWS.ERRORS);\n }}\n labels={footerLabels}\n submitBlocked={submitGuard.blocked}\n submitBlockedMessage={submitGuard.message}\n canManage={canManage}\n onReassign={() => setReassignModalOpen(true)}\n onUnassign={() => bulkUnassign.mutate({ ids: [id] })}\n unassignPending={bulkUnassign.isPending}\n />}\n </div>\n\n <EscalationSidePanel\n esc={esc}\n schema={effectiveSchema as Record<string, unknown> | null}\n envelope={envelopeObj}\n payload={payloadObj}\n resolver={resolverObj}\n triage={triageData ?? null}\n hasAI={hasAI}\n claimed={claimed}\n claimedByMe={claimedByMe}\n isTerminal={isTerminal}\n isBuilder={isBuilder}\n traceUrl={traceUrl}\n open={sidePanelOpen}\n noGutter={isIframeMode}\n formErrors={formErrors}\n activePanel={panelActiveView}\n onPanelChange={setPanelActiveView}\n />\n\n {/* The admin hand-off: the gesture IS reassign, so takeover is implied. */}\n <BulkAssignModal\n open={reassignModalOpen}\n onClose={() => setReassignModalOpen(false)}\n selectedCount={1}\n selectedRoles={esc ? [esc.role] : []}\n onSubmit={(targetUserId, durationMinutes) =>\n bulkAssign.mutate(\n { ids: [id], targetUserId, durationMinutes, reassign: true },\n { onSuccess: () => setReassignModalOpen(false) },\n )}\n isPending={bulkAssign.isPending}\n />\n\n <ConfirmCancelModal\n open={cancelModalOpen}\n onClose={() => setCancelModalOpen(false)}\n onConfirm={handleConfirmCancel}\n isPending={cancel.isPending}\n error={cancel.error as Error | null}\n actionLabel={typeof footerLabels.cancel === 'string' ? footerLabels.cancel : undefined}\n />\n\n {/* Scan hand-off: a scanned confirm-step lands here with the pending\n action in route state; the modal asks the rule's prompt. */}\n <ScanConfirmModal escalationId={id} />\n\n {/* Transition hand-off: shown after a resolve on an x-lt-transition form,\n bridging the brief gap until the born-assigned follow-on arrives. */}\n <TransitionWaitModal\n open={!!waiting || autoStarting}\n message={waiting?.message\n ?? readTransitionConfig(effectiveSchema as Record<string, unknown> | null)?.message\n ?? 'Starting…'}\n />\n\n {claimedByMe && !isTerminal && esc.assigned_until && (\n <ClaimExpiryModal\n open={claimClock.expiringSoon && esc.assigned_until !== extendDismissedUntil}\n assignedUntil={esc.assigned_until}\n onClose={() => setExtendDismissedUntil(esc.assigned_until ?? null)}\n onExtend={handleClaim}\n isPending={claim.isPending}\n />\n )}\n </div>\n );\n}\n"],"names":["LT_ERROR_CODES","isValidationErrorBody","body","ScanConfirmModal","escalationId","location","useLocation","navigate","useNavigate","queryClient","useQueryClient","pending","_a","SCAN_PENDING_ACTION_STATE","busy","setBusy","useState","error","setError","dismissed","setDismissed","clearState","confirm","SCAN_VERBS","apiFetch","_b","_c","err","jsx","Modal","jsxs","COLORS","BAR_H","Marker","pct","place","label","title","emphasis","tick","text","Fragment","EscalationTimeline","esc","className","created","claimedAt","isResolved","isCancelled","isTerminal","activeClaim","isEffectivelyClaimed","showClaimed","end","total","pendingMs","activeMs","pendingPct","activePct","activeColor","activeVerb","split","formatDurationCompact","totalStr","totalTip","legend","TriageContext","triage","payload","confidence","confidenceColor","diffs","computeDiffs","action","i","diff","DiffRow","original","current","key","origVal","currVal","origStr","renderValue","corrStr","val","deriveFieldLabel","fieldSchema","words","w","isCapsToken","word","ESCALATION_PANEL_VIEWS","PANEL_VIEW_KEY","readPanelView","validIds","v","MetadataList","metadata","role","entries","displayMetadataEntries","value","displayValue","roleUrl","metadataFacetUrl","globalUrl","Link","ListFilter","Search","DetailsList","claimed","isBuilder","traceUrl","PanelField","StatusBadge","RolePill","User","UserName","DateValue","CountdownTimer","CopyableId","ErrorsPanel","errors","schema","focusField","field","el","message","AlertCircle","EscalationSidePanel","envelope","resolver","hasAI","claimedByMe","open","noGutter","formErrors","activePanel","onPanelChange","ALL_VIEW_IDS","internalView","setInternalView","activeView","handleViewChange","useCallback","id","useEffect","helpMarkdown","useMemo","buildHelpMarkdown","defaultHelpMarkdown","handleHelpClick","e","anchor","href","views","HelpCircle","MarkdownRenderer","Info","Sparkles","Tags","Layers","JsonViewer","Braces","SlidePanel","SlidePanelViews","INTERPOLATION_PATTERN","hasInterpolation","token","resolveCtxPath","path","ctx","dot","root","getDeep","interpolatePath","template","unresolved","concrete","_match","rawPath","X_LT_OPTIONS","isScalar","toOption","entry","o","resolveFieldOptions","staticEnum","paths","p","miss","sourcePath","resolved","cur","options","resolveChecklistItems","source","X_LT_DEFAULT_CHECKED","resolveChecklistDefault","currentValue","items","validateRequireAll","mandatory","state","incomplete","validateFieldType","declared","validateFieldConstraints","allowed","s","minLength","resolveNumericConstraint","maxLength","pattern","fmt","minimum","exclusiveMinimum","maximum","exclusiveMaximum","staticVal","dynamicPath","domain","domainObj","parts","n","validateField","isRequired","isTouched","vals","typeError","requireAll","isTruthy","asComparable","resolvePath","expr","HELP_DOMAINS","evaluateShowIf","condition","negate","neqAt","eqAt","isNeq","opAt","expected","known","matches","result","X_LT_REQUIRE_ANY","readRequireAnyGroups","raw","group","m","hasRequireAnyValue","X_LT_REQUIRE_SUM","readRequireSumGroups","groups","fields","members","requireSumContribution","validateResolverForm","formValues","properties","required","liveCtx","visible","k","titles","sum","buildResolverPayload","json","context","parsed","_form_schema","mapFormToPayload","EscalationActionBar","props","mode","onActiveViewChange","onClaim","claimPending","claimNudge","workflowType","onResolve","resolvePending","resolveError","requestTriage","triageNotes","onRelease","releasePending","onCancel","assignedTo","assignedUntil","onSubmitAttempt","onValidationErrors","escalationContext","labels","submitBlocked","submitBlockedMessage","actingName","badgePrompt","canManage","onReassign","onUnassign","unassignPending","claimDurations","useClaimDurations","duration","setDuration","customMinutes","setCustomMinutes","parseError","setParseError","isCustom","onCustomChange","guardBlocksSubmit","handleClaim","minutes","handleSubmitResolve","tabClass","active","opt","CustomDurationPicker","SectionLabel","children","RoundsExhaustedContext","resolverPayload","onRetryTriage","isRetrying","summary","diagnosis","toolCalls","ltMeta","wasTriaged","triageWorkflowId","isResolvedByTriage","showResult","setShowResult","SimpleMarkdown","safeParse","IframeViewport","src","escalation","onEscalate","submitAttempted","fill","iframeRef","useRef","iframeOrigin","url","sendInit","iframe","handler","event","data","HINT_MS","LockedFormFrame","hint","onLockedClick","hintAt","setHintAt","timer","handleClick","x","prev","Lock","FieldLabel","htmlFor","FieldHelper","FieldError","inputClass","hasError","selectClass","FileUploadWidget","fieldKey","onChange","inputRef","accept","helperText","handleFile","file","reader","hasFile","CodeEditorWidget","language","handleKeyDown","target","start","updated","SignatureWidget","canvasRef","isDrawing","setIsDrawing","canvas","img","getPos","rect","scaleX","scaleY","startDraw","pos","draw","endDraw","clear","RichTextWidget","MarkdownWidget","tab","setTab","t","CHIP_LABEL_MAX","ChecklistWidget","defaultJson","d","toggle","explicitVariant","variant","checkedCount","item","focusId","checked","showItemError","Check","IMAGE_EXT","classify","dataMime","ext","_d","AttachmentWidget","expanded","setExpanded","att","head","Paperclip","Download","ExternalLink","LinkWidget","hrefTemplate","interpolateHelp","isInternal","isEmpty","OpenDetailButton","to","ArrowUpRight","EM_DASH","resolveSourceId","renderFieldValue","format","formatAgoCompact","EscalationWidget","isLoading","isError","useEscalation","EscalationCardSkeleton","EscalationCard","rowContext","f","display","resolveQueryFacets","facets","resolveScopedQuery","query","viewerId","base","DEFAULT_COLUMNS","interpolatePayload","EscalationListWidget","rawQuery","columns","actions","user","useAuth","scoped","useEscalations","schemaNeedsEnvelope","escalations","resolve","useResolveEscalation","rowErrors","setRowErrors","pendingRow","setPendingRow","fireAction","rowCtx","ListSkeleton","EmbedTable","onAction","col","_","j","WIDGET_MAP","FieldRow","onBlur","isReadOnly","widgetName","fieldId","errorId","helpId","ariaProps","isMarkdown","isAttachment","hasRegisteredWidget","Widget","widgetRequired","widgetProps","next","selectOptions","hasCurrent","picked","FORMAT_INPUT_TYPES","FORMAT_WIDTH","staticMax","dynamicMaxPath","resolvedMax","isOverMax","DictionaryList","gridCols","formatDictionaryValue","DICTIONARY","CONTENT_WIDGETS","sectionOptionsFor","formSchema","sectionName","all","opts","isDictionaryField","widget","fieldDisplay","sectionDisplay","partitionCells","layout","cells","last","groupName","SectionGroup","name","renderField","dictionaryColumns","dictionaryItems","dictEntries","renderCells","cell","ResolverForm","disabled","onOpenHelp","onDisabledClick","disabledHint","setData","hidden","setHidden","setFormSchema","touched","setTouched","internal","emitChange","updateField","markTouched","allEntries","fieldOrder","ordered","a","b","ai","bi","requiredFields","schemaTitle","schemaDescription","hasAuthoredHelp","sectionGroups","span","isReq","ResolverSection","onJsonChange","onRequestTriageChange","onTriageNotesChange","showTriage","expandViewportSrc","parse","merged","parseJson","buildShowIfContext","lookup","EscalationContextBlocks","isRoundsExhausted","payloadObj","KeyRound","EscalationFormSection","metadataFormSchema","effectiveSchema","isCertified","showIfCtx","mapPayloadToForm","viewport","isIframeViewport","MonitorPlay","resolvedSrc","ClaimExpiryModal","onClose","onExtend","isPending","claimDuration","setClaimDuration","effectiveMinutes","CLAIM_WARNING_MS","useClaimClock","warningMs","forceTick","remaining","timers","untilWarning","msRemaining","DRAFT_KEY_PREFIX","draftKey","readDraft","saveDraft","clearDraft","X_LT_TRANSITION","X_LT_TRANSITION_MESSAGE","X_LT_TRANSITION_MAX_WAIT_SECONDS","X_LT_TRANSITION_DONE","DEFAULT_MESSAGE","DEFAULT_MAX_WAIT_SECONDS","MIN_MAX_WAIT_SECONDS","MAX_MAX_WAIT_SECONDS","clampWaitSeconds","readTransitionConfig","rawMessage","readTransitionDone","X_LT_SUBMIT_ON_CLAIM","readSubmitOnClaim","X_LT_SUBMIT_GUARD","SUBMIT_GUARD_DEFAULT_MESSAGE","readSubmitGuard","guard","useSubmitGuard","isSuccess","count","confirmedEmpty","blocked","TransitionWaitModal","createPortal","PANEL_OPEN_KEY","readPanelOpen","savePanelOpen","EscalationDetailPage","useParams","EscalationDetailView","isSuperAdmin","hasRoleType","acting","useActingIdentity","scanEnabled","useScanEnabled","effectiveActorId","refetch","isFetching","useEscalationDetailEvents","hasLookupRefs","lookupData","useEscalationLookups","lookupCtx","l","claim","useClaimEscalation","escalate","useEscalateToRole","cancel","useCancelEscalation","bulkAssign","useBulkAssignEscalations","bulkUnassign","useBulkUnassignEscalations","cancelModalOpen","setCancelModalOpen","reassignModalOpen","setReassignModalOpen","workflowConfigs","useWorkflowConfigs","settings","useSettings","useAccess","wfConfig","c","setActiveView","setJson","sidePanelOpen","setSidePanelOpen","setRequestTriage","setTriageNotes","setSubmitAttempted","setFormErrors","setClaimNudge","panelActiveView","setPanelActiveView","waiting","setWaiting","autoStarting","setAutoStarting","autoStartFiredRef","autoStartActionRef","autoResolveFiredRef","autoResolveActionRef","claimClock","extendDismissedUntil","setExtendDismissedUntil","resolverSchema","submitOnClaim","footerLabels","readFooterLabels","submitGuardDef","submitGuard","jsonInitialized","initialJsonRef","seeded","formDefaults","mergedPrefill","prefill","initial","def","fieldDef","zero","draft","draftObj","params","res","child","dest","claimedByOther","iframeViewport","isIframeMode","escalationPayload","envelopeObj","aiOverride","getAiOverride","triageData","resolverObj","actionBarMode","lockedFormHint","durationMinutes","goBack","resolveDoneDest","tmpl","navigateDone","handleResolve","ApiError","transition","doneDest","handleClaimAndSubmit","dm","handleEscalate","targetRole","handleRetryTriage","handleRelease","handleConfirmCancel","headerActions","ListToolbar","PanelRightClose","PanelRightOpen","RotateCcw","X","onClick","hoverClass","icon","PageHeader","BulkAssignModal","targetUserId","ConfirmCancelModal","_e"],"mappings":"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"}
|