@hotmeshio/long-tail 0.14.3 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -9
- package/build/api/escalations/create.js +18 -0
- package/build/api/escalations/index.d.ts +1 -0
- package/build/api/escalations/index.js +3 -1
- package/build/api/escalations/lookups.d.ts +20 -0
- package/build/api/escalations/lookups.js +90 -0
- package/build/api/escalations/metadata.d.ts +1 -1
- package/build/api/escalations/metadata.js +4 -4
- package/build/api/escalations/resolve.d.ts +1 -1
- package/build/api/escalations/resolve.js +6 -6
- package/build/api/knowledge.d.ts +9 -0
- package/build/api/knowledge.js +24 -0
- package/build/bin/ltc.js +10 -0
- package/build/index.d.ts +1 -1
- package/build/index.js +3 -2
- package/build/lib/cli/commands/escalations.d.ts +3 -0
- package/build/lib/cli/commands/escalations.js +25 -0
- package/build/lib/cli/commands/knowledge.d.ts +5 -0
- package/build/lib/cli/commands/knowledge.js +17 -2
- package/build/lib/cli/scanner.js +2 -0
- package/build/lib/db/schemas/033_knowledge_versions.sql +33 -0
- package/build/routes/escalations/single.js +10 -0
- package/build/routes/knowledge.js +35 -2
- package/build/sdk/index.d.ts +5 -0
- package/build/sdk/index.js +3 -0
- package/build/services/diagnostics/patterns.js +1 -1
- package/build/services/escalation/crud.d.ts +3 -3
- package/build/services/escalation/crud.js +9 -2
- package/build/services/escalation/resolver-validation.js +6 -0
- package/build/services/escalation/sql.d.ts +1 -1
- package/build/services/escalation/sql.js +1 -1
- package/build/services/knowledge/index.d.ts +18 -0
- package/build/services/knowledge/index.js +52 -0
- package/build/services/knowledge/lookup-cache.d.ts +29 -0
- package/build/services/knowledge/lookup-cache.js +94 -0
- package/build/services/knowledge/sql.d.ts +2 -0
- package/build/services/knowledge/sql.js +14 -0
- package/build/services/mcp/server-tools.js +30 -0
- package/build/services/orchestrator/condition.d.ts +33 -13
- package/build/services/orchestrator/condition.js +41 -14
- package/build/services/yaml-workflow/durable-compiler/parser.js +4 -1
- package/build/shared/form-validation/ctx-path.d.ts +12 -0
- package/build/shared/form-validation/ctx-path.js +56 -0
- package/build/shared/form-validation/field-validator.d.ts +4 -2
- package/build/shared/form-validation/field-validator.js +25 -19
- package/build/shared/form-validation/index.d.ts +3 -0
- package/build/shared/form-validation/index.js +3 -0
- package/build/shared/form-validation/validate-resolver-payload.d.ts +2 -0
- package/build/shared/form-validation/validate-resolver-payload.js +19 -0
- package/build/shared/form-validation/x-lt-help.d.ts +1 -1
- package/build/shared/form-validation/x-lt-help.js +2 -1
- package/build/shared/form-validation/x-lt-options.d.ts +7 -0
- package/build/shared/form-validation/x-lt-options.js +63 -0
- package/build/shared/form-validation/x-lt-require-sum.d.ts +30 -0
- package/build/shared/form-validation/x-lt-require-sum.js +59 -0
- package/build/system/activities/knowledge.d.ts +3 -0
- package/build/system/activities/knowledge.js +5 -2
- package/build/system/activities/sql.d.ts +6 -10
- package/build/system/activities/sql.js +105 -49
- package/build/system/mcp-servers/admin/schemas.d.ts +4 -4
- package/build/system/mcp-servers/knowledge.js +23 -2
- package/build/system/seed/tool-manifests-escalation.js +12 -0
- package/build/system/seed/tool-manifests-knowledge.d.ts +36 -0
- package/build/system/seed/tool-manifests-knowledge.js +15 -1
- package/build/tsconfig.tsbuildinfo +1 -1
- package/build/types/escalation.d.ts +37 -3
- package/build/types/escalation.js +42 -2
- package/dashboard/dist/assets/{AdminDashboard-BS3wd7Zg.js → AdminDashboard-BVgjY4zN.js} +2 -2
- package/dashboard/dist/assets/{AdminDashboard-BS3wd7Zg.js.map → AdminDashboard-BVgjY4zN.js.map} +1 -1
- package/dashboard/dist/assets/{AgentConfigPage-4C9aU0dj.js → AgentConfigPage-ChL59YL5.js} +6 -6
- package/dashboard/dist/assets/AgentConfigPage-ChL59YL5.js.map +1 -0
- package/dashboard/dist/assets/{AgentDetailPage-B6uvDnMF.js → AgentDetailPage-IJfgCOIF.js} +2 -2
- package/dashboard/dist/assets/AgentDetailPage-IJfgCOIF.js.map +1 -0
- package/dashboard/dist/assets/{AgentsPage-vtxdvdrQ.js → AgentsPage-C7PnPXz_.js} +2 -2
- package/dashboard/dist/assets/{AgentsPage-vtxdvdrQ.js.map → AgentsPage-C7PnPXz_.js.map} +1 -1
- package/dashboard/dist/assets/AvailableEscalationsPage-C5f2rqHa.js +2 -0
- package/dashboard/dist/assets/{AvailableEscalationsPage-C9VKPhD6.js.map → AvailableEscalationsPage-C5f2rqHa.js.map} +1 -1
- package/dashboard/dist/assets/{BotPicker-CkY9u7nD.js → BotPicker-CBf6bHLV.js} +2 -2
- package/dashboard/dist/assets/{BotPicker-CkY9u7nD.js.map → BotPicker-CBf6bHLV.js.map} +1 -1
- package/dashboard/dist/assets/{BulkAssignModal-OIbUDYlC.js → BulkAssignModal-CkxoPByA.js} +2 -2
- package/dashboard/dist/assets/{BulkAssignModal-OIbUDYlC.js.map → BulkAssignModal-CkxoPByA.js.map} +1 -1
- package/dashboard/dist/assets/CapabilitiesPage-D7USh3F0.js +2 -0
- package/dashboard/dist/assets/{CapabilitiesPage-Bkbq_GO6.js.map → CapabilitiesPage-D7USh3F0.js.map} +1 -1
- package/dashboard/dist/assets/{CollapsibleSection-Zuz9HkFL.js → CollapsibleSection-DfPpAIxa.js} +2 -2
- package/dashboard/dist/assets/{CollapsibleSection-Zuz9HkFL.js.map → CollapsibleSection-DfPpAIxa.js.map} +1 -1
- package/dashboard/dist/assets/CountdownTimer-DVL7WIcE.js +2 -0
- package/dashboard/dist/assets/CountdownTimer-DVL7WIcE.js.map +1 -0
- package/dashboard/dist/assets/{CredentialsPage-CAmDMnzV.js → CredentialsPage-BHZ5SKIu.js} +2 -2
- package/dashboard/dist/assets/{CredentialsPage-CAmDMnzV.js.map → CredentialsPage-BHZ5SKIu.js.map} +1 -1
- package/dashboard/dist/assets/{CronLabel-DX2woCPZ.js → CronLabel-wE8Hms6c.js} +2 -2
- package/dashboard/dist/assets/{CronLabel-DX2woCPZ.js.map → CronLabel-wE8Hms6c.js.map} +1 -1
- package/dashboard/dist/assets/{DropZone-7UoXQ4qL.js → DropZone-Pv-v5RAs.js} +2 -2
- package/dashboard/dist/assets/{DropZone-7UoXQ4qL.js.map → DropZone-Pv-v5RAs.js.map} +1 -1
- package/dashboard/dist/assets/{ElapsedCell-D2old1NF.js → ElapsedCell-B4VxKHpw.js} +2 -2
- package/dashboard/dist/assets/{ElapsedCell-D2old1NF.js.map → ElapsedCell-B4VxKHpw.js.map} +1 -1
- package/dashboard/dist/assets/{EntityTimelinePanel-m9baDiW0.js → EntityTimelinePanel-CFbQDHOj.js} +2 -2
- package/dashboard/dist/assets/{EntityTimelinePanel-m9baDiW0.js.map → EntityTimelinePanel-CFbQDHOj.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationListSchemaPage-BPr7Ou8c.js → EscalationListSchemaPage-YTgexl4f.js} +2 -2
- package/dashboard/dist/assets/{EscalationListSchemaPage-BPr7Ou8c.js.map → EscalationListSchemaPage-YTgexl4f.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationSchemaPage-83n5JyAh.js → EscalationSchemaPage-Sjk05eHP.js} +2 -2
- package/dashboard/dist/assets/{EscalationSchemaPage-83n5JyAh.js.map → EscalationSchemaPage-Sjk05eHP.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationsOverview-CDJ5wRlq.js → EscalationsOverview-gHWPjUpZ.js} +2 -2
- package/dashboard/dist/assets/{EscalationsOverview-CDJ5wRlq.js.map → EscalationsOverview-gHWPjUpZ.js.map} +1 -1
- package/dashboard/dist/assets/{EventTable-DRUHkKtv.js → EventTable-C9lHQ57t.js} +2 -2
- package/dashboard/dist/assets/{EventTable-DRUHkKtv.js.map → EventTable-C9lHQ57t.js.map} +1 -1
- package/dashboard/dist/assets/{FilterBar-C06DK5Oa.js → FilterBar-BY--ANxv.js} +2 -2
- package/dashboard/dist/assets/{FilterBar-C06DK5Oa.js.map → FilterBar-BY--ANxv.js.map} +1 -1
- package/dashboard/dist/assets/{GraphInvokePage-DSlyTmyq.js → GraphInvokePage-B-Oo5s-W.js} +2 -2
- package/dashboard/dist/assets/{GraphInvokePage-DSlyTmyq.js.map → GraphInvokePage-B-Oo5s-W.js.map} +1 -1
- package/dashboard/dist/assets/{HomePage-DXzDBkQV.js → HomePage-BrcjKOaJ.js} +2 -2
- package/dashboard/dist/assets/{HomePage-DXzDBkQV.js.map → HomePage-BrcjKOaJ.js.map} +1 -1
- package/dashboard/dist/assets/ListToolbar-D5TQ4X_M.js +2 -0
- package/dashboard/dist/assets/{ListToolbar-BvpGFFYp.js.map → ListToolbar-D5TQ4X_M.js.map} +1 -1
- package/dashboard/dist/assets/{McpOverview-C2atR_B6.js → McpOverview-jlukVWQ7.js} +2 -2
- package/dashboard/dist/assets/{McpOverview-C2atR_B6.js.map → McpOverview-jlukVWQ7.js.map} +1 -1
- package/dashboard/dist/assets/{McpQueryDetailPage-BUxPspjB.js → McpQueryDetailPage-BWKbvJSd.js} +3 -3
- package/dashboard/dist/assets/{McpQueryDetailPage-BUxPspjB.js.map → McpQueryDetailPage-BWKbvJSd.js.map} +1 -1
- package/dashboard/dist/assets/McpQueryPage-BH2Pon4M.js +2 -0
- package/dashboard/dist/assets/{McpQueryPage-CM_Fgl9G.js.map → McpQueryPage-BH2Pon4M.js.map} +1 -1
- package/dashboard/dist/assets/{McpRunDetailPage-Bo9vXQBA.js → McpRunDetailPage-kUnq2QSO.js} +2 -2
- package/dashboard/dist/assets/{McpRunDetailPage-Bo9vXQBA.js.map → McpRunDetailPage-kUnq2QSO.js.map} +1 -1
- package/dashboard/dist/assets/{McpRunsPage-BwsgvGtg.js → McpRunsPage-BTucgt64.js} +2 -2
- package/dashboard/dist/assets/{McpRunsPage-BwsgvGtg.js.map → McpRunsPage-BTucgt64.js.map} +1 -1
- package/dashboard/dist/assets/{NamespacePill-CKp_9EaI.js → NamespacePill-DONj6eUU.js} +2 -2
- package/dashboard/dist/assets/{NamespacePill-CKp_9EaI.js.map → NamespacePill-DONj6eUU.js.map} +1 -1
- package/dashboard/dist/assets/{OperationsPage-BftWAJ9m.js → OperationsPage-Cp8WL-ld.js} +3 -3
- package/dashboard/dist/assets/{OperationsPage-BftWAJ9m.js.map → OperationsPage-Cp8WL-ld.js.map} +1 -1
- package/dashboard/dist/assets/{OperatorDashboard-CKjrYYFi.js → OperatorDashboard-wHyeLWzX.js} +2 -2
- package/dashboard/dist/assets/{OperatorDashboard-CKjrYYFi.js.map → OperatorDashboard-wHyeLWzX.js.map} +1 -1
- package/dashboard/dist/assets/{PageHeader-CDDpHpdv.js → PageHeader-CFVw67M6.js} +2 -2
- package/dashboard/dist/assets/{PageHeader-CDDpHpdv.js.map → PageHeader-CFVw67M6.js.map} +1 -1
- package/dashboard/dist/assets/{PageHeaderWithStats-DIWH6fRv.js → PageHeaderWithStats-D9tQxILm.js} +2 -2
- package/dashboard/dist/assets/{PageHeaderWithStats-DIWH6fRv.js.map → PageHeaderWithStats-D9tQxILm.js.map} +1 -1
- package/dashboard/dist/assets/{PersonaDetailPage-BsIPtBxZ.js → PersonaDetailPage-BXlTqLDK.js} +2 -2
- package/dashboard/dist/assets/{PersonaDetailPage-BsIPtBxZ.js.map → PersonaDetailPage-BXlTqLDK.js.map} +1 -1
- package/dashboard/dist/assets/{PersonasPage-62hANmNf.js → PersonasPage-DlmdJ3Dm.js} +2 -2
- package/dashboard/dist/assets/{PersonasPage-62hANmNf.js.map → PersonasPage-DlmdJ3Dm.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessDetailPage-DS_t9DcR.js → ProcessDetailPage-D88ocvmT.js} +2 -2
- package/dashboard/dist/assets/{ProcessDetailPage-DS_t9DcR.js.map → ProcessDetailPage-D88ocvmT.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessesListPage-Ch2tSICc.js → ProcessesListPage-DpXm-KtK.js} +2 -2
- package/dashboard/dist/assets/{ProcessesListPage-Ch2tSICc.js.map → ProcessesListPage-DpXm-KtK.js.map} +1 -1
- package/dashboard/dist/assets/{RoleDetailPage-DVbtnTvn.js → RoleDetailPage-DE2Rj2QE.js} +2 -2
- package/dashboard/dist/assets/{RoleDetailPage-DVbtnTvn.js.map → RoleDetailPage-DE2Rj2QE.js.map} +1 -1
- package/dashboard/dist/assets/{RolePill-C0hExOmI.js → RolePill-Di_5hfvw.js} +2 -2
- package/dashboard/dist/assets/{RolePill-C0hExOmI.js.map → RolePill-Di_5hfvw.js.map} +1 -1
- package/dashboard/dist/assets/{RolesPage-CK6FjD5P.js → RolesPage-CZSvJlsz.js} +2 -2
- package/dashboard/dist/assets/{RolesPage-CK6FjD5P.js.map → RolesPage-CZSvJlsz.js.map} +1 -1
- package/dashboard/dist/assets/{RunAsSelector-ImueSaJ4.js → RunAsSelector-BawZcqAk.js} +2 -2
- package/dashboard/dist/assets/{RunAsSelector-ImueSaJ4.js.map → RunAsSelector-BawZcqAk.js.map} +1 -1
- package/dashboard/dist/assets/{ScanCodesPage-CDqLJuCq.js → ScanCodesPage-DSlpA9kK.js} +2 -2
- package/dashboard/dist/assets/{ScanCodesPage-CDqLJuCq.js.map → ScanCodesPage-DSlpA9kK.js.map} +1 -1
- package/dashboard/dist/assets/{ScanSchemeDetailPage-DO6qtJdM.js → ScanSchemeDetailPage-BK4hisGD.js} +2 -2
- package/dashboard/dist/assets/{ScanSchemeDetailPage-DO6qtJdM.js.map → ScanSchemeDetailPage-BK4hisGD.js.map} +1 -1
- package/dashboard/dist/assets/{ScanStationPage-ID3xMhds.js → ScanStationPage-D3QjajFD.js} +2 -2
- package/dashboard/dist/assets/{ScanStationPage-ID3xMhds.js.map → ScanStationPage-D3QjajFD.js.map} +1 -1
- package/dashboard/dist/assets/{ScopeBadge-BBQvz4pj.js → ScopeBadge-CqIIeWjK.js} +2 -2
- package/dashboard/dist/assets/{ScopeBadge-BBQvz4pj.js.map → ScopeBadge-CqIIeWjK.js.map} +1 -1
- package/dashboard/dist/assets/{StickyPagination-XA1krmz5.js → StickyPagination-BfZwU2NR.js} +2 -2
- package/dashboard/dist/assets/{StickyPagination-XA1krmz5.js.map → StickyPagination-BfZwU2NR.js.map} +1 -1
- package/dashboard/dist/assets/{StreamMessageDetail-DziA1g1e.js → StreamMessageDetail-C7zIHX5D.js} +2 -2
- package/dashboard/dist/assets/{StreamMessageDetail-DziA1g1e.js.map → StreamMessageDetail-C7zIHX5D.js.map} +1 -1
- package/dashboard/dist/assets/{SwimlaneTimeline-DTNEnHiF.js → SwimlaneTimeline-DNSo8AT8.js} +2 -2
- package/dashboard/dist/assets/{SwimlaneTimeline-DTNEnHiF.js.map → SwimlaneTimeline-DNSo8AT8.js.map} +1 -1
- package/dashboard/dist/assets/{TagInput-BXxXs1JD.js → TagInput-BLwxTNsI.js} +2 -2
- package/dashboard/dist/assets/{TagInput-BXxXs1JD.js.map → TagInput-BLwxTNsI.js.map} +1 -1
- package/dashboard/dist/assets/{TaskDetailPage-U19sJHAI.js → TaskDetailPage-BOJ8pwh3.js} +2 -2
- package/dashboard/dist/assets/{TaskDetailPage-U19sJHAI.js.map → TaskDetailPage-BOJ8pwh3.js.map} +1 -1
- package/dashboard/dist/assets/{TaskQueuePill-BKGJBVZG.js → TaskQueuePill-DVgcqd-h.js} +2 -2
- package/dashboard/dist/assets/{TaskQueuePill-BKGJBVZG.js.map → TaskQueuePill-DVgcqd-h.js.map} +1 -1
- package/dashboard/dist/assets/{TasksListPage-jc4Xk7kI.js → TasksListPage-C4CYqZf8.js} +2 -2
- package/dashboard/dist/assets/{TasksListPage-jc4Xk7kI.js.map → TasksListPage-C4CYqZf8.js.map} +1 -1
- package/dashboard/dist/assets/{TimeAgo-GWgJ0LVq.js → TimeAgo-JRPi9IEd.js} +2 -2
- package/dashboard/dist/assets/{TimeAgo-GWgJ0LVq.js.map → TimeAgo-JRPi9IEd.js.map} +1 -1
- package/dashboard/dist/assets/{TimestampCell-Dk1TVsFV.js → TimestampCell-BVYyU-nl.js} +2 -2
- package/dashboard/dist/assets/{TimestampCell-Dk1TVsFV.js.map → TimestampCell-BVYyU-nl.js.map} +1 -1
- package/dashboard/dist/assets/{ToolPill-BY6zLSfA.js → ToolPill-C6hkOqPx.js} +2 -2
- package/dashboard/dist/assets/{ToolPill-BY6zLSfA.js.map → ToolPill-C6hkOqPx.js.map} +1 -1
- package/dashboard/dist/assets/{ToolTestPanel-BKcqnR68.js → ToolTestPanel-IGrd44Au.js} +2 -2
- package/dashboard/dist/assets/{ToolTestPanel-BKcqnR68.js.map → ToolTestPanel-IGrd44Au.js.map} +1 -1
- package/dashboard/dist/assets/{TopicDetailPage-D8GcDu_0.js → TopicDetailPage-DhianNey.js} +3 -3
- package/dashboard/dist/assets/{TopicDetailPage-D8GcDu_0.js.map → TopicDetailPage-DhianNey.js.map} +1 -1
- package/dashboard/dist/assets/{TopicsPage-BT9LV3yH.js → TopicsPage-Glhqz_Nv.js} +2 -2
- package/dashboard/dist/assets/{TopicsPage-BT9LV3yH.js.map → TopicsPage-Glhqz_Nv.js.map} +1 -1
- package/dashboard/dist/assets/{UserName-BrwZnLjU.js → UserName-CD9OqhNI.js} +2 -2
- package/dashboard/dist/assets/{UserName-BrwZnLjU.js.map → UserName-CD9OqhNI.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowExecutionPage-CldfHwky.js → WorkflowExecutionPage-8Q2438Ry.js} +2 -2
- package/dashboard/dist/assets/{WorkflowExecutionPage-CldfHwky.js.map → WorkflowExecutionPage-8Q2438Ry.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowPill-qp5UF3-y.js → WorkflowPill-CN-952iI.js} +2 -2
- package/dashboard/dist/assets/{WorkflowPill-qp5UF3-y.js.map → WorkflowPill-CN-952iI.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsDashboard-DkyGkxW1.js → WorkflowsDashboard-CkAoYT86.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsDashboard-DkyGkxW1.js.map → WorkflowsDashboard-CkAoYT86.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsOverview-DACADuUE.js → WorkflowsOverview-Zh_EidMp.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsOverview-DACADuUE.js.map → WorkflowsOverview-Zh_EidMp.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-DSAjzido.js → YamlWorkflowDetailPage-BKJbFT8C.js} +2 -2
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-DSAjzido.js.map → YamlWorkflowDetailPage-BKJbFT8C.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowsPage-CqoSFz5B.js → YamlWorkflowsPage-DK1z6iFt.js} +2 -2
- package/dashboard/dist/assets/{YamlWorkflowsPage-CqoSFz5B.js.map → YamlWorkflowsPage-DK1z6iFt.js.map} +1 -1
- package/dashboard/dist/assets/{agents-Cg_e-aaf.js → agents-BEASyYpg.js} +2 -2
- package/dashboard/dist/assets/{agents-Cg_e-aaf.js.map → agents-BEASyYpg.js.map} +1 -1
- package/dashboard/dist/assets/{bots-B047yNJ0.js → bots-CaXqSHat.js} +2 -2
- package/dashboard/dist/assets/{bots-B047yNJ0.js.map → bots-CaXqSHat.js.map} +1 -1
- package/dashboard/dist/assets/{capabilities-CI1dbCDk.js → capabilities-Cijq-qev.js} +2 -2
- package/dashboard/dist/assets/{capabilities-CI1dbCDk.js.map → capabilities-Cijq-qev.js.map} +1 -1
- package/dashboard/dist/assets/{controlplane-Cy7snw7f.js → controlplane-HGuRC7AW.js} +2 -2
- package/dashboard/dist/assets/{controlplane-Cy7snw7f.js.map → controlplane-HGuRC7AW.js.map} +1 -1
- package/dashboard/dist/assets/{escalation-columns-BNrONMYj.js → escalation-columns-BLVz8XCP.js} +2 -2
- package/dashboard/dist/assets/{escalation-columns-BNrONMYj.js.map → escalation-columns-BLVz8XCP.js.map} +1 -1
- package/dashboard/dist/assets/index-BJDAXUzO.js +2 -0
- package/dashboard/dist/assets/index-BJDAXUzO.js.map +1 -0
- package/dashboard/dist/assets/{index-DVtIMrTb.js → index-CEIp6WWg.js} +2 -2
- package/dashboard/dist/assets/{index-DVtIMrTb.js.map → index-CEIp6WWg.js.map} +1 -1
- package/dashboard/dist/assets/index-CK_ohh6Q.js +3 -0
- package/dashboard/dist/assets/index-CK_ohh6Q.js.map +1 -0
- package/dashboard/dist/assets/{index-DAUV3eJ-.js → index-CLQ0HBHR.js} +2 -2
- package/dashboard/dist/assets/{index-DAUV3eJ-.js.map → index-CLQ0HBHR.js.map} +1 -1
- package/dashboard/dist/assets/{index-COKZW8Xx.js → index-Cg0vCZng.js} +2 -2
- package/dashboard/dist/assets/{index-COKZW8Xx.js.map → index-Cg0vCZng.js.map} +1 -1
- package/dashboard/dist/assets/{index-lGfBW1PB.js → index-CgXVDPW-.js} +31 -31
- package/dashboard/dist/assets/index-CgXVDPW-.js.map +1 -0
- package/dashboard/dist/assets/index-ClY0ihQ5.js +2 -0
- package/dashboard/dist/assets/{index-X3_AxcUk.js.map → index-ClY0ihQ5.js.map} +1 -1
- package/dashboard/dist/assets/{index-C_y0lQ_o.js → index-D2OU2MJb.js} +2 -2
- package/dashboard/dist/assets/{index-C_y0lQ_o.js.map → index-D2OU2MJb.js.map} +1 -1
- package/dashboard/dist/assets/{index-Bf3hVGXZ.js → index-IkgBE7e_.js} +2 -2
- package/dashboard/dist/assets/{index-Bf3hVGXZ.js.map → index-IkgBE7e_.js.map} +1 -1
- package/dashboard/dist/assets/{index-B6Grf1WQ.js → index-Xi3LO4Ye.js} +4 -4
- package/dashboard/dist/assets/{index-B6Grf1WQ.js.map → index-Xi3LO4Ye.js.map} +1 -1
- package/dashboard/dist/assets/{index-Bxd2sXqz.js → index-YMd3ZiPd.js} +2 -2
- package/dashboard/dist/assets/{index-Bxd2sXqz.js.map → index-YMd3ZiPd.js.map} +1 -1
- package/dashboard/dist/assets/{index-Uk6N1qiH.js → index-t1JXcmBG.js} +2 -2
- package/dashboard/dist/assets/{index-Uk6N1qiH.js.map → index-t1JXcmBG.js.map} +1 -1
- package/dashboard/dist/assets/{index-DyTb77Jb.js → index-tCDjx1kF.js} +2 -2
- package/dashboard/dist/assets/{index-DyTb77Jb.js.map → index-tCDjx1kF.js.map} +1 -1
- package/dashboard/dist/assets/knowledge-DpaUJtVW.js +2 -0
- package/dashboard/dist/assets/knowledge-DpaUJtVW.js.map +1 -0
- package/dashboard/dist/assets/{mcp-D889kZ-c.js → mcp-BkkLq6OE.js} +2 -2
- package/dashboard/dist/assets/{mcp-D889kZ-c.js.map → mcp-BkkLq6OE.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-query-Cs9J2pVT.js → mcp-query-DeXu3La5.js} +2 -2
- package/dashboard/dist/assets/{mcp-query-Cs9J2pVT.js.map → mcp-query-DeXu3La5.js.map} +1 -1
- package/dashboard/dist/assets/{personas-xHB16O-Q.js → personas-BRbKVVko.js} +2 -2
- package/dashboard/dist/assets/{personas-xHB16O-Q.js.map → personas-BRbKVVko.js.map} +1 -1
- package/dashboard/dist/assets/{pipelines-DnTPjw1v.js → pipelines-B7xo92sK.js} +2 -2
- package/dashboard/dist/assets/{pipelines-DnTPjw1v.js.map → pipelines-B7xo92sK.js.map} +1 -1
- package/dashboard/dist/assets/{tasks-BcDvp6dL.js → tasks-BGyqM1Ho.js} +2 -2
- package/dashboard/dist/assets/{tasks-BcDvp6dL.js.map → tasks-BGyqM1Ho.js.map} +1 -1
- package/dashboard/dist/assets/{topics-DXw6BNy5.js → topics-I81rKc75.js} +2 -2
- package/dashboard/dist/assets/{topics-DXw6BNy5.js.map → topics-I81rKc75.js.map} +1 -1
- package/dashboard/dist/assets/{useEventHooks-C-bsD8zP.js → useEventHooks-CjV3uNxt.js} +2 -2
- package/dashboard/dist/assets/{useEventHooks-C-bsD8zP.js.map → useEventHooks-CjV3uNxt.js.map} +1 -1
- package/dashboard/dist/assets/{useNamespace-wZCsEF6O.js → useNamespace-B-HMdRka.js} +2 -2
- package/dashboard/dist/assets/{useNamespace-wZCsEF6O.js.map → useNamespace-B-HMdRka.js.map} +1 -1
- package/dashboard/dist/assets/{useYamlActivityEvents-Cu_o4-ow.js → useYamlActivityEvents-CNsAlsgz.js} +2 -2
- package/dashboard/dist/assets/{useYamlActivityEvents-Cu_o4-ow.js.map → useYamlActivityEvents-CNsAlsgz.js.map} +1 -1
- package/dashboard/dist/assets/{users-XpCq_umD.js → users-DiTqBepm.js} +2 -2
- package/dashboard/dist/assets/{users-XpCq_umD.js.map → users-DiTqBepm.js.map} +1 -1
- package/dashboard/dist/assets/{vendor-icons-BgsXTN4h.js → vendor-icons-h-jlRSb9.js} +141 -146
- package/dashboard/dist/assets/vendor-icons-h-jlRSb9.js.map +1 -0
- package/dashboard/dist/assets/{workflows-CMxHVqQ8.js → workflows-TA0p_3B8.js} +2 -2
- package/dashboard/dist/assets/{workflows-CMxHVqQ8.js.map → workflows-TA0p_3B8.js.map} +1 -1
- package/dashboard/dist/assets/{yaml-workflows-kxOF5yEC.js → yaml-workflows-DN9-DBnQ.js} +2 -2
- package/dashboard/dist/assets/{yaml-workflows-kxOF5yEC.js.map → yaml-workflows-DN9-DBnQ.js.map} +1 -1
- package/dashboard/dist/index.html +2 -2
- package/docs/api/http/escalations.md +31 -8
- package/docs/api/http/knowledge.md +24 -2
- package/docs/api/http/roles.md +1 -1
- package/docs/api/mcp/admin.md +1 -1
- package/docs/api/mcp/human-queue.md +14 -0
- package/docs/api/mcp/knowledge.md +17 -1
- package/docs/api/sdk/escalations.md +38 -15
- package/docs/api/sdk/knowledge.md +27 -0
- package/docs/api/sdk/roles.md +1 -1
- package/docs/compilation.md +1 -1
- package/docs/compiler.md +2 -2
- package/docs/dashboard.md +1 -1
- package/docs/data.md +3 -3
- package/docs/hitl/escalation.md +14 -12
- package/docs/hitl/form.md +1 -0
- package/docs/hitl/iframe.md +2 -2
- package/docs/hitl/lookups.md +134 -0
- package/docs/hitl/resolution.md +4 -4
- package/docs/hitl/roles.md +4 -4
- package/docs/hitl/x-lt-show-if.md +1 -1
- package/docs/hitl/x-lt-transition.md +2 -2
- package/docs/hitl/x-lt-validation.md +64 -2
- package/docs/hitl/x-lt-widget.md +2 -2
- package/docs/hitl-guide.md +8 -2
- package/docs/story.md +1 -1
- package/package.json +1 -1
- package/dashboard/dist/assets/AgentConfigPage-4C9aU0dj.js.map +0 -1
- package/dashboard/dist/assets/AgentDetailPage-B6uvDnMF.js.map +0 -1
- package/dashboard/dist/assets/AvailableEscalationsPage-C9VKPhD6.js +0 -2
- package/dashboard/dist/assets/CapabilitiesPage-Bkbq_GO6.js +0 -2
- package/dashboard/dist/assets/CountdownTimer-CGnk4Bw_.js +0 -2
- package/dashboard/dist/assets/CountdownTimer-CGnk4Bw_.js.map +0 -1
- package/dashboard/dist/assets/ListToolbar-BvpGFFYp.js +0 -2
- package/dashboard/dist/assets/McpQueryPage-CM_Fgl9G.js +0 -2
- package/dashboard/dist/assets/index-Ds5rGe-i.js +0 -3
- package/dashboard/dist/assets/index-Ds5rGe-i.js.map +0 -1
- package/dashboard/dist/assets/index-X3_AxcUk.js +0 -2
- package/dashboard/dist/assets/index-lGfBW1PB.js.map +0 -1
- package/dashboard/dist/assets/index-nUmEwQrg.js +0 -2
- package/dashboard/dist/assets/index-nUmEwQrg.js.map +0 -1
- package/dashboard/dist/assets/knowledge-DsIUzscY.js +0 -2
- package/dashboard/dist/assets/knowledge-DsIUzscY.js.map +0 -1
- package/dashboard/dist/assets/vendor-icons-BgsXTN4h.js.map +0 -1
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# Versioned Knowledge Lookups
|
|
2
|
+
|
|
3
|
+
An escalation can pin **versioned knowledge lookups** — enumerated lists (select options, checklist items, cascade maps) that live once in the knowledge store and are referenced by thousands of rows. The refs ride the escalation; the content does not. Forms address the resolved content through the `lookup.*` context domain, so the full x-lt vocabulary works against it: `x-lt-options`, `x-lt-source`, `x-lt-showIf`, `x-lt-help`.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## The Ref
|
|
8
|
+
|
|
9
|
+
```json
|
|
10
|
+
{ "domain": "catalog", "key": "materials", "version": 2, "as": "materials" }
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
| Field | Required | Meaning |
|
|
14
|
+
|-------|----------|---------|
|
|
15
|
+
| `domain` | yes | Knowledge domain |
|
|
16
|
+
| `key` | yes | Entry key within the domain |
|
|
17
|
+
| `version` | yes | The immutable edition this escalation reads |
|
|
18
|
+
| `as` | no | The ref's form-context address, when the key alone is ambiguous |
|
|
19
|
+
|
|
20
|
+
`version` is required by design. A ref names an **immutable edition**, never a moving target: every escalation created against edition 2 renders edition 2 forever, however the entry evolves afterward. Refs live under the reserved `envelope.lookups` key — the unindexed, render-only bag beside `formDefaults`. They ride the engine's atomic write but never touch the GIN-indexed metadata surface: refs are form plumbing, not facets.
|
|
21
|
+
|
|
22
|
+
## Creating an Escalation with Lookups
|
|
23
|
+
|
|
24
|
+
Pass `lookups` to `conditional` — the same compile-time-literal discipline as `schemaVersion`:
|
|
25
|
+
|
|
26
|
+
```typescript
|
|
27
|
+
const decision = await conditional<CascadeResolverV1>(signalId, {
|
|
28
|
+
role: 'catalog-picker',
|
|
29
|
+
description: 'Pick a material for this order',
|
|
30
|
+
lookups: [
|
|
31
|
+
{ domain: 'catalog', key: 'materials', version: 2 },
|
|
32
|
+
{ domain: 'catalog', key: 'geo', version: 1 },
|
|
33
|
+
],
|
|
34
|
+
schemaVersion: 1,
|
|
35
|
+
});
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
The refs fold into `envelope.lookups` as a pure transform — a pinned wait costs exactly what an unpinned one does. A malformed ref (missing field, non-integer version) throws before the row is written; over the HTTP create surface the same validation answers with a 400.
|
|
39
|
+
|
|
40
|
+
## Versioning
|
|
41
|
+
|
|
42
|
+
Every knowledge entry carries a `current_version`, and every write that changes its data mints an immutable snapshot automatically — no publish step:
|
|
43
|
+
|
|
44
|
+
1. **Add items** — write the entry (`storeEntry`, `set_knowledge_field`, the dashboard editor). The data change bumps `current_version` and snapshots the new edition. Writes that leave the data unchanged mint nothing.
|
|
45
|
+
2. **Repin** — update the workflow's `lookups` literal to the new version, evolving the resolver payload type alongside when the new items change what the form can answer.
|
|
46
|
+
3. **Rows in flight keep their edition** — an escalation pinned to v1 renders v1's list even after v5 exists.
|
|
47
|
+
|
|
48
|
+
Inspect the lineage with `GET /api/knowledge/entry/versions?domain=catalog&key=materials`, `ltc kb versions catalog materials`, or the `list_knowledge_versions` MCP tool. Fetch a specific edition with `?version=N` on the entry endpoint.
|
|
49
|
+
|
|
50
|
+
## The Grant
|
|
51
|
+
|
|
52
|
+
The refs on the row ARE the grant. Any user who may read the escalation may fetch exactly the pinned editions it names:
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
GET /api/escalations/:id/lookups
|
|
56
|
+
→ { "lookups": [{ "domain": "catalog", "key": "materials", "version": 2, "data": { "items": [...] } }] }
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
The general knowledge API (`/api/knowledge/*`) is a builder surface — superadmin or engineer. A member never queries the knowledge store directly; the escalation-scoped endpoint serves them precisely the editions their work item carries, and nothing else. A ref whose snapshot does not exist answers with `missing: true` for that ref — the batch never fails.
|
|
60
|
+
|
|
61
|
+
## Form Addressing
|
|
62
|
+
|
|
63
|
+
The resolved refs form the `lookup` context domain, keyed by each ref's `as` (or its `key`):
|
|
64
|
+
|
|
65
|
+
```json
|
|
66
|
+
{
|
|
67
|
+
"properties": {
|
|
68
|
+
"material": {
|
|
69
|
+
"type": "string",
|
|
70
|
+
"x-lt-options": "lookup.materials.items"
|
|
71
|
+
},
|
|
72
|
+
"checks": {
|
|
73
|
+
"type": "object",
|
|
74
|
+
"x-lt-widget": "checklist",
|
|
75
|
+
"x-lt-source": "lookup.checks.items",
|
|
76
|
+
"x-lt-require-all": true
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
The entry's `data` is addressed directly — a flat option list lives at `data.items`, so the token reads `lookup.<name>.items`. Everything the context domains offer works here: `x-lt-showIf` conditions, `{{lookup.materials.items}}` in `x-lt-help`, dynamic bounds.
|
|
83
|
+
|
|
84
|
+
Membership is enforced on both sides of the wire: the dashboard constrains the choices, and an `enforce_schema` role's server gate re-resolves the same pinned editions and rejects an out-of-edition value with the canonical 422.
|
|
85
|
+
|
|
86
|
+
## Cascading Selects
|
|
87
|
+
|
|
88
|
+
An option path may embed `{{domain.path}}` interpolation segments — the same grammar as `x-lt-help` tokens — so one answer drives the next field's legal set:
|
|
89
|
+
|
|
90
|
+
```json
|
|
91
|
+
{
|
|
92
|
+
"properties": {
|
|
93
|
+
"country": { "type": "string", "x-lt-options": "lookup.geo.countries" },
|
|
94
|
+
"region": { "type": "string", "x-lt-options": "lookup.geo.regions.{{resolver.country}}" }
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
With a `catalog/geo` entry shaped as:
|
|
100
|
+
|
|
101
|
+
```json
|
|
102
|
+
{
|
|
103
|
+
"countries": ["US", "EU"],
|
|
104
|
+
"regions": {
|
|
105
|
+
"US": ["CA", "NY", "TX"],
|
|
106
|
+
"EU": ["DE", "FR", "ES"]
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
- **Region renders disabled** (an empty select on the explicit **Choose…** placeholder) until Country carries an answer.
|
|
112
|
+
- **Choosing a country enables and populates Region** with exactly that country's list — the path re-resolves against the live form on every edit.
|
|
113
|
+
- **Changing the country resets the presentation**: a previously chosen region that is no longer legal shows the placeholder again, and the stale value fails the membership pass on submit — client-side in the error panel, server-side as the 422 for enforcing roles.
|
|
114
|
+
- Chains extend naturally: C can interpolate B the same way B interpolates A, walking one nested map or several refs.
|
|
115
|
+
|
|
116
|
+
Interpolation works in `x-lt-source` the same way, so checklist item sets can follow an answer too.
|
|
117
|
+
|
|
118
|
+
## Efficiency
|
|
119
|
+
|
|
120
|
+
- **Refs, not content, ride the rows.** Thousands of escalations sharing one list each store a three-field ref; the list lives once per edition.
|
|
121
|
+
- **One fetch per page.** The resolve UI batch-fetches all refs in a single `GET /:id/lookups` call at load. Pinned editions are immutable, so the response caches for the whole session.
|
|
122
|
+
- **Zero network during execution.** Cascade levels resolve locally from the already-fetched entry data — every keystroke re-resolves in memory.
|
|
123
|
+
- **Server-side, snapshots cache indefinitely.** Enforcement reads come from an in-process LRU keyed by `(domain, key, version)`; the first row referencing an edition pays the read, every later row hits memory.
|
|
124
|
+
|
|
125
|
+
## Reference Example
|
|
126
|
+
|
|
127
|
+
`examples/workflows/lookup-cascade/` is the canonical reference:
|
|
128
|
+
|
|
129
|
+
- `material` — select from the pinned `catalog/materials` edition; the seed mints v1 (three items) then v2 (five), and seeds one escalation pinned to each, so both editions render side by side from ONE role form
|
|
130
|
+
- `country` → `region` — the cascade pair over `catalog/geo`
|
|
131
|
+
- `checks` — checklist sourced from `catalog/checks` with `x-lt-require-all`
|
|
132
|
+
- the `catalog-picker` role sets `enforce_schema: true`, so out-of-edition submissions reject server-side
|
|
133
|
+
|
|
134
|
+
Invoke `lookupCascade` with `{ "data": { "materials_version": 1 } }` (or `2`) to pin either edition per run.
|
package/docs/hitl/resolution.md
CHANGED
|
@@ -120,8 +120,8 @@ Cancellation is terminal — a cancelled escalation cannot be re-opened.
|
|
|
120
120
|
|
|
121
121
|
### When cancellation happens
|
|
122
122
|
|
|
123
|
-
- **Workflow termination** — `POST /api/workflows/:workflowId/terminate` automatically cancels any pending escalations tied to it. The waiting `
|
|
124
|
-
- **Explicit cancel** — cancel a single escalation via the API or from the dashboard. Any workflow waiting on that escalation via `
|
|
123
|
+
- **Workflow termination** — `POST /api/workflows/:workflowId/terminate` automatically cancels any pending escalations tied to it. The waiting `conditional` call returns `null`.
|
|
124
|
+
- **Explicit cancel** — cancel a single escalation via the API or from the dashboard. Any workflow waiting on that escalation via `conditional` receives `null`.
|
|
125
125
|
|
|
126
126
|
### API
|
|
127
127
|
|
|
@@ -139,10 +139,10 @@ Returns 409 if the escalation is already resolved or cancelled.
|
|
|
139
139
|
|
|
140
140
|
### Handling cancellation in workflows
|
|
141
141
|
|
|
142
|
-
`
|
|
142
|
+
`conditional` returns `T | false | null`. Always guard before accessing the payload:
|
|
143
143
|
|
|
144
144
|
```typescript
|
|
145
|
-
const decision = await
|
|
145
|
+
const decision = await conditional<{ approved: boolean }>(signalId, escalationConfig);
|
|
146
146
|
|
|
147
147
|
if (decision === null) {
|
|
148
148
|
// Escalation was cancelled
|
package/docs/hitl/roles.md
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
## Role-Based Routing
|
|
4
4
|
|
|
5
|
-
Escalations are routed by role, and any member of the role can handle them — a person working the queue in the dashboard, or a service account claiming and resolving through the API or MCP tools. Members only see escalations for roles they hold. Set `role` on every `
|
|
5
|
+
Escalations are routed by role, and any member of the role can handle them — a person working the queue in the dashboard, or a service account claiming and resolving through the API or MCP tools. Members only see escalations for roles they hold. Set `role` on every `conditional` config to name the target queue:
|
|
6
6
|
|
|
7
7
|
```typescript
|
|
8
|
-
const decision = await
|
|
8
|
+
const decision = await conditional<{ approved: boolean }>(signalId, {
|
|
9
9
|
role: 'finance-reviewer', // only users with this role see it
|
|
10
10
|
description: `Approve spend of $${amount}`,
|
|
11
11
|
// ...
|
|
@@ -25,7 +25,7 @@ A `member` of a role carries a work-surface scope that narrows what they see and
|
|
|
25
25
|
|
|
26
26
|
`self` means escalations assigned to that member (`assigned_to = user`); `all` means the whole role queue. `admin` and `superadmin` always work the whole queue.
|
|
27
27
|
|
|
28
|
-
Scope is a property of the **membership** (`lt_user_roles`), not of the escalation row. The escalation engine is unchanged — `
|
|
28
|
+
Scope is a property of the **membership** (`lt_user_roles`), not of the escalation row. The escalation engine is unchanged — `conditional` and `ltCreateEscalation` write rows exactly as before. Scope is resolved at read time when a user lists or acts on the queue.
|
|
29
29
|
|
|
30
30
|
See the [Roles API](../api/http/roles.md#work-surface-scope) for the five member profiles and the assignment contract.
|
|
31
31
|
|
|
@@ -36,7 +36,7 @@ See the [Roles API](../api/http/roles.md#work-surface-scope) for the five member
|
|
|
36
36
|
To route a single item to a named person, assign the escalation to them and provision them with `read_scope=self` + `write_scope=self`. The workflow sets `assigned_to` to the person's user ID when it creates the escalation, then provisions or updates that user as a `member` with self/self scope on the target role. They land directly on that one item — a just-in-time form scoped by RBAC — with no access to the rest of the queue.
|
|
37
37
|
|
|
38
38
|
```typescript
|
|
39
|
-
const decision = await
|
|
39
|
+
const decision = await conditional<{ confirmed: boolean; address: string }>(signalId, {
|
|
40
40
|
role: 'customer-triage',
|
|
41
41
|
assigned_to: userId, // pre-claim
|
|
42
42
|
description: 'Confirm your shipping address',
|
|
@@ -94,7 +94,7 @@ A queue that receives both regular items and a special signal type. The payload
|
|
|
94
94
|
In the workflow, guard the payload fields before accessing them:
|
|
95
95
|
|
|
96
96
|
```typescript
|
|
97
|
-
const decision = await
|
|
97
|
+
const decision = await conditional<{
|
|
98
98
|
approved: boolean;
|
|
99
99
|
rejection_reason?: string;
|
|
100
100
|
notes?: string;
|
|
@@ -35,13 +35,13 @@ commit, using the HotMesh `condition({ assignee, durationMinutes, parentId })`
|
|
|
35
35
|
primitive:
|
|
36
36
|
|
|
37
37
|
```ts
|
|
38
|
-
const step1 = await
|
|
38
|
+
const step1 = await conditional<Step1 & { $resolution?: EscalationResolution }>(sig1, {
|
|
39
39
|
role: STEP1_ROLE, /* … */ schemaVersion: 1,
|
|
40
40
|
});
|
|
41
41
|
const owner = step1.$resolution?.resolvedBy; // who resolved step 1
|
|
42
42
|
const parent = step1.$resolution?.escalationId; // step 1's id — the correlation key
|
|
43
43
|
|
|
44
|
-
await
|
|
44
|
+
await conditional<Step2>(sig2, {
|
|
45
45
|
role: STEP2_ROLE,
|
|
46
46
|
assignee: owner, // born assigned — no create-then-claim race
|
|
47
47
|
durationMinutes: 30, // a hard claim, so it stays with the owner
|
|
@@ -93,6 +93,37 @@ When `envelope.min_score` is `60`, submitting a score of `45` blocks with "Minim
|
|
|
93
93
|
|
|
94
94
|
---
|
|
95
95
|
|
|
96
|
+
## Dynamic Select Options (`x-lt-options`)
|
|
97
|
+
|
|
98
|
+
A select's option list can ride the escalation instead of the schema. The field-level token names a `"domain.path"`; the array of strings or numbers at that path becomes the field's options — one static role form, per-row legal values:
|
|
99
|
+
|
|
100
|
+
```json
|
|
101
|
+
{
|
|
102
|
+
"properties": {
|
|
103
|
+
"left_quantity": {
|
|
104
|
+
"type": "number",
|
|
105
|
+
"default": 0,
|
|
106
|
+
"x-lt-options": "envelope.left_quantity_options"
|
|
107
|
+
},
|
|
108
|
+
"designation": {
|
|
109
|
+
"type": "string",
|
|
110
|
+
"x-lt-options": "envelope.return_stations"
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
When the envelope carries `left_quantity_options: [0, 1, 2, 3]`, the field renders as a dropdown offering exactly those values — an out-of-range answer is structurally impossible. The workflow mints only the small per-row array; the form itself stays on the role.
|
|
117
|
+
|
|
118
|
+
- A static `enum` takes precedence when both are present — the same static-over-dynamic rule as the bounds tokens.
|
|
119
|
+
- The declared `type` governs the value: a number-typed field emits the picked option as a number, a string-typed field as a string.
|
|
120
|
+
- While the current value is outside the option list (an empty init, options that shrank per-row), the select opens on an explicit disabled **Choose…** placeholder — never an implicit first option.
|
|
121
|
+
- A path that resolves to nothing (missing, empty array, no scalar entries) yields no options: the field renders as the plain input for its type and membership is not enforced for that submission.
|
|
122
|
+
- Membership is enforced on both sides of the wire: the dashboard constrains the choices, and an enforced role's server gate rejects a payload whose value is outside the row's resolved list with the canonical 422 (`Must be one of: 0, 1, 2, 3`).
|
|
123
|
+
- Option lists can also come from version-pinned knowledge entries (the `lookup` domain), and paths may embed `{{domain.path}}` interpolation segments for cascading selects — a dependent select whose parent is unanswered renders disabled and fails closed. See [lookups.md](lookups.md).
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
96
127
|
## Checklist Completion (`x-lt-require-all`)
|
|
97
128
|
|
|
98
129
|
A checklist-widget field can require every item to be checked before submission:
|
|
@@ -143,6 +174,29 @@ The token is an array of groups; each group is an array of property names and en
|
|
|
143
174
|
|
|
144
175
|
---
|
|
145
176
|
|
|
177
|
+
## Require a Combined Quantity (`x-lt-require-sum`)
|
|
178
|
+
|
|
179
|
+
For a group of **quantity** fields, `x-lt-require-any` is the wrong guard: `0` is an answer there, so counts defaulting to `0` vacuously satisfy the group. `x-lt-require-sum` reads the members as numbers and demands their sum reach a minimum — a Left quantity and a Right quantity can both default to `0`, and an all-zero submission still blocks:
|
|
180
|
+
|
|
181
|
+
```json
|
|
182
|
+
{
|
|
183
|
+
"x-lt-require-sum": [{ "fields": ["left_quantity", "right_quantity"] }],
|
|
184
|
+
"properties": {
|
|
185
|
+
"left_quantity": { "type": "number", "title": "Left Quantity", "default": 0 },
|
|
186
|
+
"right_quantity": { "type": "number", "title": "Right Quantity", "default": 0 }
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
The token is an array of groups; each group is `{ "fields": [...], "minimum": N }` and enforces independently. `minimum` defaults to `1` — the plain "at least one side must be positive" reading. Numbers contribute their value, numeric strings coerce, and everything else (empty, missing, non-numeric) contributes `0`.
|
|
192
|
+
|
|
193
|
+
- Visibility composes the same way as `x-lt-require-any`: a member hidden by `x-lt-showIf` (or naming no schema property) contributes nothing and is not demanded, and a group whose members are all hidden is waived.
|
|
194
|
+
- An unsatisfied group yields one violation on the group's first visible field: `Combined value of Left Quantity, Right Quantity must be at least 1` (member titles, falling back to keys).
|
|
195
|
+
- Composes with `required` and `x-lt-require-any` — each guard reports independently.
|
|
196
|
+
- The same pass runs on both sides of the wire — the dashboard panel blocks the submit, and an enforced role's server gate rejects a violating payload with the canonical 422.
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
146
200
|
## Pattern Guard
|
|
147
201
|
|
|
148
202
|
Apply a regular expression guard with `pattern`. If the input does not match, the field blocks submission. Provide `x-lt-pattern-error` for a human-readable error message; otherwise the generic "Invalid format" is shown.
|
|
@@ -163,7 +217,7 @@ Apply a regular expression guard with `pattern`. If the input does not match, th
|
|
|
163
217
|
|
|
164
218
|
## Dynamic Bounds — `"domain.path"` Resolution
|
|
165
219
|
|
|
166
|
-
`x-lt-minimum`, `x-lt-maximum`, `x-lt-min-length`,
|
|
220
|
+
`x-lt-minimum`, `x-lt-maximum`, `x-lt-min-length`, `x-lt-max-length`, and `x-lt-options` all accept a `"domain.path"` string. The value is resolved from the escalation context at the moment of submission — the same domain/path convention as `x-lt-showIf` and `x-lt-help` tokens.
|
|
167
221
|
|
|
168
222
|
| Domain | Resolves against |
|
|
169
223
|
|--------|-----------------|
|
|
@@ -177,7 +231,7 @@ The path is dot-separated, with optional `[n]` array indices. A missing or non-n
|
|
|
177
231
|
**Workflow side — passing the bound in the envelope:**
|
|
178
232
|
|
|
179
233
|
```typescript
|
|
180
|
-
const decision = await
|
|
234
|
+
const decision = await conditional<{ score: number; notes: string }>(signalId, {
|
|
181
235
|
role: 'quality-reviewer',
|
|
182
236
|
envelope: {
|
|
183
237
|
min_score: 60,
|
|
@@ -216,3 +270,11 @@ The error panel updates in real-time as fields are corrected — fixing a field
|
|
|
216
270
|
- `checks` — checklist widget with `x-lt-source: 'envelope.checklist_items'`
|
|
217
271
|
|
|
218
272
|
The `quality-reviewer` role is seeded with two test escalations that carry different `min_score` and `max_notes_length` values so every dynamic bound is exercisable without code changes.
|
|
273
|
+
|
|
274
|
+
`examples/workflows/parameterized-form/` is the reference for per-row form parameterization:
|
|
275
|
+
|
|
276
|
+
- `left_quantity` / `right_quantity` — number selects with `x-lt-options` from `envelope.left_quantity_options` / `envelope.right_quantity_options`, both defaulting to `0`
|
|
277
|
+
- `designation` — string select with `x-lt-options` from `envelope.return_stations`
|
|
278
|
+
- `x-lt-require-sum` — the quantity pair must total at least 1
|
|
279
|
+
|
|
280
|
+
The `verdict-reviewer` role is seeded with two test escalations whose envelopes carry different quantity ranges and station lists, so the same role form offers different legal values per row.
|
package/docs/hitl/x-lt-widget.md
CHANGED
|
@@ -144,7 +144,7 @@ The field type must be `"object"`. The submitted value is `Record<string, boolea
|
|
|
144
144
|
|
|
145
145
|
`x-lt-source` uses the `"domain.path"` convention (same as `x-lt-showIf` and `x-lt-help` tokens). The renderer expects an array of `{ id: string; label: string; required?: boolean }` objects at that path.
|
|
146
146
|
|
|
147
|
-
- `"envelope"` — for item definitions that are render data only (no query cost). The workflow puts them in `
|
|
147
|
+
- `"envelope"` — for item definitions that are render data only (no query cost). The workflow puts them in `conditional`'s `envelope` parameter.
|
|
148
148
|
- `"metadata"` — only when items need to be GIN-indexed and searchable as facets. Adds index cost.
|
|
149
149
|
|
|
150
150
|
### Geometry (`x-lt-variant`)
|
|
@@ -191,7 +191,7 @@ const checklistItems = [
|
|
|
191
191
|
{ id: 'photos', label: 'Before/after photos are present', required: false },
|
|
192
192
|
];
|
|
193
193
|
|
|
194
|
-
const decision = await
|
|
194
|
+
const decision = await conditional<{ checks: Record<string, boolean> }>(signalId, {
|
|
195
195
|
role: 'checklist-operator',
|
|
196
196
|
envelope: {
|
|
197
197
|
checklist_items: checklistItems,
|
package/docs/hitl-guide.md
CHANGED
|
@@ -16,6 +16,7 @@ This works because the form is data: a JSON Schema stored on the role, versioned
|
|
|
16
16
|
|----------|-----|-----|
|
|
17
17
|
| Typed fields, formats, required | Plain JSON Schema | [form.md](hitl/form.md) |
|
|
18
18
|
| Input guards (bounds, patterns, dynamic limits) | Validation keywords | [x-lt-validation.md](hitl/x-lt-validation.md) |
|
|
19
|
+
| Option lists shared by thousands of rows, cascading selects | Versioned lookups | [lookups.md](hitl/lookups.md) |
|
|
19
20
|
| Fields that appear based on another answer | `x-lt-showIf` | [x-lt-show-if.md](hitl/x-lt-show-if.md) |
|
|
20
21
|
| Sections, columns, ordering, side-panel help | Layout keywords | [x-lt-layout.md](hitl/x-lt-layout.md) |
|
|
21
22
|
| Runtime-driven items, files, signatures, SOP blocks | Widgets | [x-lt-widget.md](hitl/x-lt-widget.md) |
|
|
@@ -65,6 +66,7 @@ When you author a HITL-backed workflow, the platform handles:
|
|
|
65
66
|
- **AI triage** — optional auto-resolution for common patterns
|
|
66
67
|
- **Credential security** — password fields use ephemeral tokens, never stored in plain text
|
|
67
68
|
- **Schema enforcement** — roles with `enforce_schema` validate every resolver payload server-side (dashboard, API, MCP, CLI alike) with the same pass the form runs, rejecting violations as a structured 422 (see [schema-enforcement.md](schema-enforcement.md))
|
|
69
|
+
- **Versioned lookups** — escalations pin immutable knowledge editions for their option lists; the refs grant readers exactly those editions, and cascading selects resolve locally from one batch fetch (see [lookups.md](hitl/lookups.md))
|
|
68
70
|
- **Telemetry** — trace IDs link escalations to OpenTelemetry traces
|
|
69
71
|
- **Bulk operations** — bulk claim, assign, triage, and cancel for queue management
|
|
70
72
|
- **Cancellation** — cancel pending escalations from the API or dashboard
|
|
@@ -79,7 +81,8 @@ Ordered as a learning path — each file adds one capability to the same form:
|
|
|
79
81
|
|
|
80
82
|
| Topic | File |
|
|
81
83
|
|-------|------|
|
|
82
|
-
| Creating escalations with `
|
|
84
|
+
| Creating escalations with `conditional`, schema versioning | [escalation.md](hitl/escalation.md) |
|
|
85
|
+
| Versioned knowledge lookups, the `lookup.*` domain, cascading selects | [lookups.md](hitl/lookups.md) |
|
|
83
86
|
| Field types, formats, required, read-only | [form.md](hitl/form.md) |
|
|
84
87
|
| Pre-submission validation guards (min, max, pattern, dynamic bounds) | [x-lt-validation.md](hitl/x-lt-validation.md) |
|
|
85
88
|
| Conditional visibility (`x-lt-showIf`, `x-lt-hide-if-empty`) | [x-lt-show-if.md](hitl/x-lt-show-if.md) |
|
|
@@ -101,8 +104,10 @@ Ordered as a learning path — each file adds one capability to the same form:
|
|
|
101
104
|
| Keyword | Level | Purpose |
|
|
102
105
|
|---------|-------|---------|
|
|
103
106
|
| `x-lt-widget` | field | Rich control: `file-upload`, `code-editor`, `signature`, `rich-text`, `markdown`, `checklist`, `attachment` (alias `image`) |
|
|
104
|
-
| `x-lt-source` | field | Data path for context-driven widgets: `"domain.path"` |
|
|
107
|
+
| `x-lt-source` | field | Data path for context-driven widgets: `"domain.path"`; may embed `{{domain.path}}` interpolation segments |
|
|
105
108
|
| `x-lt-require-all` | field | Checklist completion guard — every item must be checked, except items declared `required: false` |
|
|
109
|
+
| `x-lt-require-any` | schema | At-least-one guard — each `string[]` group needs a value in one visible member; `0`/`false` count as answers |
|
|
110
|
+
| `x-lt-require-sum` | schema | Quantity-group guard — the numeric values of `{ fields, minimum? }` must total at least `minimum` (default 1) |
|
|
106
111
|
| `x-lt-language` | field | Syntax hint for the `code-editor` widget |
|
|
107
112
|
| `accept` | field | File-type filter for `file-upload` (e.g. `".pdf,.png"`) |
|
|
108
113
|
| `x-lt-bind` | field | Path in the resolver payload (e.g. `"customer.email"`) |
|
|
@@ -110,6 +115,7 @@ Ordered as a learning path — each file adds one capability to the same form:
|
|
|
110
115
|
| `x-lt-showIf` | field | Show field when a value is truthy at `domain.path`; prefix `!` to invert; `=VALUE` / `!=VALUE` compare the string form |
|
|
111
116
|
| `x-lt-hide-if-empty` | field | `true` — suppress the field when its value is null, `""`, `false`, or `0` |
|
|
112
117
|
| `x-lt-section` | field | Section group label |
|
|
118
|
+
| `x-lt-options` | field | Dynamic select options — resolves a `"domain.path"` to the field's option list; static `enum` wins; `{{domain.path}}` segments make cascading selects |
|
|
113
119
|
| `x-lt-minimum` | field | Dynamic lower bound — resolves a `"domain.path"` from the escalation context |
|
|
114
120
|
| `x-lt-maximum` | field | Dynamic upper bound — resolves a `"domain.path"` from the escalation context |
|
|
115
121
|
| `x-lt-min-length` | field | Dynamic minimum string length — resolves a `"domain.path"` |
|
package/docs/story.md
CHANGED
|
@@ -120,7 +120,7 @@ Each capability shows who uses it: which agents, which pipelines, which workflow
|
|
|
120
120
|
|
|
121
121
|
The orchestration backstage — the same durable workflow, offered two ways:
|
|
122
122
|
|
|
123
|
-
- **Procedural** — readable,
|
|
123
|
+
- **Procedural** — readable, durable TypeScript. Configure it, invoke it, watch its executions. Emulated atop the graph: cheap to maintain, heavier to run.
|
|
124
124
|
- **Graph** — that same workflow as a compiled, deterministic DAG. Same guarantees, roughly 3x faster, less to read. Run or schedule it; the router discovers it and pulls the work when it's healthy to.
|
|
125
125
|
|
|
126
126
|
Every procedural pattern has a graph equivalent and the reverse, so the choice is readability or speed — never durability, escalation, or transactional safety. Engineers move freely between them: execution traces, durable cycle replay, swimlane timelines. Nothing is hidden. The technical depth is the product.
|
package/package.json
CHANGED