@hotmeshio/long-tail 0.27.0 → 0.28.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (386) hide show
  1. package/README.md +9 -2
  2. package/build/api/files.d.ts +5 -0
  3. package/build/api/files.js +19 -2
  4. package/build/api/knowledge.d.ts +3 -1
  5. package/build/api/settings.d.ts +4 -1
  6. package/build/api/settings.js +7 -1
  7. package/build/index.js +9 -4
  8. package/build/lib/db/config-lock.d.ts +10 -0
  9. package/build/lib/db/config-lock.js +28 -0
  10. package/build/lib/db/schemas/041_machine_lines.sql +26 -0
  11. package/build/lib/db/schemas/042_knowledge_edition_labels.sql +9 -0
  12. package/build/lib/events/browser-view.js +8 -2
  13. package/build/lib/events/publish.d.ts +33 -0
  14. package/build/lib/events/publish.js +52 -1
  15. package/build/lib/machines/line.d.ts +7 -1
  16. package/build/lib/machines/line.js +25 -2
  17. package/build/lib/machines/protocol/codec.d.ts +14 -0
  18. package/build/lib/machines/protocol/codec.js +10 -1
  19. package/build/lib/machines/protocol/constants.d.ts +1 -1
  20. package/build/lib/machines/protocol/constants.js +1 -1
  21. package/build/lib/machines/protocol/contract.d.ts +2 -0
  22. package/build/lib/machines/protocol/contract.js +13 -8
  23. package/build/lib/machines/site/mosquitto-conf.d.ts +9 -4
  24. package/build/lib/machines/site/mosquitto-conf.js +32 -22
  25. package/build/lib/machines/site/site-conf.d.ts +13 -3
  26. package/build/lib/machines/site/site-conf.js +31 -8
  27. package/build/lib/machines/transport/callback-feed.d.ts +1 -0
  28. package/build/lib/machines/transport/callback-feed.js +4 -1
  29. package/build/lib/machines/transport/memory.d.ts +2 -0
  30. package/build/lib/machines/transport/memory.js +6 -0
  31. package/build/lib/machines/transport/mqtt-bus.d.ts +2 -0
  32. package/build/lib/machines/transport/mqtt-bus.js +4 -0
  33. package/build/lib/machines/transport/nats-bus.d.ts +3 -0
  34. package/build/lib/machines/transport/nats-bus.js +3 -0
  35. package/build/lib/machines/transport/nats-feed.d.ts +1 -0
  36. package/build/lib/machines/transport/nats-feed.js +4 -1
  37. package/build/lib/machines/transport/pubsub-feed.d.ts +1 -0
  38. package/build/lib/machines/transport/pubsub-feed.js +4 -1
  39. package/build/lib/machines/transport/stream-bus.d.ts +7 -1
  40. package/build/lib/machines/transport/stream-bus.js +17 -5
  41. package/build/lib/machines/transport/streams.d.ts +10 -2
  42. package/build/lib/machines/transport/streams.js +32 -5
  43. package/build/lib/messaging/memory.js +3 -0
  44. package/build/lib/messaging/nats/streams.d.ts +3 -0
  45. package/build/lib/messaging/nats/streams.js +16 -0
  46. package/build/lib/storage/local.d.ts +2 -0
  47. package/build/lib/storage/local.js +3 -0
  48. package/build/lib/storage/s3.d.ts +3 -2
  49. package/build/lib/storage/s3.js +6 -1
  50. package/build/lib/storage/types.d.ts +7 -1
  51. package/build/modules/machines.d.ts +8 -0
  52. package/build/modules/machines.js +16 -0
  53. package/build/routes/file-browser.js +3 -1
  54. package/build/routes/index.js +2 -0
  55. package/build/routes/knowledge.js +6 -5
  56. package/build/routes/machines.d.ts +2 -0
  57. package/build/routes/machines.js +253 -0
  58. package/build/services/knowledge/index.d.ts +4 -2
  59. package/build/services/knowledge/index.js +8 -2
  60. package/build/services/knowledge/lookup-cache.d.ts +8 -0
  61. package/build/services/knowledge/lookup-cache.js +30 -3
  62. package/build/services/knowledge/lookup-refs.js +1 -1
  63. package/build/services/knowledge/sql.d.ts +4 -2
  64. package/build/services/knowledge/sql.js +8 -3
  65. package/build/services/machines/commands.d.ts +5 -5
  66. package/build/services/machines/commands.js +3 -2
  67. package/build/services/machines/config.d.ts +4 -1
  68. package/build/services/machines/config.js +2 -1
  69. package/build/services/machines/contracts.d.ts +28 -0
  70. package/build/services/machines/contracts.js +15 -1
  71. package/build/services/machines/forms.d.ts +26 -1
  72. package/build/services/machines/forms.js +17 -1
  73. package/build/services/machines/gateway/actions.d.ts +14 -1
  74. package/build/services/machines/gateway/admission.d.ts +30 -4
  75. package/build/services/machines/gateway/admission.js +76 -14
  76. package/build/services/machines/gateway/api-escalations.js +4 -0
  77. package/build/services/machines/gateway/dispatcher.d.ts +12 -4
  78. package/build/services/machines/gateway/dispatcher.js +53 -17
  79. package/build/services/machines/gateway/executor.d.ts +13 -2
  80. package/build/services/machines/gateway/executor.js +84 -29
  81. package/build/services/machines/gateway/gateway.d.ts +21 -1
  82. package/build/services/machines/gateway/gateway.js +65 -25
  83. package/build/services/machines/gateway/index.d.ts +3 -0
  84. package/build/services/machines/gateway/index.js +3 -0
  85. package/build/services/machines/gateway/inspect.d.ts +17 -0
  86. package/build/services/machines/gateway/inspect.js +68 -0
  87. package/build/services/machines/gateway/log.d.ts +10 -0
  88. package/build/services/machines/gateway/log.js +20 -0
  89. package/build/services/machines/gateway/lt-http.js +11 -2
  90. package/build/services/machines/gateway/pacing.js +2 -1
  91. package/build/services/machines/gateway/plan-escalation.js +8 -3
  92. package/build/services/machines/gateway/plan-machine.js +41 -16
  93. package/build/services/machines/gateway/plan-shared.d.ts +5 -3
  94. package/build/services/machines/gateway/plan-shared.js +6 -4
  95. package/build/services/machines/gateway/project.d.ts +9 -0
  96. package/build/services/machines/gateway/project.js +55 -0
  97. package/build/services/machines/gateway/receipts.d.ts +3 -0
  98. package/build/services/machines/gateway/receipts.js +3 -1
  99. package/build/services/machines/gateway/reconcile.js +3 -3
  100. package/build/services/machines/gateway/registration.js +1 -1
  101. package/build/services/machines/gateway/reply-waiter.d.ts +8 -3
  102. package/build/services/machines/gateway/reply-waiter.js +37 -16
  103. package/build/services/machines/gateway/state.d.ts +53 -4
  104. package/build/services/machines/gateway/state.js +128 -13
  105. package/build/services/machines/gateway/wire-window.d.ts +21 -0
  106. package/build/services/machines/gateway/wire-window.js +61 -0
  107. package/build/services/machines/gateway/wire.d.ts +58 -0
  108. package/build/services/machines/gateway/wire.js +172 -0
  109. package/build/services/machines/index.d.ts +3 -0
  110. package/build/services/machines/index.js +2 -0
  111. package/build/services/machines/line-index.d.ts +16 -0
  112. package/build/services/machines/line-index.js +39 -0
  113. package/build/services/machines/registry-sql.d.ts +31 -0
  114. package/build/services/machines/registry-sql.js +110 -0
  115. package/build/services/machines/registry-sync.d.ts +31 -0
  116. package/build/services/machines/registry-sync.js +81 -0
  117. package/build/services/machines/registry.d.ts +77 -0
  118. package/build/services/machines/registry.js +158 -0
  119. package/build/services/machines/roles.d.ts +5 -4
  120. package/build/services/machines/roles.js +13 -4
  121. package/build/services/machines/rows.js +10 -1
  122. package/build/services/machines/select.d.ts +3 -2
  123. package/build/services/machines/select.js +4 -3
  124. package/build/services/machines/surface.d.ts +54 -5
  125. package/build/services/machines/surface.js +113 -17
  126. package/build/start/apply-report.d.ts +1 -1
  127. package/build/start/apply-report.js +3 -25
  128. package/build/start/index.js +16 -4
  129. package/build/system/activities/knowledge.d.ts +4 -0
  130. package/build/system/activities/knowledge.js +15 -0
  131. package/build/system/activities/sql.d.ts +2 -0
  132. package/build/system/activities/sql.js +6 -1
  133. package/build/system/index.js +13 -0
  134. package/build/system/mcp-servers/admin/schemas.d.ts +22 -22
  135. package/build/system/mcp-servers/human-queue-schemas.d.ts +7 -7
  136. package/build/system/mcp-servers/knowledge.js +4 -2
  137. package/build/system/mcp-servers/machines-schemas.d.ts +35 -0
  138. package/build/system/mcp-servers/machines-schemas.js +35 -0
  139. package/build/system/mcp-servers/machines.d.ts +20 -0
  140. package/build/system/mcp-servers/machines.js +154 -0
  141. package/build/system/seed/tool-manifests-machines.d.ts +2 -0
  142. package/build/system/seed/tool-manifests-machines.js +88 -0
  143. package/build/tsconfig.tsbuildinfo +1 -1
  144. package/build/types/escalation.d.ts +9 -6
  145. package/build/types/escalation.js +8 -2
  146. package/build/types/events.d.ts +6 -1
  147. package/build/types/index.d.ts +1 -0
  148. package/build/types/machines-view.d.ts +175 -0
  149. package/build/types/machines-view.js +7 -0
  150. package/build/types/machines.d.ts +5 -0
  151. package/build/types/messaging.d.ts +2 -0
  152. package/build/types/startup.d.ts +2 -0
  153. package/dashboard/dist/assets/{AdminDashboard-DlItqxFS.js → AdminDashboard-Bm7VG65H.js} +2 -2
  154. package/dashboard/dist/assets/{AdminDashboard-DlItqxFS.js.map → AdminDashboard-Bm7VG65H.js.map} +1 -1
  155. package/dashboard/dist/assets/{AgentConfigPage-BUmT4a7n.js → AgentConfigPage-aJF7Sdbc.js} +6 -6
  156. package/dashboard/dist/assets/{AgentConfigPage-BUmT4a7n.js.map → AgentConfigPage-aJF7Sdbc.js.map} +1 -1
  157. package/dashboard/dist/assets/{AgentDetailPage-Cww8rlBi.js → AgentDetailPage-GwwghhxT.js} +3 -3
  158. package/dashboard/dist/assets/{AgentDetailPage-Cww8rlBi.js.map → AgentDetailPage-GwwghhxT.js.map} +1 -1
  159. package/dashboard/dist/assets/AgentsPage-DVvCzZyg.js +2 -0
  160. package/dashboard/dist/assets/{AgentsPage-C9UuUKhr.js.map → AgentsPage-DVvCzZyg.js.map} +1 -1
  161. package/dashboard/dist/assets/AvailableEscalationsPage-Cxmcji_K.js +2 -0
  162. package/dashboard/dist/assets/{AvailableEscalationsPage-DrvfXz70.js.map → AvailableEscalationsPage-Cxmcji_K.js.map} +1 -1
  163. package/dashboard/dist/assets/{BotPicker-CDq9XRMp.js → BotPicker-CofRxk4L.js} +2 -2
  164. package/dashboard/dist/assets/{BotPicker-CDq9XRMp.js.map → BotPicker-CofRxk4L.js.map} +1 -1
  165. package/dashboard/dist/assets/{BulkAssignModal-jsvqtrEA.js → BulkAssignModal-BARWuz4L.js} +2 -2
  166. package/dashboard/dist/assets/{BulkAssignModal-jsvqtrEA.js.map → BulkAssignModal-BARWuz4L.js.map} +1 -1
  167. package/dashboard/dist/assets/{CapabilitiesPage-CSCrI6B1.js → CapabilitiesPage-BJAWVNEx.js} +2 -2
  168. package/dashboard/dist/assets/{CapabilitiesPage-CSCrI6B1.js.map → CapabilitiesPage-BJAWVNEx.js.map} +1 -1
  169. package/dashboard/dist/assets/{CollapsibleSection-uD9mn-CQ.js → CollapsibleSection-CtgoaG75.js} +2 -2
  170. package/dashboard/dist/assets/{CollapsibleSection-uD9mn-CQ.js.map → CollapsibleSection-CtgoaG75.js.map} +1 -1
  171. package/dashboard/dist/assets/{ConfirmDeleteModal-BRmx2hA4.js → ConfirmDeleteModal-BYXXBWs6.js} +2 -2
  172. package/dashboard/dist/assets/{ConfirmDeleteModal-BRmx2hA4.js.map → ConfirmDeleteModal-BYXXBWs6.js.map} +1 -1
  173. package/dashboard/dist/assets/{ConnectedAppsPage-DlMzE5a-.js → ConnectedAppsPage-D0JkzWa7.js} +2 -2
  174. package/dashboard/dist/assets/{ConnectedAppsPage-DlMzE5a-.js.map → ConnectedAppsPage-D0JkzWa7.js.map} +1 -1
  175. package/dashboard/dist/assets/{CountdownTimer-sRuM4eM5.js → CountdownTimer-BcFxdZYN.js} +2 -2
  176. package/dashboard/dist/assets/{CountdownTimer-sRuM4eM5.js.map → CountdownTimer-BcFxdZYN.js.map} +1 -1
  177. package/dashboard/dist/assets/{CredentialsPage-bLYydwqa.js → CredentialsPage-DPSY20rV.js} +2 -2
  178. package/dashboard/dist/assets/{CredentialsPage-bLYydwqa.js.map → CredentialsPage-DPSY20rV.js.map} +1 -1
  179. package/dashboard/dist/assets/{CronLabel-D_ATDL2N.js → CronLabel-Dg_Oew_Y.js} +2 -2
  180. package/dashboard/dist/assets/{CronLabel-D_ATDL2N.js.map → CronLabel-Dg_Oew_Y.js.map} +1 -1
  181. package/dashboard/dist/assets/{DropZone-u1JGfR9G.js → DropZone-Cl_Flb16.js} +2 -2
  182. package/dashboard/dist/assets/{DropZone-u1JGfR9G.js.map → DropZone-Cl_Flb16.js.map} +1 -1
  183. package/dashboard/dist/assets/{ElapsedCell-groSMfqB.js → ElapsedCell-Dm3G5fK2.js} +2 -2
  184. package/dashboard/dist/assets/{ElapsedCell-groSMfqB.js.map → ElapsedCell-Dm3G5fK2.js.map} +1 -1
  185. package/dashboard/dist/assets/{EntityTimelinePanel-D-F3_A9m.js → EntityTimelinePanel-CrEEP04e.js} +2 -2
  186. package/dashboard/dist/assets/{EntityTimelinePanel-D-F3_A9m.js.map → EntityTimelinePanel-CrEEP04e.js.map} +1 -1
  187. package/dashboard/dist/assets/{EscalationListSchemaPage-Bad6Jrmr.js → EscalationListSchemaPage-wOInXcjs.js} +3 -3
  188. package/dashboard/dist/assets/{EscalationListSchemaPage-Bad6Jrmr.js.map → EscalationListSchemaPage-wOInXcjs.js.map} +1 -1
  189. package/dashboard/dist/assets/{EscalationSchemaPage-BKi_npI9.js → EscalationSchemaPage-CrIj_g9d.js} +3 -3
  190. package/dashboard/dist/assets/{EscalationSchemaPage-BKi_npI9.js.map → EscalationSchemaPage-CrIj_g9d.js.map} +1 -1
  191. package/dashboard/dist/assets/{EscalationTimeline-DQUUm3b1.js → EscalationTimeline-CeAsl5IT.js} +2 -2
  192. package/dashboard/dist/assets/{EscalationTimeline-DQUUm3b1.js.map → EscalationTimeline-CeAsl5IT.js.map} +1 -1
  193. package/dashboard/dist/assets/{EscalationTitleSelect-3mhXh77a.js → EscalationTitleSelect-D8qpCYiy.js} +2 -2
  194. package/dashboard/dist/assets/{EscalationTitleSelect-3mhXh77a.js.map → EscalationTitleSelect-D8qpCYiy.js.map} +1 -1
  195. package/dashboard/dist/assets/{EscalationsOverview-Qaov-uML.js → EscalationsOverview-CvaqVPsr.js} +2 -2
  196. package/dashboard/dist/assets/{EscalationsOverview-Qaov-uML.js.map → EscalationsOverview-CvaqVPsr.js.map} +1 -1
  197. package/dashboard/dist/assets/{EventTable-V4RF_n58.js → EventTable-Be0JuEl6.js} +2 -2
  198. package/dashboard/dist/assets/{EventTable-V4RF_n58.js.map → EventTable-Be0JuEl6.js.map} +1 -1
  199. package/dashboard/dist/assets/FilterBar-BVyAjIgv.js +2 -0
  200. package/dashboard/dist/assets/FilterBar-BVyAjIgv.js.map +1 -0
  201. package/dashboard/dist/assets/{GraphInvokePage-Djslhf96.js → GraphInvokePage-D_QigJeD.js} +2 -2
  202. package/dashboard/dist/assets/{GraphInvokePage-Djslhf96.js.map → GraphInvokePage-D_QigJeD.js.map} +1 -1
  203. package/dashboard/dist/assets/{HomePage-EjcNxlKx.js → HomePage-C1haeuNy.js} +2 -2
  204. package/dashboard/dist/assets/{HomePage-EjcNxlKx.js.map → HomePage-C1haeuNy.js.map} +1 -1
  205. package/dashboard/dist/assets/LinePage-CWD5pv1g.js +5 -0
  206. package/dashboard/dist/assets/LinePage-CWD5pv1g.js.map +1 -0
  207. package/dashboard/dist/assets/LinesPage-NqChsKcO.js +3 -0
  208. package/dashboard/dist/assets/LinesPage-NqChsKcO.js.map +1 -0
  209. package/dashboard/dist/assets/{ListToolbar-RrEAePOX.js → ListToolbar-BZCNrTh6.js} +2 -2
  210. package/dashboard/dist/assets/{ListToolbar-RrEAePOX.js.map → ListToolbar-BZCNrTh6.js.map} +1 -1
  211. package/dashboard/dist/assets/{McpOverview-8gqiL3Vj.js → McpOverview-yJTYnh1z.js} +2 -2
  212. package/dashboard/dist/assets/{McpOverview-8gqiL3Vj.js.map → McpOverview-yJTYnh1z.js.map} +1 -1
  213. package/dashboard/dist/assets/{McpQueryDetailPage-COyn6Ak5.js → McpQueryDetailPage-ChuLpJ4u.js} +3 -3
  214. package/dashboard/dist/assets/{McpQueryDetailPage-COyn6Ak5.js.map → McpQueryDetailPage-ChuLpJ4u.js.map} +1 -1
  215. package/dashboard/dist/assets/{McpQueryPage-Dj6Qj72w.js → McpQueryPage-9S-v9soF.js} +2 -2
  216. package/dashboard/dist/assets/{McpQueryPage-Dj6Qj72w.js.map → McpQueryPage-9S-v9soF.js.map} +1 -1
  217. package/dashboard/dist/assets/McpRunDetailPage-BhrcfxD5.js +2 -0
  218. package/dashboard/dist/assets/{McpRunDetailPage-80fQn9iX.js.map → McpRunDetailPage-BhrcfxD5.js.map} +1 -1
  219. package/dashboard/dist/assets/{McpRunsPage-DaSsI-EM.js → McpRunsPage-C5_i8_Zx.js} +2 -2
  220. package/dashboard/dist/assets/{McpRunsPage-DaSsI-EM.js.map → McpRunsPage-C5_i8_Zx.js.map} +1 -1
  221. package/dashboard/dist/assets/{NamespacePill-C5epAgq6.js → NamespacePill-OTZD2hzt.js} +2 -2
  222. package/dashboard/dist/assets/{NamespacePill-C5epAgq6.js.map → NamespacePill-OTZD2hzt.js.map} +1 -1
  223. package/dashboard/dist/assets/{OperationsPage-BSu1o2gB.js → OperationsPage-C03CeU5P.js} +2 -2
  224. package/dashboard/dist/assets/{OperationsPage-BSu1o2gB.js.map → OperationsPage-C03CeU5P.js.map} +1 -1
  225. package/dashboard/dist/assets/{OperatorDashboard-HFI4WGIV.js → OperatorDashboard-BzC134Jt.js} +2 -2
  226. package/dashboard/dist/assets/{OperatorDashboard-HFI4WGIV.js.map → OperatorDashboard-BzC134Jt.js.map} +1 -1
  227. package/dashboard/dist/assets/{PageHeader-BSWIspNB.js → PageHeader-Hx8APPwE.js} +2 -2
  228. package/dashboard/dist/assets/{PageHeader-BSWIspNB.js.map → PageHeader-Hx8APPwE.js.map} +1 -1
  229. package/dashboard/dist/assets/{PageHeaderWithStats-DDjopQ-k.js → PageHeaderWithStats-BEQYYBJv.js} +2 -2
  230. package/dashboard/dist/assets/{PageHeaderWithStats-DDjopQ-k.js.map → PageHeaderWithStats-BEQYYBJv.js.map} +1 -1
  231. package/dashboard/dist/assets/{PersonaDetailPage-D0qlBuGi.js → PersonaDetailPage-D0mY9L6j.js} +2 -2
  232. package/dashboard/dist/assets/{PersonaDetailPage-D0qlBuGi.js.map → PersonaDetailPage-D0mY9L6j.js.map} +1 -1
  233. package/dashboard/dist/assets/{PersonasPage-BJClu-5H.js → PersonasPage-FFlm5Eug.js} +2 -2
  234. package/dashboard/dist/assets/{PersonasPage-BJClu-5H.js.map → PersonasPage-FFlm5Eug.js.map} +1 -1
  235. package/dashboard/dist/assets/{PortalPage-CucNZn_w.js → PortalPage-Cpc25uO-.js} +2 -2
  236. package/dashboard/dist/assets/{PortalPage-CucNZn_w.js.map → PortalPage-Cpc25uO-.js.map} +1 -1
  237. package/dashboard/dist/assets/{ProcessDetailPage-B9wMw0RV.js → ProcessDetailPage-Di2J7KwY.js} +2 -2
  238. package/dashboard/dist/assets/{ProcessDetailPage-B9wMw0RV.js.map → ProcessDetailPage-Di2J7KwY.js.map} +1 -1
  239. package/dashboard/dist/assets/{ProcessesListPage-B6k4RpmR.js → ProcessesListPage-BEXwU3Z0.js} +2 -2
  240. package/dashboard/dist/assets/{ProcessesListPage-B6k4RpmR.js.map → ProcessesListPage-BEXwU3Z0.js.map} +1 -1
  241. package/dashboard/dist/assets/{ResolverForm-ZVufJ4G-.js → ResolverForm-2ks-3jXC.js} +6 -6
  242. package/dashboard/dist/assets/{ResolverForm-ZVufJ4G-.js.map → ResolverForm-2ks-3jXC.js.map} +1 -1
  243. package/dashboard/dist/assets/{RoleDetailPage-CTbq0mz4.js → RoleDetailPage-DqoOk0xc.js} +3 -3
  244. package/dashboard/dist/assets/{RoleDetailPage-CTbq0mz4.js.map → RoleDetailPage-DqoOk0xc.js.map} +1 -1
  245. package/dashboard/dist/assets/{RolePill-CoETDpjF.js → RolePill-R5_ctGFy.js} +2 -2
  246. package/dashboard/dist/assets/{RolePill-CoETDpjF.js.map → RolePill-R5_ctGFy.js.map} +1 -1
  247. package/dashboard/dist/assets/{RolesPage-DBKxeam4.js → RolesPage-CPmo8Srr.js} +2 -2
  248. package/dashboard/dist/assets/{RolesPage-DBKxeam4.js.map → RolesPage-CPmo8Srr.js.map} +1 -1
  249. package/dashboard/dist/assets/{RosterWidget-BkLAwEYB.js → RosterWidget-D2yovCKw.js} +2 -2
  250. package/dashboard/dist/assets/{RosterWidget-BkLAwEYB.js.map → RosterWidget-D2yovCKw.js.map} +1 -1
  251. package/dashboard/dist/assets/{RunAsSelector-D2DC4iDf.js → RunAsSelector-CMv96On6.js} +2 -2
  252. package/dashboard/dist/assets/{RunAsSelector-D2DC4iDf.js.map → RunAsSelector-CMv96On6.js.map} +1 -1
  253. package/dashboard/dist/assets/{ScanCodesPage-BlKleaT0.js → ScanCodesPage-CA6cTT-M.js} +2 -2
  254. package/dashboard/dist/assets/{ScanCodesPage-BlKleaT0.js.map → ScanCodesPage-CA6cTT-M.js.map} +1 -1
  255. package/dashboard/dist/assets/{ScanSchemeDetailPage-CTW6gofi.js → ScanSchemeDetailPage-DnctN5-H.js} +2 -2
  256. package/dashboard/dist/assets/{ScanSchemeDetailPage-CTW6gofi.js.map → ScanSchemeDetailPage-DnctN5-H.js.map} +1 -1
  257. package/dashboard/dist/assets/{ScanStationPage-DPRjSPyT.js → ScanStationPage-Bk8RwkKL.js} +2 -2
  258. package/dashboard/dist/assets/{ScanStationPage-DPRjSPyT.js.map → ScanStationPage-Bk8RwkKL.js.map} +1 -1
  259. package/dashboard/dist/assets/{ScopeBadge-CGsTtqFr.js → ScopeBadge-BXZ084nD.js} +2 -2
  260. package/dashboard/dist/assets/{ScopeBadge-CGsTtqFr.js.map → ScopeBadge-BXZ084nD.js.map} +1 -1
  261. package/dashboard/dist/assets/{StickyPagination-CkmX3-Gu.js → StickyPagination-B0FSuUgs.js} +2 -2
  262. package/dashboard/dist/assets/{StickyPagination-CkmX3-Gu.js.map → StickyPagination-B0FSuUgs.js.map} +1 -1
  263. package/dashboard/dist/assets/{StreamMessageDetail-Xm_n510s.js → StreamMessageDetail-BwZEvMpP.js} +2 -2
  264. package/dashboard/dist/assets/{StreamMessageDetail-Xm_n510s.js.map → StreamMessageDetail-BwZEvMpP.js.map} +1 -1
  265. package/dashboard/dist/assets/{SwimlaneTimeline-De48aJan.js → SwimlaneTimeline-BDVQEaMw.js} +2 -2
  266. package/dashboard/dist/assets/{SwimlaneTimeline-De48aJan.js.map → SwimlaneTimeline-BDVQEaMw.js.map} +1 -1
  267. package/dashboard/dist/assets/{TagInput-S7UuVT_M.js → TagInput-DjPUDp2M.js} +2 -2
  268. package/dashboard/dist/assets/{TagInput-S7UuVT_M.js.map → TagInput-DjPUDp2M.js.map} +1 -1
  269. package/dashboard/dist/assets/{TaskDetailPage-HycMx3O9.js → TaskDetailPage-BOlv3iGB.js} +2 -2
  270. package/dashboard/dist/assets/{TaskDetailPage-HycMx3O9.js.map → TaskDetailPage-BOlv3iGB.js.map} +1 -1
  271. package/dashboard/dist/assets/{TaskQueuePill-BlHNpYiZ.js → TaskQueuePill-D-4Ynf3K.js} +2 -2
  272. package/dashboard/dist/assets/{TaskQueuePill-BlHNpYiZ.js.map → TaskQueuePill-D-4Ynf3K.js.map} +1 -1
  273. package/dashboard/dist/assets/{TasksListPage-OIcFFp1C.js → TasksListPage-e2teY0bD.js} +2 -2
  274. package/dashboard/dist/assets/{TasksListPage-OIcFFp1C.js.map → TasksListPage-e2teY0bD.js.map} +1 -1
  275. package/dashboard/dist/assets/{TimeAgo-OTC_55oZ.js → TimeAgo-Cvkpf_b3.js} +2 -2
  276. package/dashboard/dist/assets/{TimeAgo-OTC_55oZ.js.map → TimeAgo-Cvkpf_b3.js.map} +1 -1
  277. package/dashboard/dist/assets/{TimestampCell-CAwIj_AI.js → TimestampCell-B3btAV0N.js} +2 -2
  278. package/dashboard/dist/assets/{TimestampCell-CAwIj_AI.js.map → TimestampCell-B3btAV0N.js.map} +1 -1
  279. package/dashboard/dist/assets/{ToolPill-D40uLM_v.js → ToolPill-GsKQ80CO.js} +2 -2
  280. package/dashboard/dist/assets/{ToolPill-D40uLM_v.js.map → ToolPill-GsKQ80CO.js.map} +1 -1
  281. package/dashboard/dist/assets/{ToolTestPanel-8Vf6pfw4.js → ToolTestPanel-B03nebR7.js} +2 -2
  282. package/dashboard/dist/assets/{ToolTestPanel-8Vf6pfw4.js.map → ToolTestPanel-B03nebR7.js.map} +1 -1
  283. package/dashboard/dist/assets/{TopicDetailPage-iZW8rK9L.js → TopicDetailPage-DBRWne3O.js} +3 -3
  284. package/dashboard/dist/assets/{TopicDetailPage-iZW8rK9L.js.map → TopicDetailPage-DBRWne3O.js.map} +1 -1
  285. package/dashboard/dist/assets/{TopicsPage-CqiEcj-W.js → TopicsPage-CVe2M9HD.js} +2 -2
  286. package/dashboard/dist/assets/{TopicsPage-CqiEcj-W.js.map → TopicsPage-CVe2M9HD.js.map} +1 -1
  287. package/dashboard/dist/assets/{UserName-DQFjuoib.js → UserName-B_q_qp6V.js} +2 -2
  288. package/dashboard/dist/assets/{UserName-DQFjuoib.js.map → UserName-B_q_qp6V.js.map} +1 -1
  289. package/dashboard/dist/assets/WorkflowExecutionPage-Bh_dr9tM.js +2 -0
  290. package/dashboard/dist/assets/{WorkflowExecutionPage-Di08wCbs.js.map → WorkflowExecutionPage-Bh_dr9tM.js.map} +1 -1
  291. package/dashboard/dist/assets/{WorkflowPill-DJLcK_CM.js → WorkflowPill-D7244fKp.js} +2 -2
  292. package/dashboard/dist/assets/{WorkflowPill-DJLcK_CM.js.map → WorkflowPill-D7244fKp.js.map} +1 -1
  293. package/dashboard/dist/assets/{WorkflowsDashboard-Bb8HlrTJ.js → WorkflowsDashboard-DA6Mj7qH.js} +2 -2
  294. package/dashboard/dist/assets/{WorkflowsDashboard-Bb8HlrTJ.js.map → WorkflowsDashboard-DA6Mj7qH.js.map} +1 -1
  295. package/dashboard/dist/assets/{WorkflowsOverview-Dta1kurk.js → WorkflowsOverview-B1kBLj-a.js} +2 -2
  296. package/dashboard/dist/assets/{WorkflowsOverview-Dta1kurk.js.map → WorkflowsOverview-B1kBLj-a.js.map} +1 -1
  297. package/dashboard/dist/assets/{YamlWorkflowDetailPage-CfAajg68.js → YamlWorkflowDetailPage-6GJM8QIX.js} +8 -8
  298. package/dashboard/dist/assets/{YamlWorkflowDetailPage-CfAajg68.js.map → YamlWorkflowDetailPage-6GJM8QIX.js.map} +1 -1
  299. package/dashboard/dist/assets/{YamlWorkflowsPage-CQFUzT4t.js → YamlWorkflowsPage-Bu811C7f.js} +2 -2
  300. package/dashboard/dist/assets/{YamlWorkflowsPage-CQFUzT4t.js.map → YamlWorkflowsPage-Bu811C7f.js.map} +1 -1
  301. package/dashboard/dist/assets/{agents-PuftRTB2.js → agents-MPk_GnYz.js} +2 -2
  302. package/dashboard/dist/assets/{agents-PuftRTB2.js.map → agents-MPk_GnYz.js.map} +1 -1
  303. package/dashboard/dist/assets/{bots-BmEiPAWY.js → bots-2RihE2Tc.js} +2 -2
  304. package/dashboard/dist/assets/{bots-BmEiPAWY.js.map → bots-2RihE2Tc.js.map} +1 -1
  305. package/dashboard/dist/assets/{capabilities-CRii4Soa.js → capabilities-CC4iwJ1P.js} +2 -2
  306. package/dashboard/dist/assets/{capabilities-CRii4Soa.js.map → capabilities-CC4iwJ1P.js.map} +1 -1
  307. package/dashboard/dist/assets/{controlplane-DO_czaYo.js → controlplane-Bmkic8BH.js} +2 -2
  308. package/dashboard/dist/assets/{controlplane-DO_czaYo.js.map → controlplane-Bmkic8BH.js.map} +1 -1
  309. package/dashboard/dist/assets/{escalation-columns-CzCquCPh.js → escalation-columns-B0lhUUrQ.js} +2 -2
  310. package/dashboard/dist/assets/{escalation-columns-CzCquCPh.js.map → escalation-columns-B0lhUUrQ.js.map} +1 -1
  311. package/dashboard/dist/assets/{escalation-items-Cy0ZgJqV.js → escalation-items-7WFpPo46.js} +2 -2
  312. package/dashboard/dist/assets/{escalation-items-Cy0ZgJqV.js.map → escalation-items-7WFpPo46.js.map} +1 -1
  313. package/dashboard/dist/assets/index-B9uv-euR.css +1 -0
  314. package/dashboard/dist/assets/{index-DhSCCpqM.js → index-B_XV1rwu.js} +2 -2
  315. package/dashboard/dist/assets/{index-DhSCCpqM.js.map → index-B_XV1rwu.js.map} +1 -1
  316. package/dashboard/dist/assets/{index-Cx8xb-oU.js → index-C2CLfGwL.js} +2 -2
  317. package/dashboard/dist/assets/{index-Cx8xb-oU.js.map → index-C2CLfGwL.js.map} +1 -1
  318. package/dashboard/dist/assets/{index-Cga5IW3D.js → index-C3AeFihz.js} +2 -2
  319. package/dashboard/dist/assets/{index-Cga5IW3D.js.map → index-C3AeFihz.js.map} +1 -1
  320. package/dashboard/dist/assets/{index-DiaRlFYI.js → index-CBri8fYM.js} +2 -2
  321. package/dashboard/dist/assets/{index-DiaRlFYI.js.map → index-CBri8fYM.js.map} +1 -1
  322. package/dashboard/dist/assets/{index-CL_1VpGb.js → index-CRWsB7ZC.js} +2 -2
  323. package/dashboard/dist/assets/{index-CL_1VpGb.js.map → index-CRWsB7ZC.js.map} +1 -1
  324. package/dashboard/dist/assets/{index-XntldBd0.js → index-CTOv3G7a.js} +2 -2
  325. package/dashboard/dist/assets/{index-XntldBd0.js.map → index-CTOv3G7a.js.map} +1 -1
  326. package/dashboard/dist/assets/{index-CfP2nKRc.js → index-CcArGkzI.js} +3 -3
  327. package/dashboard/dist/assets/{index-CfP2nKRc.js.map → index-CcArGkzI.js.map} +1 -1
  328. package/dashboard/dist/assets/{index-Dz6R8-Dw.js → index-CkMHS-hG.js} +25 -25
  329. package/dashboard/dist/assets/index-CkMHS-hG.js.map +1 -0
  330. package/dashboard/dist/assets/index-CmsmwCyv.js +2 -0
  331. package/dashboard/dist/assets/{index-4YaDUcKd.js.map → index-CmsmwCyv.js.map} +1 -1
  332. package/dashboard/dist/assets/{index-2SM2_onB.js → index-CvJsvqIc.js} +2 -2
  333. package/dashboard/dist/assets/{index-2SM2_onB.js.map → index-CvJsvqIc.js.map} +1 -1
  334. package/dashboard/dist/assets/{index-Rwqrflm-.js → index-D-ilRyfy.js} +2 -2
  335. package/dashboard/dist/assets/{index-Rwqrflm-.js.map → index-D-ilRyfy.js.map} +1 -1
  336. package/dashboard/dist/assets/{index-CZ7A3AcD.js → index-DSUtfDXx.js} +2 -2
  337. package/dashboard/dist/assets/{index-CZ7A3AcD.js.map → index-DSUtfDXx.js.map} +1 -1
  338. package/dashboard/dist/assets/{index-jL2K6us4.js → index-Da6ycKyf.js} +2 -2
  339. package/dashboard/dist/assets/{index-jL2K6us4.js.map → index-Da6ycKyf.js.map} +1 -1
  340. package/dashboard/dist/assets/{knowledge-CeUqGPuo.js → knowledge-Bpbg20DC.js} +2 -2
  341. package/dashboard/dist/assets/{knowledge-CeUqGPuo.js.map → knowledge-Bpbg20DC.js.map} +1 -1
  342. package/dashboard/dist/assets/machines-BqOZZU-3.js +2 -0
  343. package/dashboard/dist/assets/machines-BqOZZU-3.js.map +1 -0
  344. package/dashboard/dist/assets/{mcp-Cx96NTeD.js → mcp-CmcUXYce.js} +2 -2
  345. package/dashboard/dist/assets/{mcp-Cx96NTeD.js.map → mcp-CmcUXYce.js.map} +1 -1
  346. package/dashboard/dist/assets/{mcp-query-XAzWl0gm.js → mcp-query-C8buQxN9.js} +2 -2
  347. package/dashboard/dist/assets/{mcp-query-XAzWl0gm.js.map → mcp-query-C8buQxN9.js.map} +1 -1
  348. package/dashboard/dist/assets/{personas--4kjwyOw.js → personas-C2n5oDmY.js} +2 -2
  349. package/dashboard/dist/assets/{personas--4kjwyOw.js.map → personas-C2n5oDmY.js.map} +1 -1
  350. package/dashboard/dist/assets/{pipelines-PgkwvG7f.js → pipelines-RKpSkFz7.js} +2 -2
  351. package/dashboard/dist/assets/{pipelines-PgkwvG7f.js.map → pipelines-RKpSkFz7.js.map} +1 -1
  352. package/dashboard/dist/assets/{tasks-CcYxdBa3.js → tasks-Dab4hExW.js} +2 -2
  353. package/dashboard/dist/assets/{tasks-CcYxdBa3.js.map → tasks-Dab4hExW.js.map} +1 -1
  354. package/dashboard/dist/assets/{topics-_lik7cNY.js → topics-FTMNP7r3.js} +2 -2
  355. package/dashboard/dist/assets/{topics-_lik7cNY.js.map → topics-FTMNP7r3.js.map} +1 -1
  356. package/dashboard/dist/assets/{useDebouncedValue-Bm_AoxVx.js → useDebouncedValue-B_1u1YIk.js} +2 -2
  357. package/dashboard/dist/assets/{useDebouncedValue-Bm_AoxVx.js.map → useDebouncedValue-B_1u1YIk.js.map} +1 -1
  358. package/dashboard/dist/assets/{useNamespace-DgXXKdx5.js → useNamespace-HUeAI7Qb.js} +2 -2
  359. package/dashboard/dist/assets/{useNamespace-DgXXKdx5.js.map → useNamespace-HUeAI7Qb.js.map} +1 -1
  360. package/dashboard/dist/assets/{useYamlActivityEvents-Dj2qtGSd.js → useYamlActivityEvents-Cax54qHH.js} +2 -2
  361. package/dashboard/dist/assets/{useYamlActivityEvents-Dj2qtGSd.js.map → useYamlActivityEvents-Cax54qHH.js.map} +1 -1
  362. package/dashboard/dist/assets/{validate-FlXCBBT6.js → validate-DxOaV7QS.js} +2 -2
  363. package/dashboard/dist/assets/{validate-FlXCBBT6.js.map → validate-DxOaV7QS.js.map} +1 -1
  364. package/dashboard/dist/assets/{vendor-icons-DUYcKTjP.js → vendor-icons-fxBvvHBi.js} +187 -182
  365. package/dashboard/dist/assets/vendor-icons-fxBvvHBi.js.map +1 -0
  366. package/dashboard/dist/assets/{yaml-workflows-B0_JxRYQ.js → yaml-workflows-BgY1XHJx.js} +2 -2
  367. package/dashboard/dist/assets/{yaml-workflows-B0_JxRYQ.js.map → yaml-workflows-BgY1XHJx.js.map} +1 -1
  368. package/dashboard/dist/index.html +3 -3
  369. package/docs/architecture.md +1 -0
  370. package/docs/code-owned-configuration.md +6 -0
  371. package/docs/dashboard.md +2 -1
  372. package/docs/events.md +34 -1
  373. package/docs/hitl/lookups.md +6 -4
  374. package/docs/machines.md +114 -28
  375. package/docs/mcp.md +19 -0
  376. package/package.json +1 -1
  377. package/dashboard/dist/assets/AgentsPage-C9UuUKhr.js +0 -2
  378. package/dashboard/dist/assets/AvailableEscalationsPage-DrvfXz70.js +0 -2
  379. package/dashboard/dist/assets/FilterBar-BygWrnB1.js +0 -2
  380. package/dashboard/dist/assets/FilterBar-BygWrnB1.js.map +0 -1
  381. package/dashboard/dist/assets/McpRunDetailPage-80fQn9iX.js +0 -2
  382. package/dashboard/dist/assets/WorkflowExecutionPage-Di08wCbs.js +0 -2
  383. package/dashboard/dist/assets/index-4YaDUcKd.js +0 -2
  384. package/dashboard/dist/assets/index-CnU7Jjz3.css +0 -1
  385. package/dashboard/dist/assets/index-Dz6R8-Dw.js.map +0 -1
  386. package/dashboard/dist/assets/vendor-icons-DUYcKTjP.js.map +0 -1
@@ -21,7 +21,7 @@ async function describeMissingLookupRefs(refs) {
21
21
  const where = versions.length
22
22
  ? `editions: ${versions.map((v) => `v${v}`).join(', ')}`
23
23
  : `no knowledge entry ${ref.domain}/${ref.key}`;
24
- const named = (0, escalation_1.isCurrentLookupRef)(ref) ? 'current' : `v${ref.version}`;
24
+ const named = (0, escalation_1.isCurrentLookupRef)(ref) ? 'current' : (0, escalation_1.isLabelLookupRef)(ref) ? `label ${JSON.stringify(ref.version)}` : `v${ref.version}`;
25
25
  problems.push(`Lookup ref ${ref.domain}/${ref.key} ${named} names no edition (${where})`);
26
26
  }
27
27
  return problems;
@@ -1,4 +1,6 @@
1
- export declare const GET_KNOWLEDGE_VERSION = "\n SELECT domain, key, version, data, tags, change_summary, created_at\n FROM lt_knowledge_versions\n WHERE domain = $1 AND key = $2 AND version = $3";
2
- export declare const LIST_KNOWLEDGE_VERSIONS = "\n SELECT v.version, v.change_summary, v.created_at,\n (v.version = k.current_version) AS is_current\n FROM lt_knowledge_versions v\n JOIN lt_knowledge k ON k.domain = v.domain AND k.key = v.key\n WHERE v.domain = $1 AND v.key = $2\n ORDER BY v.version DESC";
1
+ export declare const GET_KNOWLEDGE_VERSION = "\n SELECT domain, key, version, label, data, tags, change_summary, created_at\n FROM lt_knowledge_versions\n WHERE domain = $1 AND key = $2 AND version = $3";
2
+ /** The edition a label names, when one does. */
3
+ export declare const GET_KNOWLEDGE_VERSION_BY_LABEL = "\n SELECT version\n FROM lt_knowledge_versions\n WHERE domain = $1 AND key = $2 AND label = $3";
4
+ export declare const LIST_KNOWLEDGE_VERSIONS = "\n SELECT v.version, v.label, v.change_summary, v.created_at,\n (v.version = k.current_version) AS is_current\n FROM lt_knowledge_versions v\n JOIN lt_knowledge k ON k.domain = v.domain AND k.key = v.key\n WHERE v.domain = $1 AND v.key = $2\n ORDER BY v.version DESC";
3
5
  /** The newest edition, or the newest created at or before $3 when it is set. */
4
6
  export declare const GET_LATEST_KNOWLEDGE_VERSION = "\n SELECT version, data, tags\n FROM lt_knowledge_versions\n WHERE domain = $1 AND key = $2\n AND ($3::timestamptz IS NULL OR created_at <= $3)\n ORDER BY version DESC\n LIMIT 1";
@@ -1,12 +1,17 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.GET_LATEST_KNOWLEDGE_VERSION = exports.LIST_KNOWLEDGE_VERSIONS = exports.GET_KNOWLEDGE_VERSION = void 0;
3
+ exports.GET_LATEST_KNOWLEDGE_VERSION = exports.LIST_KNOWLEDGE_VERSIONS = exports.GET_KNOWLEDGE_VERSION_BY_LABEL = exports.GET_KNOWLEDGE_VERSION = void 0;
4
4
  exports.GET_KNOWLEDGE_VERSION = `
5
- SELECT domain, key, version, data, tags, change_summary, created_at
5
+ SELECT domain, key, version, label, data, tags, change_summary, created_at
6
6
  FROM lt_knowledge_versions
7
7
  WHERE domain = $1 AND key = $2 AND version = $3`;
8
+ /** The edition a label names, when one does. */
9
+ exports.GET_KNOWLEDGE_VERSION_BY_LABEL = `
10
+ SELECT version
11
+ FROM lt_knowledge_versions
12
+ WHERE domain = $1 AND key = $2 AND label = $3`;
8
13
  exports.LIST_KNOWLEDGE_VERSIONS = `
9
- SELECT v.version, v.change_summary, v.created_at,
14
+ SELECT v.version, v.label, v.change_summary, v.created_at,
10
15
  (v.version = k.current_version) AS is_current
11
16
  FROM lt_knowledge_versions v
12
17
  JOIN lt_knowledge k ON k.domain = v.domain AND k.key = v.key
@@ -1,11 +1,11 @@
1
1
  /**
2
2
  * Commands as rows. A host asks a machine to start, stop, pause, resume,
3
- * change over or cancel a job by parking a machine-command row on the machine's role, from a
4
- * workflow step or through the API, the same way it asks a person for
3
+ * change over, cancel a job, report a snapshot, or do anything its codec
4
+ * declares (`rowOps`), by parking a machine-command row on the machine's role,
5
+ * from a workflow step or through the API, the same way it asks a person for
5
6
  * anything. The gateway sends the command and resolves the row with the
6
7
  * machine's reply (CommandResolution), so the step reads the outcome as data.
7
8
  */
8
- import type { Op } from '../../lib/machines/protocol';
9
9
  import { type LineDef } from '../../lib/machines/line';
10
10
  import { type CommandFacets } from './contracts';
11
11
  /** Where a command goes: the machine and the role its rows land on. */
@@ -17,10 +17,10 @@ export interface CommandTarget {
17
17
  }
18
18
  export declare function commandTarget(line: LineDef, machineId: string): CommandTarget;
19
19
  /** The row that asks a machine for `op`: pass it to conditional(), or create it through the API. */
20
- export declare function commandRow(target: CommandTarget, op: Op, args?: Record<string, unknown>): {
20
+ export declare function commandRow(target: CommandTarget, op: string, args?: Record<string, unknown>): {
21
21
  role: string;
22
22
  type: "machine-command";
23
- subtype: Op;
23
+ subtype: string;
24
24
  description: string;
25
25
  priority: number;
26
26
  metadata: Record<string, unknown>;
@@ -1,8 +1,9 @@
1
1
  "use strict";
2
2
  /**
3
3
  * Commands as rows. A host asks a machine to start, stop, pause, resume,
4
- * change over or cancel a job by parking a machine-command row on the machine's role, from a
5
- * workflow step or through the API, the same way it asks a person for
4
+ * change over, cancel a job, report a snapshot, or do anything its codec
5
+ * declares (`rowOps`), by parking a machine-command row on the machine's role,
6
+ * from a workflow step or through the API, the same way it asks a person for
6
7
  * anything. The gateway sends the command and resolves the row with the
7
8
  * machine's reply (CommandResolution), so the step reads the outcome as data.
8
9
  */
@@ -29,7 +29,6 @@ export interface MachineLineConfig {
29
29
  mqtt?: MqttEndpoint;
30
30
  replyTimeoutMs: number;
31
31
  dispatchAttempts: number;
32
- handoffTimeout: string;
33
32
  offlineDebounceMs: number;
34
33
  /** A connected machine silent this long gets a quiet row; 0 turns the check off. */
35
34
  quietMs: number;
@@ -41,6 +40,10 @@ export interface MachineLineConfig {
41
40
  lifecycle: boolean;
42
41
  /** With lifecycle notes, progress is noted each time it crosses this many percent; 0 notes none. */
43
42
  progressStep: number;
43
+ /** Telemetry messages are published as wire events too; off by default, since they are read live and many. */
44
+ wireTelemetry: boolean;
45
+ /** How many of the line's last wire events the leader keeps for GET .../wire. */
46
+ wireWindow: number;
44
47
  ltBaseUrl: string;
45
48
  }
46
49
  type Env = Record<string, string | undefined>;
@@ -68,13 +68,14 @@ function loadMachineLineConfig(env = process.env) {
68
68
  lineConfigPath: env.MACHINE_LINE_CONFIG || undefined,
69
69
  replyTimeoutMs: int(env, 'MACHINE_REPLY_TIMEOUT_MS', protocol_1.REPLY_DEADLINE_MS),
70
70
  dispatchAttempts: Math.max(1, int(env, 'MACHINE_DISPATCH_ATTEMPTS', 3)),
71
- handoffTimeout: env.MACHINE_HANDOFF_TIMEOUT ?? '10m',
72
71
  offlineDebounceMs: int(env, 'MACHINE_OFFLINE_DEBOUNCE_MS', 15_000),
73
72
  quietMs: int(env, 'MACHINE_QUIET_MS', 90_000),
74
73
  dispatchTtlMs: int(env, 'MACHINE_DISPATCH_TTL_MS', 600_000),
75
74
  receiptDelayMs: int(env, 'MACHINE_RECEIPT_DELAY_MS', 250),
76
75
  lifecycle: oneOf('MACHINE_LIFECYCLE', env.MACHINE_LIFECYCLE || SWITCH.OFF, Object.values(SWITCH)) === SWITCH.ON,
77
76
  progressStep: percentStep(env, 'MACHINE_PROGRESS_STEP', 25),
77
+ wireTelemetry: oneOf('MACHINE_WIRE_TELEMETRY', env.MACHINE_WIRE_TELEMETRY || SWITCH.OFF, Object.values(SWITCH)) === SWITCH.ON,
78
+ wireWindow: Math.max(1, int(env, 'MACHINE_WIRE_WINDOW', 500)),
78
79
  ltBaseUrl: env.LT_BASE_URL ?? 'http://localhost:3000',
79
80
  };
80
81
  if (transport === exports.MACHINE_TRANSPORT.NATS) {
@@ -16,12 +16,16 @@ export declare const ROW_TYPE: {
16
16
  readonly CONTRACT_VIOLATION: "contract-violation";
17
17
  /** An address claims a station the line already knows by another address, or the reverse: a person approves or rejects. */
18
18
  readonly MACHINE_REGISTRATION: "machine-registration";
19
+ /** Units a machine finished on hold wait for a quality decision: release, rework or scrap. */
20
+ readonly QUALITY_HOLD: "quality-hold";
19
21
  };
20
22
  export declare const LINE_ROLE: {
21
23
  /** People who clear alarms, bring machines back and decide failed handoffs. */
22
24
  readonly OPERATOR: "line-operator";
23
25
  /** People who take finished units off the line: the final handoff. */
24
26
  readonly EXIT: "line-exit";
27
+ /** People who decide units a machine finished on hold. */
28
+ readonly QUALITY: "line-quality";
25
29
  /** The gateway's own identity. */
26
30
  readonly CONTROLLER: "line-controller";
27
31
  };
@@ -43,6 +47,8 @@ export interface HandoffUnit {
43
47
  artifacts?: ArtifactRef[];
44
48
  /** Parameters for this unit alone, sent to the machine as given. */
45
49
  parameters?: Record<string, unknown>;
50
+ /** The host's references for this unit, by name; sent to the machine as given and searchable on the row. */
51
+ refs?: Record<string, string>;
46
52
  }
47
53
  /** Metadata on a handoff row. Everything a dispatch needs rides here. */
48
54
  export interface HandoffFacets {
@@ -66,6 +72,8 @@ export interface HandoffFacets {
66
72
  attempt: number;
67
73
  /** Parameters for the job, sent to the machine as given; what they mean is between the host and its codec. */
68
74
  parameters?: Record<string, unknown>;
75
+ /** The host's references for the job, by name (an order, a batch, a ticket); sent to the machine as given and searchable on the row. */
76
+ refs?: Record<string, string>;
69
77
  }
70
78
  /**
71
79
  * Items a handoff row accumulates, one per unit: the sender's finished-job
@@ -112,6 +120,8 @@ export declare const HANDOFF_ERROR: {
112
120
  readonly SOFTWARE_UNSUPPORTED: "software-unsupported";
113
121
  readonly WITHDRAWN: "withdrawn";
114
122
  readonly CANCELLED: "cancelled";
123
+ /** An arrival no open handoff into the machine expects, shown to the operator role once per machine and carrier. */
124
+ readonly UNMATCHED_ARRIVAL: "unmatched-arrival";
115
125
  };
116
126
  export type HandoffErrorCode = typeof HANDOFF_ERROR[keyof typeof HANDOFF_ERROR];
117
127
  /** A material lot a machine consumed for a unit. */
@@ -151,8 +161,12 @@ export interface HandoffResolution {
151
161
  /** The machine that reported the error, when it is not the one resolving. */
152
162
  reportedBy?: string;
153
163
  errorCode?: HandoffErrorCode;
164
+ /** On `sender-rejected`, how the sender finished the unit: reject, hold, scrap or rework. */
165
+ result?: string;
154
166
  reason?: string | null;
155
167
  detail?: string;
168
+ /** The machine's structured code for a refusal or failure, when its reply carried one. */
169
+ code?: string;
156
170
  }
157
171
  /** Decisions on line-operator rows: failed handoffs, alarms, dark machines, contested registrations. */
158
172
  export declare const DECISION: {
@@ -164,6 +178,10 @@ export declare const DECISION: {
164
178
  readonly RESTORED: "restored";
165
179
  readonly APPROVE: "approve";
166
180
  readonly REJECT: "reject";
181
+ /** A quality decision on held units: they continue from where they are. */
182
+ readonly RELEASE: "release";
183
+ /** A quality decision on held units: they run again from a station on the route. */
184
+ readonly REWORK: "rework";
167
185
  };
168
186
  export type Decision = typeof DECISION[keyof typeof DECISION];
169
187
  /** The decisions an operator may take on a failed handoff; retry only while every unit is still at the sender. */
@@ -172,11 +190,19 @@ export interface OperatorResolution {
172
190
  decision: Decision;
173
191
  note?: string;
174
192
  }
193
+ /** The decisions a quality role may take on units a machine finished on hold. */
194
+ export declare const HOLD_DECISIONS: readonly Decision[];
195
+ export interface QualityResolution extends OperatorResolution {
196
+ /** For `rework`: the station the units run again from; the holding station when absent. */
197
+ station?: string;
198
+ }
175
199
  /** Signal keys for the unit workflow; every attempt mints a fresh key. */
176
200
  export declare const signalKeys: {
177
201
  handoff: (jobKey: string, step: number, attempt: number) => string;
178
202
  handoffError: (jobKey: string, step: number, attempt: number, round?: number) => string;
179
203
  jobStop: (jobKey: string, step: number, attempt: number) => string;
204
+ hold: (jobKey: string, step: number, attempt: number, round?: number) => string;
205
+ disposition: (jobKey: string, step: number, attempt: number) => string;
180
206
  };
181
207
  /** Metadata on a machine-command row. */
182
208
  export interface CommandFacets {
@@ -202,6 +228,8 @@ export interface CommandResolution {
202
228
  op: string;
203
229
  status: CommandStatus;
204
230
  reason?: string;
231
+ /** The machine's structured code for the outcome, when its reply carried one. */
232
+ code?: string;
205
233
  }
206
234
  /** A row's dispatch command in its validity round; a later round is a new command (gateway/pacing.ts dispatchWindow). */
207
235
  export declare const dispatchCommandId: (escalationId: string, round?: number) => string;
@@ -6,7 +6,7 @@
6
6
  * protocol that resolves it differs.
7
7
  */
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.cancelCommandId = exports.controlCommandId = exports.dispatchCommandId = exports.COMMAND_STATUS = exports.signalKeys = exports.DECISION = exports.LIFECYCLE_FACET = exports.TRACE_FACET = exports.HANDOFF_ERROR = exports.itemKeys = exports.LINE_ROLE = exports.ROW_TYPE = void 0;
9
+ exports.cancelCommandId = exports.controlCommandId = exports.dispatchCommandId = exports.COMMAND_STATUS = exports.signalKeys = exports.HOLD_DECISIONS = exports.DECISION = exports.LIFECYCLE_FACET = exports.TRACE_FACET = exports.HANDOFF_ERROR = exports.itemKeys = exports.LINE_ROLE = exports.ROW_TYPE = void 0;
10
10
  exports.arrivedUnit = arrivedUnit;
11
11
  exports.handoffProgress = handoffProgress;
12
12
  exports.handoffDecisions = handoffDecisions;
@@ -24,12 +24,16 @@ exports.ROW_TYPE = {
24
24
  CONTRACT_VIOLATION: 'contract-violation',
25
25
  /** An address claims a station the line already knows by another address, or the reverse: a person approves or rejects. */
26
26
  MACHINE_REGISTRATION: 'machine-registration',
27
+ /** Units a machine finished on hold wait for a quality decision: release, rework or scrap. */
28
+ QUALITY_HOLD: 'quality-hold',
27
29
  };
28
30
  exports.LINE_ROLE = {
29
31
  /** People who clear alarms, bring machines back and decide failed handoffs. */
30
32
  OPERATOR: line_1.DEFAULT_OPERATOR_ROLE,
31
33
  /** People who take finished units off the line: the final handoff. */
32
34
  EXIT: line_1.DEFAULT_EXIT_ROLE,
35
+ /** People who decide units a machine finished on hold. */
36
+ QUALITY: line_1.DEFAULT_QUALITY_ROLE,
33
37
  /** The gateway's own identity. */
34
38
  CONTROLLER: 'line-controller',
35
39
  };
@@ -75,6 +79,8 @@ exports.HANDOFF_ERROR = {
75
79
  SOFTWARE_UNSUPPORTED: 'software-unsupported',
76
80
  WITHDRAWN: 'withdrawn',
77
81
  CANCELLED: 'cancelled',
82
+ /** An arrival no open handoff into the machine expects, shown to the operator role once per machine and carrier. */
83
+ UNMATCHED_ARRIVAL: 'unmatched-arrival',
78
84
  ...protocol_1.TRANSFER_FAILURE,
79
85
  };
80
86
  /**
@@ -95,6 +101,10 @@ exports.DECISION = {
95
101
  RESTORED: 'restored',
96
102
  APPROVE: 'approve',
97
103
  REJECT: 'reject',
104
+ /** A quality decision on held units: they continue from where they are. */
105
+ RELEASE: 'release',
106
+ /** A quality decision on held units: they run again from a station on the route. */
107
+ REWORK: 'rework',
98
108
  };
99
109
  /**
100
110
  * Failures a retry cannot repair. Units a sender finished as not ok leave the
@@ -107,11 +117,15 @@ function handoffDecisions(errorCode) {
107
117
  const noRetry = !!errorCode && NO_RETRY.includes(errorCode);
108
118
  return noRetry ? [exports.DECISION.MANUAL, exports.DECISION.SCRAP] : [exports.DECISION.RETRY, exports.DECISION.MANUAL, exports.DECISION.SCRAP];
109
119
  }
120
+ /** The decisions a quality role may take on units a machine finished on hold. */
121
+ exports.HOLD_DECISIONS = [exports.DECISION.RELEASE, exports.DECISION.REWORK, exports.DECISION.SCRAP];
110
122
  /** Signal keys for the unit workflow; every attempt mints a fresh key. */
111
123
  exports.signalKeys = {
112
124
  handoff: (jobKey, step, attempt) => `handoff-${jobKey}-s${step}-a${attempt}`,
113
125
  handoffError: (jobKey, step, attempt, round = 1) => `handoff-error-${jobKey}-s${step}-a${attempt}${round > 1 ? `-r${round}` : ''}`,
114
126
  jobStop: (jobKey, step, attempt) => `job-stop-${jobKey}-s${step}-a${attempt}`,
127
+ hold: (jobKey, step, attempt, round = 1) => `hold-${jobKey}-s${step}-a${attempt}${round > 1 ? `-r${round}` : ''}`,
128
+ disposition: (jobKey, step, attempt) => `disposition-${jobKey}-s${step}-a${attempt}`,
115
129
  };
116
130
  exports.COMMAND_STATUS = { ...protocol_1.REPLY_STATUS, NO_REPLY: 'no-reply', UNSUPPORTED: 'unsupported' };
117
131
  /** A row's dispatch command in its validity round; a later round is a new command (gateway/pacing.ts dispatchWindow). */
@@ -36,7 +36,7 @@ export declare const OPERATOR_FORM_SCHEMA: {
36
36
  properties: {
37
37
  decision: {
38
38
  type: string;
39
- enum: ("reject" | "scrap" | "retry" | "manual" | "acknowledge" | "cleared" | "restored" | "approve")[];
39
+ enum: ("release" | "reject" | "scrap" | "rework" | "retry" | "manual" | "acknowledge" | "cleared" | "restored" | "approve")[];
40
40
  default: "acknowledge";
41
41
  description: string;
42
42
  };
@@ -53,3 +53,28 @@ export declare const OPERATOR_FORM_SCHEMA: {
53
53
  };
54
54
  };
55
55
  };
56
+ export declare const QUALITY_FORM_SCHEMA: {
57
+ title: string;
58
+ description: string;
59
+ 'x-lt-order': string[];
60
+ required: string[];
61
+ properties: {
62
+ decision: {
63
+ type: string;
64
+ enum: ("release" | "scrap" | "rework")[];
65
+ default: "release";
66
+ description: string;
67
+ };
68
+ station: {
69
+ type: string;
70
+ default: string;
71
+ description: string;
72
+ };
73
+ note: {
74
+ type: string;
75
+ format: string;
76
+ default: string;
77
+ description: string;
78
+ };
79
+ };
80
+ };
@@ -6,7 +6,7 @@
6
6
  * handoffs and close alarm and machine-state rows.
7
7
  */
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.OPERATOR_FORM_SCHEMA = exports.HANDOFF_FORM_SCHEMA = void 0;
9
+ exports.QUALITY_FORM_SCHEMA = exports.OPERATOR_FORM_SCHEMA = exports.HANDOFF_FORM_SCHEMA = void 0;
10
10
  const contracts_1 = require("./contracts");
11
11
  exports.HANDOFF_FORM_SCHEMA = {
12
12
  title: 'Receive units',
@@ -35,3 +35,19 @@ exports.OPERATOR_FORM_SCHEMA = {
35
35
  clearedBy: { type: 'string', default: '', description: 'Who cleared it at the machine, when the machine reports it' },
36
36
  },
37
37
  };
38
+ exports.QUALITY_FORM_SCHEMA = {
39
+ title: 'Quality decision',
40
+ description: 'Units a machine finished on hold: release them to continue, send them back to a station for rework, or scrap them.',
41
+ 'x-lt-order': ['decision', 'station', 'note'],
42
+ required: ['decision'],
43
+ properties: {
44
+ decision: {
45
+ type: 'string',
46
+ enum: [contracts_1.DECISION.RELEASE, contracts_1.DECISION.REWORK, contracts_1.DECISION.SCRAP],
47
+ default: contracts_1.DECISION.RELEASE,
48
+ description: 'Release, rework or scrap',
49
+ },
50
+ station: { type: 'string', default: '', description: 'For rework: the station the units run again from; the holding station when empty' },
51
+ note: { type: 'string', format: 'textarea', default: '', description: 'What was found' },
52
+ },
53
+ };
@@ -18,14 +18,19 @@ export interface CreateRowInput {
18
18
  escalation_payload?: string;
19
19
  }
20
20
  export type Action =
21
- /** `receivedOnAccept`: the units are already at the machine, so its acceptance completes the handoff. */
21
+ /**
22
+ * `receivedOnAccept`: the units are already at the machine, so its acceptance completes the handoff.
23
+ * `ended`: the row already resolved; the job is sent again for units the machine still holds, and no verb touches the row.
24
+ */
22
25
  {
23
26
  kind: 'dispatch';
24
27
  rowId: string;
25
28
  machineId: string;
26
29
  cmdId: string;
27
30
  args: Record<string, any>;
31
+ issuedAt?: number;
28
32
  receivedOnAccept?: boolean;
33
+ ended?: boolean;
29
34
  } | {
30
35
  kind: 'command';
31
36
  machineId: string;
@@ -78,6 +83,8 @@ export type Action =
78
83
  cmdId: string;
79
84
  status: string;
80
85
  reason: string;
86
+ code?: string;
87
+ preparing?: boolean;
81
88
  }
82
89
  /** A machine reported the jobs it holds: answers a status query in flight. */
83
90
  | {
@@ -98,6 +105,12 @@ export type Action =
98
105
  machineId: string;
99
106
  address: string;
100
107
  reason: string;
108
+ }
109
+ /** Jobs a restarted machine lost that this gateway cannot send again: nothing of them is remembered. */
110
+ | {
111
+ kind: 'unrecoverable';
112
+ machineId: string;
113
+ jobs: string[];
101
114
  };
102
115
  /** Once the row holds every one of `keys`: resolve it with `payload`, or run `then` instead. */
103
116
  export interface Completion {
@@ -4,32 +4,58 @@
4
4
  * and under a strict codec a message that breaks the contract is held for a
5
5
  * person instead of acted on.
6
6
  */
7
+ import type { OpenRowQuery } from '../rows';
7
8
  import { type LineDef } from '../../../lib/machines/line';
8
- import type { Inspection } from '../../../lib/machines/protocol';
9
+ import { type Inspection } from '../../../lib/machines/protocol';
9
10
  import { type Disposition, type InboundMessage } from '../../../lib/machines/transport';
11
+ import type { WireAction } from '../../../types/machines-view';
10
12
  import type { Action } from './actions';
11
13
  import { type GatewayLog } from './log';
12
14
  import type { GatewayState } from './state';
13
- /** What handling one decoded message came to. */
15
+ /** What handling one decoded message came to, with what the gateway did for the wire record. */
14
16
  export interface Applied {
15
17
  disposition: Disposition;
16
18
  failed: boolean;
19
+ actions: WireAction[];
20
+ /** The address the message came from, when it was not admitted as a station's. */
21
+ sender?: {
22
+ machineId: string | null;
23
+ address: string | null;
24
+ };
25
+ }
26
+ /** A message admitted as a station's, with what admitting it did (a binding, say). */
27
+ export interface Admitted {
28
+ seen: Inspection;
29
+ actions: WireAction[];
17
30
  }
18
31
  export interface AdmissionContext {
19
32
  state: GatewayState;
20
33
  line: LineDef;
21
34
  executor: {
22
- apply(actions: Action[]): Promise<void>;
35
+ apply(actions: Action[]): Promise<WireAction[]>;
23
36
  };
24
37
  log: GatewayLog;
25
38
  /** Send waiting handoffs that may now go out. */
26
39
  pace(): Promise<void>;
40
+ /** The controller's pending rows of a type, for the rows shown to people once. */
41
+ openRows(query: OpenRowQuery): Promise<Record<string, any>[]>;
27
42
  }
28
43
  /**
29
44
  * The station a message is from (registration.ts). A newly claimed station is
30
45
  * bound and its waiting work goes out; a contested claim raises one row for a
31
46
  * person; either of those, and an address no station claims, is not acted on.
32
47
  */
33
- export declare function admitSender(ctx: AdmissionContext, topic: string, raw: Inspection): Promise<Inspection | Applied>;
48
+ export declare function admitSender(ctx: AdmissionContext, topic: string, raw: Inspection): Promise<Admitted | Applied>;
34
49
  /** Under a strict codec a broken message is not acted on: a person sees it on a row, once. */
35
50
  export declare function holdViolation(ctx: AdmissionContext, msg: InboundMessage, seen: Inspection): Promise<Applied>;
51
+ /** A job arrival: a scan, or a transfer that failed on the carrier read. */
52
+ export declare function isArrival(seen: Inspection): boolean;
53
+ /** An arrival that read no id at all: no row can ever claim it, so it goes to a person on its first delivery. */
54
+ export declare function isUnreadableArrival(seen: Inspection): boolean;
55
+ /**
56
+ * An arrival no open handoff into the machine expects, after every delivery:
57
+ * a person sees it on one handoff-error row per machine and carrier, with the
58
+ * raw arrival, so the unit can be re-scanned or routed. Resolving the row lets
59
+ * the next such arrival raise one again.
60
+ */
61
+ export declare function holdArrival(ctx: AdmissionContext, msg: InboundMessage, seen: Inspection): Promise<Applied>;
@@ -8,11 +8,19 @@
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.admitSender = admitSender;
10
10
  exports.holdViolation = holdViolation;
11
+ exports.isArrival = isArrival;
12
+ exports.isUnreadableArrival = isUnreadableArrival;
13
+ exports.holdArrival = holdArrival;
11
14
  const contracts_1 = require("../contracts");
12
15
  const line_1 = require("../../../lib/machines/line");
16
+ const protocol_1 = require("../../../lib/machines/protocol");
13
17
  const transport_1 = require("../../../lib/machines/transport");
18
+ const dispatcher_1 = require("./dispatcher");
14
19
  const log_1 = require("./log");
15
20
  const registration_1 = require("./registration");
21
+ function from(sender) {
22
+ return { machineId: sender.machineId ?? null, address: sender.address };
23
+ }
16
24
  /**
17
25
  * The station a message is from (registration.ts). A newly claimed station is
18
26
  * bound and its waiting work goes out; a contested claim raises one row for a
@@ -20,47 +28,101 @@ const registration_1 = require("./registration");
20
28
  */
21
29
  async function admitSender(ctx, topic, raw) {
22
30
  const sender = (0, registration_1.resolveSender)(ctx.state, ctx.line, raw);
31
+ const actions = [];
23
32
  try {
24
33
  if (sender.status === registration_1.SENDER.BOUND) {
25
- await ctx.executor.apply([{ kind: 'bindAddress', machineId: sender.machineId, address: sender.address }]);
34
+ actions.push(...await ctx.executor.apply([{ kind: 'bindAddress', machineId: sender.machineId, address: sender.address }]));
26
35
  await ctx.pace();
27
36
  }
28
37
  if (sender.seen)
29
- return sender.seen;
38
+ return { seen: sender.seen, actions };
30
39
  if (sender.status === registration_1.SENDER.CONTESTED)
31
40
  ctx.state.hearClaim(sender.address, sender.machineId);
32
41
  if (sender.status === registration_1.SENDER.CONTESTED && !ctx.state.claimRaised(sender.address, sender.machineId)) {
33
- await ctx.executor.apply([{ kind: 'createRow', row: (0, registration_1.registrationRow)(ctx.state, ctx.line, sender.address, sender.machineId) }]);
34
- ctx.state.raiseClaim(sender.address, sender.machineId);
42
+ const [made] = await ctx.executor.apply([{ kind: 'createRow', row: (0, registration_1.registrationRow)(ctx.state, ctx.line, sender.address, sender.machineId) }]);
43
+ ctx.state.raiseClaim(sender.address, sender.machineId, made?.rowId);
35
44
  ctx.log.warn(log_1.GATEWAY_LOG.ADDRESS_CONTESTED, { topic, address: sender.address, machine: sender.machineId });
45
+ actions.push({ ...made, detail: `${sender.address} says it is ${sender.machineId}; a person decides` });
46
+ }
47
+ else if (sender.status === registration_1.SENDER.CONTESTED) {
48
+ actions.push({ verb: 'none', detail: `${sender.address} says it is ${sender.machineId}; waiting for a person` });
36
49
  }
37
- if (sender.status === registration_1.SENDER.UNKNOWN && ctx.state.firstHeardStranger(sender.address))
38
- ctx.log.warn(log_1.GATEWAY_LOG.ADDRESS_UNKNOWN, { topic, address: sender.address });
39
- return { disposition: transport_1.DISPOSITION.ACK, failed: false };
50
+ if (sender.status === registration_1.SENDER.UNKNOWN) {
51
+ if (ctx.state.firstHeardStranger(sender.address))
52
+ ctx.log.warn(log_1.GATEWAY_LOG.ADDRESS_UNKNOWN, { topic, address: sender.address });
53
+ actions.push({ verb: 'none', detail: `${sender.address} claims no station on this line` });
54
+ }
55
+ return { disposition: transport_1.DISPOSITION.ACK, failed: false, actions, sender: from(sender) };
40
56
  }
41
57
  catch (err) {
42
- ctx.log.error(log_1.GATEWAY_LOG.VERB_FAILED, { topic, error: err.message });
43
- return { disposition: transport_1.DISPOSITION.NAK, failed: true };
58
+ if (!(err instanceof dispatcher_1.GatewayStopped))
59
+ ctx.log.error(log_1.GATEWAY_LOG.VERB_FAILED, { topic, error: err.message });
60
+ return { disposition: transport_1.DISPOSITION.NAK, failed: true, actions, sender: from(sender) };
44
61
  }
45
62
  }
46
63
  /** Under a strict codec a broken message is not acted on: a person sees it on a row, once. */
47
64
  async function holdViolation(ctx, msg, seen) {
48
65
  const { ident, kind } = seen.parsed;
49
66
  const key = seen.receiptId ?? seen.body?.id ?? `${msg.topic}:${msg.payload}`;
67
+ const detail = seen.violations.join('; ');
50
68
  if (ctx.state.violationRaised(key))
51
- return { disposition: transport_1.DISPOSITION.ACK, failed: false };
69
+ return { disposition: transport_1.DISPOSITION.ACK, failed: false, actions: [{ verb: 'hold', detail: `${detail} (already shown to a person)` }] };
52
70
  try {
53
- await ctx.executor.apply([{ kind: 'createRow', row: {
71
+ const [made] = await ctx.executor.apply([{ kind: 'createRow', row: {
54
72
  type: contracts_1.ROW_TYPE.CONTRACT_VIOLATION, role: (0, line_1.operatorRole)(ctx.line), priority: 2,
55
73
  description: `${ident.machineId} sent a ${kind} message that breaks the contract: ${seen.violations.join('; ')}`,
56
74
  metadata: { siteId: ident.siteId, lineId: ident.lineId, machineId: ident.machineId, kind, topic: msg.topic, messageId: seen.body?.id ?? null, violations: seen.violations },
57
75
  escalation_payload: msg.payload,
58
76
  } }]);
59
77
  ctx.state.raiseViolation(key);
60
- return { disposition: transport_1.DISPOSITION.ACK, failed: false };
78
+ return { disposition: transport_1.DISPOSITION.ACK, failed: false, actions: [{ verb: 'hold', rowId: made?.rowId, detail }] };
79
+ }
80
+ catch (err) {
81
+ if (!(err instanceof dispatcher_1.GatewayStopped))
82
+ ctx.log.error(log_1.GATEWAY_LOG.VERB_FAILED, { topic: msg.topic, error: err.message });
83
+ return { disposition: transport_1.DISPOSITION.NAK, failed: true, actions: [] };
84
+ }
85
+ }
86
+ /** A job arrival: a scan, or a transfer that failed on the carrier read. */
87
+ function isArrival(seen) {
88
+ const event = seen.body?.body?.event;
89
+ return seen.parsed?.kind === protocol_1.MESSAGE_KIND.JOB && (event === protocol_1.JOB_EVENT.ARRIVED || event === protocol_1.JOB_EVENT.TRANSFER_FAILED);
90
+ }
91
+ /** An arrival that read no id at all: no row can ever claim it, so it goes to a person on its first delivery. */
92
+ function isUnreadableArrival(seen) {
93
+ return seen.parsed?.kind === protocol_1.MESSAGE_KIND.JOB && (0, protocol_1.isUnreadableRead)(seen.body?.body ?? {});
94
+ }
95
+ /**
96
+ * An arrival no open handoff into the machine expects, after every delivery:
97
+ * a person sees it on one handoff-error row per machine and carrier, with the
98
+ * raw arrival, so the unit can be re-scanned or routed. Resolving the row lets
99
+ * the next such arrival raise one again.
100
+ */
101
+ async function holdArrival(ctx, msg, seen) {
102
+ const { ident } = seen.parsed;
103
+ const body = seen.body?.body ?? {};
104
+ const carrierId = typeof body.carrierId === 'string' ? body.carrierId : null;
105
+ const unitId = typeof body.unitId === 'string' ? body.unitId : null;
106
+ const detail = `no handoff into ${ident.machineId} expects ${carrierId ? `carrier ${carrierId}` : 'an unreadable carrier'}`;
107
+ try {
108
+ const open = await ctx.openRows({ type: contracts_1.ROW_TYPE.HANDOFF_ERROR, role: (0, line_1.operatorRole)(ctx.line) });
109
+ const shown = open.find((r) => r.metadata?.errorCode === contracts_1.HANDOFF_ERROR.UNMATCHED_ARRIVAL && r.metadata?.machineId === ident.machineId && (r.metadata?.carrierId ?? null) === carrierId);
110
+ if (shown)
111
+ return { disposition: transport_1.DISPOSITION.ACK, failed: false, actions: [{ verb: 'unmatched', rowId: shown.id, detail: `${detail} (already shown to a person)` }] };
112
+ const [made] = await ctx.executor.apply([{ kind: 'createRow', row: {
113
+ type: contracts_1.ROW_TYPE.HANDOFF_ERROR, role: (0, line_1.operatorRole)(ctx.line), priority: 2,
114
+ description: `${ident.machineId} reports an arrival no handoff expects: ${carrierId ? `carrier ${carrierId}` : 'the carrier could not be read'}`,
115
+ metadata: {
116
+ siteId: ident.siteId, lineId: ident.lineId, machineId: ident.machineId, errorCode: contracts_1.HANDOFF_ERROR.UNMATCHED_ARRIVAL,
117
+ carrierId, unitId, event: body.event, topic: msg.topic, messageId: seen.body?.id ?? null, arrival: body,
118
+ },
119
+ escalation_payload: msg.payload,
120
+ } }]);
121
+ return { disposition: transport_1.DISPOSITION.ACK, failed: false, actions: [{ verb: 'create-row', rowId: made?.rowId, detail }] };
61
122
  }
62
123
  catch (err) {
63
- ctx.log.error(log_1.GATEWAY_LOG.VERB_FAILED, { topic: msg.topic, error: err.message });
64
- return { disposition: transport_1.DISPOSITION.NAK, failed: true };
124
+ if (!(err instanceof dispatcher_1.GatewayStopped))
125
+ ctx.log.error(log_1.GATEWAY_LOG.VERB_FAILED, { topic: msg.topic, error: err.message });
126
+ return { disposition: transport_1.DISPOSITION.NAK, failed: true, actions: [] };
65
127
  }
66
128
  }
@@ -42,6 +42,8 @@ const escalationApi = __importStar(require("../../../api/escalations"));
42
42
  const uuid_1 = require("../../../lib/uuid");
43
43
  const escalations_1 = require("./escalations");
44
44
  const actions_1 = require("./actions");
45
+ /** A row that was never given items (one parked by hand) answers 400; it holds none. */
46
+ const NO_ITEMS_STATUS = 400;
45
47
  class ApiLineEscalations {
46
48
  constructor(userFor) {
47
49
  this.userFor = userFor;
@@ -75,6 +77,8 @@ class ApiLineEscalations {
75
77
  }
76
78
  async items(id) {
77
79
  const result = await escalationApi.getEscalationItems({ id }, this.auth(actions_1.CONTROLLER));
80
+ if (result.status === NO_ITEMS_STATUS)
81
+ return [];
78
82
  if (result.status >= 300)
79
83
  throw new Error(`items failed ${result.status}: ${result.error}`);
80
84
  return result.data.items.map((i) => ({ itemKey: i.itemKey, payload: i.payload ?? {} }));