agentworkshop 0.8.1 → 0.8.3

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 (1563) hide show
  1. package/.output/.AgentWorkShop/aml-python/train-example.py +92 -92
  2. package/.output/nitro.json +1 -1
  3. package/.output/public/_nuxt/{BCLUwdP52.js → 39W1CH-l2.js} +1 -1
  4. package/.output/public/_nuxt/7xbYPfY6.js +1 -0
  5. package/.output/public/_nuxt/{BfvuWqSa.js → ATAvN55g.js} +1 -1
  6. package/.output/public/_nuxt/{B2NbzUau2.js → B3eCVqcT2.js} +1 -1
  7. package/.output/public/_nuxt/{DuUc4bbY2.js → B9qIhT7k2.js} +1 -1
  8. package/.output/public/_nuxt/{BkEokGX5.js → BE9oKpOt.js} +1 -1
  9. package/.output/public/_nuxt/{D_59BNP1.js → Bbk1XCCM.js} +3 -3
  10. package/.output/public/_nuxt/{Dz9C2pTa.js → CMzExk8F.js} +1 -1
  11. package/.output/public/_nuxt/{dHwWyr6b.js → CT4bi_Y4.js} +1 -1
  12. package/.output/public/_nuxt/{26OL4Ao82.js → CeCSjB9O2.js} +1 -1
  13. package/.output/public/_nuxt/{Dyxf2xZw.js → Cot5VNae.js} +1 -1
  14. package/.output/public/_nuxt/{BVg2R2VB2.js → Crf8_Ad02.js} +1 -1
  15. package/.output/public/_nuxt/{rDvMijKA.js → D9tNM-1a.js} +2 -2
  16. package/.output/public/_nuxt/{YAA98rWJ.js → DAug2CPf.js} +7 -7
  17. package/.output/public/_nuxt/{CQSxS_Ek.js → DbhTN7-T.js} +1 -1
  18. package/.output/public/_nuxt/DgGzwjAr2.js +2 -0
  19. package/.output/public/_nuxt/DkRozlDP2.js +1 -0
  20. package/.output/public/_nuxt/{DGu_fna7.js → DoChWkff.js} +1 -1
  21. package/.output/public/_nuxt/{Byiiiwc72.js → DxH5focQ2.js} +1 -1
  22. package/.output/public/_nuxt/Dyr3LPGL.js +1 -0
  23. package/.output/public/_nuxt/{CC2Pv8VL2.js → MC_i34H42.js} +1 -1
  24. package/.output/public/_nuxt/OmpTerminalPanel.DMWgGwDs.css +1 -0
  25. package/.output/public/_nuxt/PluginSlot.BqBzLD4T.css +1 -0
  26. package/.output/public/_nuxt/TownView.Cn8SPG7S.css +1 -0
  27. package/.output/public/_nuxt/{CmuGMxDP.js → TugRY_4O.js} +1 -1
  28. package/.output/public/_nuxt/{BPUQZ9Lq2.js → WybiLTow2.js} +1 -1
  29. package/.output/public/_nuxt/{BaYDgyaR.js → Zn0BZpf0.js} +3 -3
  30. package/.output/public/_nuxt/{_id_.BQRWK7J2.css → _id_.Be5JaH-P.css} +1 -1
  31. package/.output/public/_nuxt/{_wsId_.DCnKQQdY.css → _wsId_.p_vAYtTp.css} +1 -1
  32. package/.output/public/_nuxt/{agents.D-JPovTZ.css → agents.CRomddYR.css} +1 -1
  33. package/.output/public/_nuxt/aml.DgOMpDpv.css +1 -0
  34. package/.output/public/_nuxt/builds/latest.json +1 -1
  35. package/.output/public/_nuxt/builds/meta/fd0033e4-1eaa-42f8-9a04-3132717a703b.json +1 -0
  36. package/.output/public/_nuxt/{default.BEXGWZFQ.css → default.CpAx70gC.css} +1 -1
  37. package/.output/public/_nuxt/{logs.BkJPbR_K.css → logs.DcSvz6vi.css} +1 -1
  38. package/.output/public/_nuxt/{monitor.D3yEqqrv.css → monitor.OoNTwfMJ.css} +1 -1
  39. package/.output/public/_nuxt/{ontology.B_3Wn907.css → ontology.JqJ6PjV1.css} +1 -1
  40. package/.output/public/_nuxt/{operations.-l6u44Ar.css → operations.C48ggFa5.css} +1 -1
  41. package/.output/public/_nuxt/{pages.Cdpm_B-G.css → pages.Dpa28tJW.css} +1 -1
  42. package/.output/public/_nuxt/permissions.CrV-4t-6.css +1 -0
  43. package/.output/public/_nuxt/{BfeXib9G.js → rcdmiszh2.js} +1 -1
  44. package/.output/public/_nuxt/schedules.DYWOjGHm.css +1 -0
  45. package/.output/public/_nuxt/{teams.CLQaXno5.css → teams.DEJoJ4QV.css} +1 -1
  46. package/.output/public/_nuxt/{tokens.BDSUWF-L.css → tokens.DKZWCP5v.css} +1 -1
  47. package/.output/public/_nuxt/tools.DP-nsTli.css +1 -0
  48. package/.output/public/_nuxt/wK6Pp4Zc2.js +2 -0
  49. package/.output/public/_nuxt/{workshop.BBiFhXuM.css → workshop.PT1xhP8C.css} +1 -1
  50. package/.output/public/favicon.svg +14 -14
  51. package/.output/public/robots.txt +3 -3
  52. package/.output/server/chunks/_/LeftOutlined.mjs.map +1 -1
  53. package/.output/server/chunks/_/RightOutlined.mjs.map +1 -1
  54. package/.output/server/chunks/_/SearchOutlined.mjs +1230 -1261
  55. package/.output/server/chunks/_/SearchOutlined.mjs.map +1 -1
  56. package/.output/server/chunks/_/error-500.mjs.map +1 -1
  57. package/.output/server/chunks/_/nitro.mjs +3308 -3389
  58. package/.output/server/chunks/_/nitro.mjs.map +1 -1
  59. package/.output/server/chunks/build/AuthGate-G74Wr5IV.mjs +704 -0
  60. package/.output/server/chunks/build/AuthGate-G74Wr5IV.mjs.map +1 -0
  61. package/.output/server/chunks/build/FormItemContext-DmuQqaeJ.mjs +77 -0
  62. package/.output/server/chunks/build/FormItemContext-DmuQqaeJ.mjs.map +1 -0
  63. package/.output/server/chunks/build/OmpTerminalPanel-5cB-78zp.mjs +889 -0
  64. package/.output/server/chunks/build/OmpTerminalPanel-5cB-78zp.mjs.map +1 -0
  65. package/.output/server/chunks/build/PluginSlot-CZlGlRoR.mjs +131 -0
  66. package/.output/server/chunks/build/PluginSlot-CZlGlRoR.mjs.map +1 -0
  67. package/.output/server/chunks/build/TownView-CUbzOT_M.mjs +5960 -0
  68. package/.output/server/chunks/build/TownView-CUbzOT_M.mjs.map +1 -0
  69. package/.output/server/chunks/build/_id_-BHWZiRQZ.mjs +373 -0
  70. package/.output/server/chunks/build/_id_-BHWZiRQZ.mjs.map +1 -0
  71. package/.output/server/chunks/build/_id_-JaGx0yBE.mjs +1922 -0
  72. package/.output/server/chunks/build/_id_-JaGx0yBE.mjs.map +1 -0
  73. package/.output/server/chunks/build/_wsId_-C4DKkEqv.mjs +13707 -0
  74. package/.output/server/chunks/build/_wsId_-C4DKkEqv.mjs.map +1 -0
  75. package/.output/server/chunks/build/agents-DRod4lTC.mjs +1047 -0
  76. package/.output/server/chunks/build/agents-DRod4lTC.mjs.map +1 -0
  77. package/.output/server/chunks/build/alert-CNGhs--Y.mjs +260 -0
  78. package/.output/server/chunks/build/alert-CNGhs--Y.mjs.map +1 -0
  79. package/.output/server/chunks/build/aml-B3Umz4DR.mjs +729 -0
  80. package/.output/server/chunks/build/aml-B3Umz4DR.mjs.map +1 -0
  81. package/.output/server/chunks/build/analysis-tNpFLtMt.mjs +502 -0
  82. package/.output/server/chunks/build/analysis-tNpFLtMt.mjs.map +1 -0
  83. package/.output/server/chunks/build/{api-B4Om0mEc.mjs → api-D-zkgkj-.mjs} +8 -10
  84. package/.output/server/chunks/build/api-D-zkgkj-.mjs.map +1 -0
  85. package/.output/server/chunks/build/{api-BsAgXWxi.mjs → api-D3gy2e2q.mjs} +22 -24
  86. package/.output/server/chunks/build/api-D3gy2e2q.mjs.map +1 -0
  87. package/.output/server/chunks/build/{api-BEW_ebY_.mjs → api-bn4OKkl_.mjs} +17 -19
  88. package/.output/server/chunks/build/api-bn4OKkl_.mjs.map +1 -0
  89. package/.output/server/chunks/build/api-error-CnW_xiNI.mjs +46 -0
  90. package/.output/server/chunks/build/api-error-CnW_xiNI.mjs.map +1 -0
  91. package/.output/server/chunks/build/apiClient-DIXx9sfD.mjs +70 -0
  92. package/.output/server/chunks/build/apiClient-DIXx9sfD.mjs.map +1 -0
  93. package/.output/server/chunks/build/board-B2oYXGBy.mjs +172 -0
  94. package/.output/server/chunks/build/board-B2oYXGBy.mjs.map +1 -0
  95. package/.output/server/chunks/build/builtin-catalog-edpDcgfL.mjs +81 -94
  96. package/.output/server/chunks/build/builtin-catalog-edpDcgfL.mjs.map +1 -1
  97. package/.output/server/chunks/build/card-BECE6y_G.mjs +922 -0
  98. package/.output/server/chunks/build/card-BECE6y_G.mjs.map +1 -0
  99. package/.output/server/chunks/build/channel-templates-R2TInv8B.mjs +950 -0
  100. package/.output/server/chunks/build/channel-templates-R2TInv8B.mjs.map +1 -0
  101. package/.output/server/chunks/build/chart-trend-BWeZh5Lv.mjs +113 -112
  102. package/.output/server/chunks/build/chart-trend-BWeZh5Lv.mjs.map +1 -1
  103. package/.output/server/chunks/build/checkbox-C6xY5uc6.mjs +429 -0
  104. package/.output/server/chunks/build/checkbox-C6xY5uc6.mjs.map +1 -0
  105. package/.output/server/chunks/build/client-only-S7k53PIm.mjs +42 -0
  106. package/.output/server/chunks/build/client-only-S7k53PIm.mjs.map +1 -0
  107. package/.output/server/chunks/build/constants-HPHJvjne.mjs +65 -75
  108. package/.output/server/chunks/build/constants-HPHJvjne.mjs.map +1 -1
  109. package/.output/server/chunks/build/core-CRlsQhzd.mjs +292 -0
  110. package/.output/server/chunks/build/core-CRlsQhzd.mjs.map +1 -0
  111. package/.output/server/chunks/build/daq-DHsYtWC-.mjs +1210 -0
  112. package/.output/server/chunks/build/daq-DHsYtWC-.mjs.map +1 -0
  113. package/.output/server/chunks/build/data-Cl4wRZO6.mjs +459 -0
  114. package/.output/server/chunks/build/data-Cl4wRZO6.mjs.map +1 -0
  115. package/.output/server/chunks/build/dcw-DnjOM6p1.mjs +467 -0
  116. package/.output/server/chunks/build/dcw-DnjOM6p1.mjs.map +1 -0
  117. package/.output/server/chunks/build/dcw-driver-badge-Df5wL_ZA.mjs +3 -15
  118. package/.output/server/chunks/build/dcw-driver-badge-Df5wL_ZA.mjs.map +1 -1
  119. package/.output/server/chunks/build/default-DDRKP2Mb.mjs +2246 -0
  120. package/.output/server/chunks/build/default-DDRKP2Mb.mjs.map +1 -0
  121. package/.output/server/chunks/build/descriptions-B3uhDesi.mjs +401 -0
  122. package/.output/server/chunks/build/descriptions-B3uhDesi.mjs.map +1 -0
  123. package/.output/server/chunks/build/drawer-DwXxapMg.mjs +822 -0
  124. package/.output/server/chunks/build/drawer-DwXxapMg.mjs.map +1 -0
  125. package/.output/server/chunks/build/dropdown-DLrGy-Fs.mjs +12 -0
  126. package/.output/server/chunks/build/dropdown-DLrGy-Fs.mjs.map +1 -0
  127. package/.output/server/chunks/build/dropdown-nsGv8Gqx.mjs +530 -0
  128. package/.output/server/chunks/build/dropdown-nsGv8Gqx.mjs.map +1 -0
  129. package/.output/server/chunks/build/{es-Bxu10NJ2.mjs → es-DXSEkmAm.mjs} +1 -2
  130. package/.output/server/chunks/build/es-DXSEkmAm.mjs.map +1 -0
  131. package/.output/server/chunks/build/firstNotUndefined-laiThpLD.mjs +2082 -0
  132. package/.output/server/chunks/build/firstNotUndefined-laiThpLD.mjs.map +1 -0
  133. package/.output/server/chunks/build/form-Cw2Ex9w5.mjs +3543 -0
  134. package/.output/server/chunks/build/form-Cw2Ex9w5.mjs.map +1 -0
  135. package/.output/server/chunks/build/hasIn-RYRGomyg.mjs +192 -0
  136. package/.output/server/chunks/build/hasIn-RYRGomyg.mjs.map +1 -0
  137. package/.output/server/chunks/build/hitl-B4cHRlkC.mjs +120 -0
  138. package/.output/server/chunks/build/hitl-B4cHRlkC.mjs.map +1 -0
  139. package/.output/server/chunks/build/input-CJgB-RL6.mjs +1705 -0
  140. package/.output/server/chunks/build/input-CJgB-RL6.mjs.map +1 -0
  141. package/.output/server/chunks/build/input-number-CQKL42p_.mjs +1027 -0
  142. package/.output/server/chunks/build/input-number-CQKL42p_.mjs.map +1 -0
  143. package/.output/server/chunks/build/interval-DiAUqODq.mjs +8 -0
  144. package/.output/server/chunks/build/interval-DiAUqODq.mjs.map +1 -0
  145. package/.output/server/chunks/build/isNumeric-DQiJ-b15.mjs +6 -0
  146. package/.output/server/chunks/build/isNumeric-DQiJ-b15.mjs.map +1 -0
  147. package/.output/server/chunks/build/logs-C4vKFkHQ.mjs +381 -0
  148. package/.output/server/chunks/build/logs-C4vKFkHQ.mjs.map +1 -0
  149. package/.output/server/chunks/build/menu-xO8ocVtL.mjs +1833 -0
  150. package/.output/server/chunks/build/menu-xO8ocVtL.mjs.map +1 -0
  151. package/.output/server/chunks/build/monitor-BNrG6v3b.mjs +2216 -0
  152. package/.output/server/chunks/build/monitor-BNrG6v3b.mjs.map +1 -0
  153. package/.output/server/chunks/build/narrow-fetch-CcG-BPxc.mjs +0 -2
  154. package/.output/server/chunks/build/narrow-fetch-CcG-BPxc.mjs.map +1 -1
  155. package/.output/server/chunks/build/ontology-B_0Vm6j-.mjs +1416 -0
  156. package/.output/server/chunks/build/ontology-B_0Vm6j-.mjs.map +1 -0
  157. package/.output/server/chunks/build/operations-D8D6-Jm-.mjs +278 -0
  158. package/.output/server/chunks/build/operations-D8D6-Jm-.mjs.map +1 -0
  159. package/.output/server/chunks/build/optimizer-DaTyaY3c.mjs +202 -0
  160. package/.output/server/chunks/build/optimizer-DaTyaY3c.mjs.map +1 -0
  161. package/.output/server/chunks/build/pages-Dac4icQC.mjs +439 -0
  162. package/.output/server/chunks/build/pages-Dac4icQC.mjs.map +1 -0
  163. package/.output/server/chunks/build/pagination-BTzq7dD5.mjs +1330 -0
  164. package/.output/server/chunks/build/pagination-BTzq7dD5.mjs.map +1 -0
  165. package/.output/server/chunks/build/permissions-qmimwB0M.mjs +649 -0
  166. package/.output/server/chunks/build/permissions-qmimwB0M.mjs.map +1 -0
  167. package/.output/server/chunks/build/plugins-Dh_goy-k.mjs +269 -0
  168. package/.output/server/chunks/build/plugins-Dh_goy-k.mjs.map +1 -0
  169. package/.output/server/chunks/build/popconfirm-DuGF7ty-.mjs +333 -0
  170. package/.output/server/chunks/build/popconfirm-DuGF7ty-.mjs.map +1 -0
  171. package/.output/server/chunks/build/responsiveObserve-CzRpNXkr.mjs +77 -0
  172. package/.output/server/chunks/build/responsiveObserve-CzRpNXkr.mjs.map +1 -0
  173. package/.output/server/chunks/build/schedules-C2_x38gj.mjs +7039 -0
  174. package/.output/server/chunks/build/schedules-C2_x38gj.mjs.map +1 -0
  175. package/.output/server/chunks/build/segmented-29uEKZ3D.mjs +332 -0
  176. package/.output/server/chunks/build/segmented-29uEKZ3D.mjs.map +1 -0
  177. package/.output/server/chunks/build/select-CJb2XrQf.mjs +3734 -0
  178. package/.output/server/chunks/build/select-CJb2XrQf.mjs.map +1 -0
  179. package/.output/server/chunks/build/settings-Cz2Plds0.mjs +944 -0
  180. package/.output/server/chunks/build/settings-Cz2Plds0.mjs.map +1 -0
  181. package/.output/server/chunks/build/space-BByD-mFE.mjs +107 -0
  182. package/.output/server/chunks/build/space-BByD-mFE.mjs.map +1 -0
  183. package/.output/server/chunks/build/spin-XhbgGeLP.mjs +313 -0
  184. package/.output/server/chunks/build/spin-XhbgGeLP.mjs.map +1 -0
  185. package/.output/server/chunks/build/studio-CwYXl00G.mjs +329 -0
  186. package/.output/server/chunks/build/studio-CwYXl00G.mjs.map +1 -0
  187. package/.output/server/chunks/build/switch-DWcwVFxW.mjs +374 -0
  188. package/.output/server/chunks/build/switch-DWcwVFxW.mjs.map +1 -0
  189. package/.output/server/chunks/build/table-Zhuo7Fq-.mjs +7249 -0
  190. package/.output/server/chunks/build/table-Zhuo7Fq-.mjs.map +1 -0
  191. package/.output/server/chunks/build/tabs-BCwBXjNt.mjs +1838 -0
  192. package/.output/server/chunks/build/tabs-BCwBXjNt.mjs.map +1 -0
  193. package/.output/server/chunks/build/tag-CRW-anwy.mjs +1010 -0
  194. package/.output/server/chunks/build/tag-CRW-anwy.mjs.map +1 -0
  195. package/.output/server/chunks/build/teams-CwhFdcYn.mjs +1160 -0
  196. package/.output/server/chunks/build/teams-CwhFdcYn.mjs.map +1 -0
  197. package/.output/server/chunks/build/tokens-C5ODO1HA.mjs +992 -0
  198. package/.output/server/chunks/build/tokens-C5ODO1HA.mjs.map +1 -0
  199. package/.output/server/chunks/build/tools-C0YKragH.mjs +487 -0
  200. package/.output/server/chunks/build/tools-C0YKragH.mjs.map +1 -0
  201. package/.output/server/chunks/build/tooltip-GlMrUZzx.mjs +888 -0
  202. package/.output/server/chunks/build/tooltip-GlMrUZzx.mjs.map +1 -0
  203. package/.output/server/chunks/build/town-BV-hbwb5.mjs +16 -29
  204. package/.output/server/chunks/build/town-BV-hbwb5.mjs.map +1 -1
  205. package/.output/server/chunks/build/town-LkDwWnKA.mjs +117 -0
  206. package/.output/server/chunks/build/town-LkDwWnKA.mjs.map +1 -0
  207. package/.output/server/chunks/build/types-D6J7slEa.mjs.map +1 -1
  208. package/.output/server/chunks/build/types-DWqIeMRP.mjs +28 -29
  209. package/.output/server/chunks/build/types-DWqIeMRP.mjs.map +1 -1
  210. package/.output/server/chunks/build/useAgentHarnessOptions-CYKuLtZ2.mjs +120 -0
  211. package/.output/server/chunks/build/useAgentHarnessOptions-CYKuLtZ2.mjs.map +1 -0
  212. package/.output/server/chunks/build/useAgentTemplateActions-Da_V1LSD.mjs +71 -0
  213. package/.output/server/chunks/build/useAgentTemplateActions-Da_V1LSD.mjs.map +1 -0
  214. package/.output/server/chunks/build/useAgentTemplateDialogState-CZzpu5og.mjs +16 -23
  215. package/.output/server/chunks/build/useAgentTemplateDialogState-CZzpu5og.mjs.map +1 -1
  216. package/.output/server/chunks/build/useAgentTemplateForm-BWvax5_E.mjs +112 -0
  217. package/.output/server/chunks/build/useAgentTemplateForm-BWvax5_E.mjs.map +1 -0
  218. package/.output/server/chunks/build/useAgentTemplatesCatalog-BnYjZy59.mjs +140 -0
  219. package/.output/server/chunks/build/useAgentTemplatesCatalog-BnYjZy59.mjs.map +1 -0
  220. package/.output/server/chunks/build/useAmlDatasets-nGi10DAl.mjs +88 -0
  221. package/.output/server/chunks/build/useAmlDatasets-nGi10DAl.mjs.map +1 -0
  222. package/.output/server/chunks/build/useAmlEntities-CTgNAgcZ.mjs +79 -0
  223. package/.output/server/chunks/build/useAmlEntities-CTgNAgcZ.mjs.map +1 -0
  224. package/.output/server/chunks/build/useAmlEnv-Da2TVfyK.mjs +188 -0
  225. package/.output/server/chunks/build/useAmlEnv-Da2TVfyK.mjs.map +1 -0
  226. package/.output/server/chunks/build/useAmlExperiments-U9AQ52RI.mjs +86 -0
  227. package/.output/server/chunks/build/useAmlExperiments-U9AQ52RI.mjs.map +1 -0
  228. package/.output/server/chunks/build/useAmlFormat-C2sl3MGB.mjs +32 -37
  229. package/.output/server/chunks/build/useAmlFormat-C2sl3MGB.mjs.map +1 -1
  230. package/.output/server/chunks/build/useAmlJobs-BM1mu5iH.mjs +251 -0
  231. package/.output/server/chunks/build/useAmlJobs-BM1mu5iH.mjs.map +1 -0
  232. package/.output/server/chunks/build/useAmlModels-C1DwIOMi.mjs +90 -0
  233. package/.output/server/chunks/build/useAmlModels-C1DwIOMi.mjs.map +1 -0
  234. package/.output/server/chunks/build/useAmlNotes-CNm47QdS.mjs +80 -0
  235. package/.output/server/chunks/build/useAmlNotes-CNm47QdS.mjs.map +1 -0
  236. package/.output/server/chunks/build/useAmlPredict-m8I1AdRn.mjs +126 -0
  237. package/.output/server/chunks/build/useAmlPredict-m8I1AdRn.mjs.map +1 -0
  238. package/.output/server/chunks/build/useAnalysisFeed-CpbOaiBD.mjs +120 -0
  239. package/.output/server/chunks/build/useAnalysisFeed-CpbOaiBD.mjs.map +1 -0
  240. package/.output/server/chunks/build/useDaqAddNode-CRorxgOY.mjs +141 -0
  241. package/.output/server/chunks/build/useDaqAddNode-CRorxgOY.mjs.map +1 -0
  242. package/.output/server/chunks/build/useDaqDetailBinding-Ck-YUW9J.mjs +72 -0
  243. package/.output/server/chunks/build/useDaqDetailBinding-Ck-YUW9J.mjs.map +1 -0
  244. package/.output/server/chunks/build/useDaqDetailFrames-CLMoreaz.mjs +78 -0
  245. package/.output/server/chunks/build/useDaqDetailFrames-CLMoreaz.mjs.map +1 -0
  246. package/.output/server/chunks/build/useDaqDetailHistory-BVNQXwC_.mjs +166 -0
  247. package/.output/server/chunks/build/useDaqDetailHistory-BVNQXwC_.mjs.map +1 -0
  248. package/.output/server/chunks/build/useDaqDetailNode-BC0e9OfX.mjs +103 -0
  249. package/.output/server/chunks/build/useDaqDetailNode-BC0e9OfX.mjs.map +1 -0
  250. package/.output/server/chunks/build/useDaqDetailParams-D173iwFg.mjs +157 -0
  251. package/.output/server/chunks/build/useDaqDetailParams-D173iwFg.mjs.map +1 -0
  252. package/.output/server/chunks/build/useDaqFilters-CC-o_21d.mjs +224 -0
  253. package/.output/server/chunks/build/useDaqFilters-CC-o_21d.mjs.map +1 -0
  254. package/.output/server/chunks/build/useDaqNodeWindow-1DWj2H5G.mjs +43 -44
  255. package/.output/server/chunks/build/useDaqNodeWindow-1DWj2H5G.mjs.map +1 -1
  256. package/.output/server/chunks/build/useDaqOptimizations-4vK2w1yn.mjs +132 -0
  257. package/.output/server/chunks/build/useDaqOptimizations-4vK2w1yn.mjs.map +1 -0
  258. package/.output/server/chunks/build/useDaqStream-BHKpSJFd.mjs +385 -0
  259. package/.output/server/chunks/build/useDaqStream-BHKpSJFd.mjs.map +1 -0
  260. package/.output/server/chunks/build/useDaqTemplates-CsXSc7yI.mjs +181 -0
  261. package/.output/server/chunks/build/useDaqTemplates-CsXSc7yI.mjs.map +1 -0
  262. package/.output/server/chunks/build/useDashboardCharts-D45083s_.mjs +312 -310
  263. package/.output/server/chunks/build/useDashboardCharts-D45083s_.mjs.map +1 -1
  264. package/.output/server/chunks/build/useDashboardData-DuKjuJTz.mjs +139 -0
  265. package/.output/server/chunks/build/useDashboardData-DuKjuJTz.mjs.map +1 -0
  266. package/.output/server/chunks/build/useDcwAddNode-C5DcxsHF.mjs +217 -0
  267. package/.output/server/chunks/build/useDcwAddNode-C5DcxsHF.mjs.map +1 -0
  268. package/.output/server/chunks/build/{useDcwCards-SaiImIYQ.mjs → useDcwCards-0bAVo6uB.mjs} +20 -23
  269. package/.output/server/chunks/build/useDcwCards-0bAVo6uB.mjs.map +1 -0
  270. package/.output/server/chunks/build/useDcwDetailScope-BNFOlt2v.mjs +184 -0
  271. package/.output/server/chunks/build/useDcwDetailScope-BNFOlt2v.mjs.map +1 -0
  272. package/.output/server/chunks/build/useDcwDetailTemplates-DSH-o0tE.mjs +143 -0
  273. package/.output/server/chunks/build/useDcwDetailTemplates-DSH-o0tE.mjs.map +1 -0
  274. package/.output/server/chunks/build/useDcwFilter-W61BFUcT.mjs +65 -0
  275. package/.output/server/chunks/build/useDcwFilter-W61BFUcT.mjs.map +1 -0
  276. package/.output/server/chunks/build/{useDcwLedger-0ie-0WTc.mjs → useDcwLedger-DsColLdc.mjs} +29 -35
  277. package/.output/server/chunks/build/useDcwLedger-DsColLdc.mjs.map +1 -0
  278. package/.output/server/chunks/build/useDcwLineMutations-Cx4Ir7g3.mjs +133 -0
  279. package/.output/server/chunks/build/useDcwLineMutations-Cx4Ir7g3.mjs.map +1 -0
  280. package/.output/server/chunks/build/useDcwLineRun-DQ0vB08z.mjs +100 -0
  281. package/.output/server/chunks/build/useDcwLineRun-DQ0vB08z.mjs.map +1 -0
  282. package/.output/server/chunks/build/useDcwParamApprovals-CYspRuDk.mjs +119 -0
  283. package/.output/server/chunks/build/useDcwParamApprovals-CYspRuDk.mjs.map +1 -0
  284. package/.output/server/chunks/build/useDcwProducts-CTbm_5S_.mjs +88 -0
  285. package/.output/server/chunks/build/useDcwProducts-CTbm_5S_.mjs.map +1 -0
  286. package/.output/server/chunks/build/useDcwQuery-E0yjZs7G.mjs +93 -0
  287. package/.output/server/chunks/build/useDcwQuery-E0yjZs7G.mjs.map +1 -0
  288. package/.output/server/chunks/build/useDcwQuickActions-BvT5VFOY.mjs +84 -0
  289. package/.output/server/chunks/build/useDcwQuickActions-BvT5VFOY.mjs.map +1 -0
  290. package/.output/server/chunks/build/useDcwRecipes-zngShyk0.mjs +263 -0
  291. package/.output/server/chunks/build/useDcwRecipes-zngShyk0.mjs.map +1 -0
  292. package/.output/server/chunks/build/useDcwStream-82IdjJKk.mjs +455 -0
  293. package/.output/server/chunks/build/useDcwStream-82IdjJKk.mjs.map +1 -0
  294. package/.output/server/chunks/build/useDcwTemplates-CpHrcnvJ.mjs +87 -0
  295. package/.output/server/chunks/build/useDcwTemplates-CpHrcnvJ.mjs.map +1 -0
  296. package/.output/server/chunks/build/useDcwWrites-BlOhljp9.mjs +136 -0
  297. package/.output/server/chunks/build/useDcwWrites-BlOhljp9.mjs.map +1 -0
  298. package/.output/server/chunks/build/useDeviceTwins-DL-VLFeX.mjs +118 -0
  299. package/.output/server/chunks/build/useDeviceTwins-DL-VLFeX.mjs.map +1 -0
  300. package/.output/server/chunks/build/useExpConfirmations-DgwqTb9O.mjs +104 -0
  301. package/.output/server/chunks/build/useExpConfirmations-DgwqTb9O.mjs.map +1 -0
  302. package/.output/server/chunks/build/useLocalTime-C__kwn8h.mjs +52 -0
  303. package/.output/server/chunks/build/useLocalTime-C__kwn8h.mjs.map +1 -0
  304. package/.output/server/chunks/build/useLogsFormat-B-o4MHy7.mjs +30 -33
  305. package/.output/server/chunks/build/useLogsFormat-B-o4MHy7.mjs.map +1 -1
  306. package/.output/server/chunks/build/useLogsManual-BcfanT0s.mjs +80 -0
  307. package/.output/server/chunks/build/useLogsManual-BcfanT0s.mjs.map +1 -0
  308. package/.output/server/chunks/build/useLogsQuery-BGlKVKpV.mjs +136 -0
  309. package/.output/server/chunks/build/useLogsQuery-BGlKVKpV.mjs.map +1 -0
  310. package/.output/server/chunks/build/useLogsScope-BRyy550Y.mjs +75 -0
  311. package/.output/server/chunks/build/useLogsScope-BRyy550Y.mjs.map +1 -0
  312. package/.output/server/chunks/build/useMonitorColumns-vVnt3r5Q.mjs +155 -166
  313. package/.output/server/chunks/build/useMonitorColumns-vVnt3r5Q.mjs.map +1 -1
  314. package/.output/server/chunks/build/useMonitorData-BUey2Xly.mjs +128 -0
  315. package/.output/server/chunks/build/useMonitorData-BUey2Xly.mjs.map +1 -0
  316. package/.output/server/chunks/build/useMonitorFormat-rhs7FlNo.mjs +77 -0
  317. package/.output/server/chunks/build/useMonitorFormat-rhs7FlNo.mjs.map +1 -0
  318. package/.output/server/chunks/build/useMonitorTerminal-Dj4QwRNW.mjs +20 -27
  319. package/.output/server/chunks/build/useMonitorTerminal-Dj4QwRNW.mjs.map +1 -1
  320. package/.output/server/chunks/build/useOperationsFeed-DWfCjP4l.mjs +182 -0
  321. package/.output/server/chunks/build/useOperationsFeed-DWfCjP4l.mjs.map +1 -0
  322. package/.output/server/chunks/build/useOpsLog--yf8erUi.mjs +139 -0
  323. package/.output/server/chunks/build/useOpsLog--yf8erUi.mjs.map +1 -0
  324. package/.output/server/chunks/build/useRecipeDispatchApprovals-CKF2sB9P.mjs +146 -0
  325. package/.output/server/chunks/build/useRecipeDispatchApprovals-CKF2sB9P.mjs.map +1 -0
  326. package/.output/server/chunks/build/useResponsive-BKDMGTHs.mjs +23 -39
  327. package/.output/server/chunks/build/useResponsive-BKDMGTHs.mjs.map +1 -1
  328. package/.output/server/chunks/build/useTeamActions-C08sAVqY.mjs +71 -0
  329. package/.output/server/chunks/build/useTeamActions-C08sAVqY.mjs.map +1 -0
  330. package/.output/server/chunks/build/useTeamAddMemberDialog-fzTmflr8.mjs +78 -0
  331. package/.output/server/chunks/build/useTeamAddMemberDialog-fzTmflr8.mjs.map +1 -0
  332. package/.output/server/chunks/build/useTeamCreateDialog-De63ep-X.mjs +91 -0
  333. package/.output/server/chunks/build/useTeamCreateDialog-De63ep-X.mjs.map +1 -0
  334. package/.output/server/chunks/build/useTeamDeployDialog-CpAtG5Jy.mjs +76 -0
  335. package/.output/server/chunks/build/useTeamDeployDialog-CpAtG5Jy.mjs.map +1 -0
  336. package/.output/server/chunks/build/useTeamDialogState-CFRUQxAf.mjs +31 -38
  337. package/.output/server/chunks/build/useTeamDialogState-CFRUQxAf.mjs.map +1 -1
  338. package/.output/server/chunks/build/useTeamPluginDialog-C1OOe1sL.mjs +99 -0
  339. package/.output/server/chunks/build/useTeamPluginDialog-C1OOe1sL.mjs.map +1 -0
  340. package/.output/server/chunks/build/useTeamsCatalog-DA41SMDu.mjs +124 -0
  341. package/.output/server/chunks/build/useTeamsCatalog-DA41SMDu.mjs.map +1 -0
  342. package/.output/server/chunks/build/useTokenClipboard-CwQpoFeP.mjs +21 -28
  343. package/.output/server/chunks/build/useTokenClipboard-CwQpoFeP.mjs.map +1 -1
  344. package/.output/server/chunks/build/useTokenCreate-XHTQExra.mjs +106 -0
  345. package/.output/server/chunks/build/useTokenCreate-XHTQExra.mjs.map +1 -0
  346. package/.output/server/chunks/build/useTokenRename-Cf1B0cRy.mjs +81 -0
  347. package/.output/server/chunks/build/useTokenRename-Cf1B0cRy.mjs.map +1 -0
  348. package/.output/server/chunks/build/useTokenReveal-C8n1Vt9t.mjs +108 -0
  349. package/.output/server/chunks/build/useTokenReveal-C8n1Vt9t.mjs.map +1 -0
  350. package/.output/server/chunks/build/useTokensList-MMIq24E-.mjs +86 -0
  351. package/.output/server/chunks/build/useTokensList-MMIq24E-.mjs.map +1 -0
  352. package/.output/server/chunks/build/useTownBus-D9SoIsAN.mjs +16 -17
  353. package/.output/server/chunks/build/useTownBus-D9SoIsAN.mjs.map +1 -1
  354. package/.output/server/chunks/build/useWorkbenchAuth-Dyc_czui.mjs +131 -0
  355. package/.output/server/chunks/build/useWorkbenchAuth-Dyc_czui.mjs.map +1 -0
  356. package/.output/server/chunks/build/useWorkbenchWorkspaces-DT33HbBD.mjs +128 -0
  357. package/.output/server/chunks/build/useWorkbenchWorkspaces-DT33HbBD.mjs.map +1 -0
  358. package/.output/server/chunks/build/useWorkshopApi-BkEgGBIM.mjs +118 -0
  359. package/.output/server/chunks/build/useWorkshopApi-BkEgGBIM.mjs.map +1 -0
  360. package/.output/server/chunks/build/useWorkshopWs-BWrVj4jL.mjs +1577 -0
  361. package/.output/server/chunks/build/useWorkshopWs-BWrVj4jL.mjs.map +1 -0
  362. package/.output/server/chunks/build/{useWorkspaceAuth-Dlvj9csD.mjs → useWorkspaceAuth-TahC9EC7.mjs} +4 -16
  363. package/.output/server/chunks/build/useWorkspaceAuth-TahC9EC7.mjs.map +1 -0
  364. package/.output/server/chunks/build/useWorkspaceChannels-BVAHmhN3.mjs +94 -0
  365. package/.output/server/chunks/build/useWorkspaceChannels-BVAHmhN3.mjs.map +1 -0
  366. package/.output/server/chunks/build/useWorkspacePanels-CTwREmq0.mjs +30 -33
  367. package/.output/server/chunks/build/useWorkspacePanels-CTwREmq0.mjs.map +1 -1
  368. package/.output/server/chunks/build/useWorkspaceShell-rQHWNNWJ.mjs +150 -0
  369. package/.output/server/chunks/build/useWorkspaceShell-rQHWNNWJ.mjs.map +1 -0
  370. package/.output/server/chunks/build/users-pVCK50z-.mjs +566 -0
  371. package/.output/server/chunks/build/users-pVCK50z-.mjs.map +1 -0
  372. package/.output/server/chunks/build/workshop-DAgsBgG4.mjs +499 -0
  373. package/.output/server/chunks/build/workshop-DAgsBgG4.mjs.map +1 -0
  374. package/.output/server/chunks/build/workspaces-CmW0cpOt.mjs +111 -121
  375. package/.output/server/chunks/build/workspaces-CmW0cpOt.mjs.map +1 -1
  376. package/.output/server/chunks/routes/api/plugins/_name/_...path_.mjs +4 -1
  377. package/.output/server/chunks/routes/api/plugins/_name/_...path_.mjs.map +1 -1
  378. package/.output/server/chunks/routes/renderer.mjs +1 -1
  379. package/.output/server/chunks/routes/renderer.mjs.map +1 -1
  380. package/.output/server/chunks/virtual/entry.mjs +9357 -10721
  381. package/.output/server/chunks/virtual/entry.mjs.map +1 -1
  382. package/.output/server/chunks/virtual/precomputed.mjs +1 -1
  383. package/.output/server/chunks/virtual/precomputed.mjs.map +1 -1
  384. package/.output/server/package.json +1 -1
  385. package/README-zh.md +2 -2
  386. package/README.md +3 -3
  387. package/app/components/AwLogo.vue +75 -75
  388. package/app/components/aml/AmlDatasetFormModal.vue +279 -279
  389. package/app/components/aml/AmlDatasetTable.vue +319 -319
  390. package/app/components/aml/AmlExperimentsTable.vue +142 -142
  391. package/app/components/aml/AmlInfraBanner.vue +23 -23
  392. package/app/components/aml/AmlJobsTable.vue +248 -248
  393. package/app/components/aml/AmlOverviewBar.vue +62 -62
  394. package/app/components/aml/AmlPageHeader.vue +47 -47
  395. package/app/components/aml/AmlPredictConsole.vue +201 -201
  396. package/app/components/app-header/HitlBell.vue +423 -423
  397. package/app/components/daq/DaqAddNodeModal.vue +209 -209
  398. package/app/components/daq/DaqAlarmBar.vue +46 -46
  399. package/app/components/daq/DaqControlCard.vue +159 -159
  400. package/app/components/daq/DaqInfraBanner.vue +31 -31
  401. package/app/components/daq/DaqLineBanner.vue +47 -47
  402. package/app/components/daq/DaqNodePanel.vue +396 -396
  403. package/app/components/daq/DaqOptPanel.vue +197 -197
  404. package/app/components/daq/DaqTemplateModal.vue +246 -246
  405. package/app/components/dashboard/DashboardGaugeBand.vue +78 -78
  406. package/app/components/dashboard/DashboardHero.vue +209 -209
  407. package/app/components/dashboard/DashboardLineStatePanel.vue +78 -78
  408. package/app/components/dashboard/DashboardNodeStatePanel.vue +46 -46
  409. package/app/components/dashboard/DashboardPipelinePanel.vue +46 -46
  410. package/app/components/dashboard/DashboardTrendPanel.vue +83 -83
  411. package/app/components/dashboard/DashboardWritePanel.vue +52 -52
  412. package/app/components/dcw/DcwCreateLineModal.vue +105 -105
  413. package/app/components/dcw/DcwDeleteLineModal.vue +73 -73
  414. package/app/components/dcw/DcwDetailTemplateModal.vue +238 -238
  415. package/app/components/dcw/DcwLedgerCard.vue +160 -160
  416. package/app/components/dcw/DcwMesArtifacts.vue +140 -140
  417. package/app/components/dcw/DcwProductCreateModal.vue +113 -113
  418. package/app/components/dcw/DcwRecipeDispatchHistoryModal.vue +244 -244
  419. package/app/components/dcw/DcwRecipeEditModal.vue +399 -399
  420. package/app/components/dcw/DcwRecipeHistoryModal.vue +165 -165
  421. package/app/components/dcw/DcwRunDataModal.vue +191 -191
  422. package/app/components/dcw/DcwTemplateModal.vue +227 -227
  423. package/app/components/dcw/DcwWriteHistoryCard.vue +96 -96
  424. package/app/components/dcw/ExpConfirmCard.vue +103 -103
  425. package/app/components/dcw/RecipeDispatchApprovalCard.vue +330 -330
  426. package/app/components/logs/LogsPageHead.vue +71 -71
  427. package/app/components/monitor/MonitorAgentTable.vue +143 -143
  428. package/app/components/monitor/MonitorChannelTable.vue +80 -80
  429. package/app/components/monitor/MonitorLoginGate.vue +24 -24
  430. package/app/components/monitor/MonitorPageHead.vue +92 -92
  431. package/app/components/monitor/MonitorProcessTable.vue +159 -159
  432. package/app/components/ontology/OntologyGraph.vue +356 -356
  433. package/app/components/operations/OperationsFilterCard.vue +164 -164
  434. package/app/components/operations/OperationsPageHead.vue +47 -47
  435. package/app/components/tokens/TokenCreateModal.vue +42 -42
  436. package/app/components/tokens/TokenOnceModal.vue +164 -164
  437. package/app/components/tokens/TokenRenameModal.vue +40 -40
  438. package/app/components/tokens/TokensPageHead.vue +76 -76
  439. package/app/components/workshop/A2aRpcDebugger.vue +237 -237
  440. package/app/components/workshop/AgentInspectorDrawer.vue +424 -424
  441. package/app/components/workshop/AgentLanesView.vue +278 -278
  442. package/app/components/workshop/ArtifactCard.vue +120 -120
  443. package/app/components/workshop/AssetLibrary.vue +452 -452
  444. package/app/components/workshop/ChatMemberPanel.vue +556 -556
  445. package/app/components/workshop/CommandPalette.vue +270 -270
  446. package/app/components/workshop/Composer.vue +540 -540
  447. package/app/components/workshop/DaqTemplateIcon.vue +33 -33
  448. package/app/components/workshop/DeviceTwinPanel.vue +167 -167
  449. package/app/components/workshop/FileSelectorModal.vue +188 -188
  450. package/app/components/workshop/InspectorPanel.vue +301 -301
  451. package/app/components/workshop/PluginSlot.vue +120 -120
  452. package/app/components/workshop/TranscriptTimeline.vue +223 -223
  453. package/app/components/workshop/agents/AgentTemplateEditModal.vue +139 -139
  454. package/app/components/workshop/blocks/ClusterArtifact.vue +61 -61
  455. package/app/components/workshop/blocks/ClusterError.vue +85 -85
  456. package/app/components/workshop/blocks/ClusterLife.vue +87 -87
  457. package/app/components/workshop/blocks/ClusterMember.vue +95 -95
  458. package/app/components/workshop/blocks/ClusterMemory.vue +84 -84
  459. package/app/components/workshop/blocks/ClusterOther.vue +67 -67
  460. package/app/components/workshop/blocks/ClusterStatus.vue +149 -149
  461. package/app/components/workshop/blocks/ClusterTool.vue +176 -176
  462. package/app/components/workshop/blocks/EventBlockAvatar.vue +114 -114
  463. package/app/components/workshop/blocks/EventBlockHead.vue +232 -232
  464. package/app/components/workshop/composer/ComposerToolbar.vue +278 -278
  465. package/app/components/workshop/composer/MentionMenu.vue +135 -135
  466. package/app/components/workshop/composer/ReplyChip.vue +65 -65
  467. package/app/components/workshop/composer/StatusChip.vue +171 -171
  468. package/app/components/workshop/console/Dock.vue +71 -71
  469. package/app/components/workshop/console/LeftPane.vue +84 -84
  470. package/app/components/workshop/device-twin/DeviceTwinCard.vue +265 -265
  471. package/app/components/workshop/device-twin/DeviceTwinDcwSection.vue +203 -203
  472. package/app/components/workshop/lanes/AddMemberModal.vue +270 -270
  473. package/app/components/workshop/lanes/EditMemberModal.vue +106 -106
  474. package/app/components/workshop/lanes/LanesToolbar.vue +97 -97
  475. package/app/components/workshop/session-list/ChannelSettingsModal.vue +3 -3
  476. package/app/components/workshop/session-list/MountChannelModal.vue +124 -124
  477. package/app/components/workshop/session-list/SaveTemplateModal.vue +93 -93
  478. package/app/components/workshop/task-board/Card.vue +172 -172
  479. package/app/components/workshop/task-board/Column.vue +151 -151
  480. package/app/components/workshop/task-board/List.vue +157 -157
  481. package/app/components/workshop/task-board/StatusMenu.vue +88 -88
  482. package/app/components/workshop/teams/TeamAddMemberModal.vue +53 -53
  483. package/app/components/workshop/teams/TeamCreateModal.vue +94 -94
  484. package/app/components/workshop/teams/TeamDeployModal.vue +40 -40
  485. package/app/components/workshop/teams/TeamPluginModal.vue +119 -119
  486. package/app/components/workshop/terminal/OmpTerminalPanel.vue +270 -270
  487. package/app/components/workshop/terminal/TerminalHitlCard.vue +170 -170
  488. package/app/components/workshop/town/TownScene.ts +466 -466
  489. package/app/components/workshop/town/TownView.vue +561 -561
  490. package/app/components/workshop/town/components/AutoModeConfirmModal.vue +94 -94
  491. package/app/components/workshop/town/components/TownAgentBindings.vue +405 -405
  492. package/app/components/workshop/town/components/TownAgentInspector.vue +554 -554
  493. package/app/components/workshop/town/components/TownAlarmList.vue +147 -147
  494. package/app/components/workshop/town/components/TownBoundaryPanel.vue +350 -350
  495. package/app/components/workshop/town/components/TownCalloutLayer.vue +147 -147
  496. package/app/components/workshop/town/components/TownChannelDock.vue +116 -116
  497. package/app/components/workshop/town/components/TownControlDock.vue +405 -405
  498. package/app/components/workshop/town/components/TownDaqNodeInspector.vue +345 -345
  499. package/app/components/workshop/town/components/TownDaqTree.vue +366 -366
  500. package/app/components/workshop/town/components/TownDcwBindSection.vue +473 -473
  501. package/app/components/workshop/town/components/TownDcwNodeInspector.vue +185 -185
  502. package/app/components/workshop/town/components/TownDcwTree.vue +280 -280
  503. package/app/components/workshop/town/components/TownDeviceBindings.vue +394 -394
  504. package/app/components/workshop/town/components/TownDeviceTransform.vue +248 -248
  505. package/app/components/workshop/town/components/TownEventList.vue +120 -120
  506. package/app/components/workshop/town/components/TownHealthBody.vue +100 -100
  507. package/app/components/workshop/town/components/TownKpiStrip.vue +207 -207
  508. package/app/components/workshop/town/components/TownLeftRail.vue +308 -308
  509. package/app/components/workshop/town/components/TownLoadingMask.vue +61 -61
  510. package/app/components/workshop/town/components/TownNavMap.vue +154 -154
  511. package/app/components/workshop/town/components/TownRightRail.vue +543 -543
  512. package/app/components/workshop/town/components/TownStage.vue +281 -281
  513. package/app/components/workshop/town/components/TownStageTop.vue +238 -238
  514. package/app/components/workshop/town/components/TownStatusBar.vue +108 -108
  515. package/app/components/workshop/town/components/TownTopNav.vue +367 -367
  516. package/app/components/workshop/town/components/TownTrendDock.vue +178 -178
  517. package/app/components/workshop/town/scene/town-scene-agents.ts +254 -254
  518. package/app/components/workshop/town/scene/town-scene-behavior.ts +194 -194
  519. package/app/components/workshop/town/scene/town-scene-bubbles.ts +96 -96
  520. package/app/components/workshop/town/scene/town-scene-core.ts +158 -158
  521. package/app/components/workshop/town/scene/town-scene-models.ts +109 -109
  522. package/app/components/workshop/town/scene/town-scene-visuals.ts +279 -279
  523. package/app/components/workshop/town/scene/town-scene3d-agents.ts +308 -308
  524. package/app/components/workshop/town/scene/town-scene3d-blocks.ts +297 -297
  525. package/app/components/workshop/town/scene/town-scene3d-bubbles.ts +281 -281
  526. package/app/components/workshop/town/scene/town-scene3d-camera.ts +282 -282
  527. package/app/components/workshop/town/scene/town-scene3d-devices.ts +433 -433
  528. package/app/components/workshop/town/scene/town-scene3d-editing.ts +490 -490
  529. package/app/components/workshop/town/scene/town-scene3d-events.ts +173 -173
  530. package/app/components/workshop/town/scene/town-scene3d-factory.ts +412 -412
  531. package/app/components/workshop/town/scene/town-scene3d-hud.ts +110 -110
  532. package/app/components/workshop/town/scene/town-scene3d-lifecycle.ts +144 -144
  533. package/app/components/workshop/town/scene/town-scene3d-links.ts +141 -141
  534. package/app/components/workshop/town/scene/town-scene3d-loop.ts +286 -286
  535. package/app/components/workshop/town/scene/town-scene3d-models.ts +154 -154
  536. package/app/components/workshop/town/scene/town-scene3d-nodes.ts +562 -562
  537. package/app/components/workshop/town/scene/town-scene3d-ranges.ts +273 -273
  538. package/app/components/workshop/town/scene/town-scene3d-renderer.ts +320 -320
  539. package/app/components/workshop/town/scene/town-scene3d-selection.ts +257 -257
  540. package/app/components/workshop/town/scene/town-scene3d-types.ts +264 -264
  541. package/app/components/workshop/transcript/TranscriptBlockList.vue +68 -68
  542. package/app/components/workshop/transcript/TranscriptEarlierPager.vue +81 -81
  543. package/app/components/workshop/transcript/TranscriptFilterBar.vue +126 -126
  544. package/app/components/workshop/workbench/CreateWorkspaceModal.vue +36 -36
  545. package/app/components/workshop/workbench/WorkspaceEmpty.vue +56 -56
  546. package/app/composables/useResponsive.ts +88 -88
  547. package/app/composables/workshop/device-twin-types.ts +29 -29
  548. package/app/composables/workshop/event-blocks/attention.ts +58 -58
  549. package/app/composables/workshop/event-blocks/classify.ts +44 -44
  550. package/app/composables/workshop/event-blocks/clusterer.ts +231 -231
  551. package/app/composables/workshop/event-blocks/fold-stream.ts +45 -45
  552. package/app/composables/workshop/event-blocks/markdown.ts +81 -81
  553. package/app/composables/workshop/event-blocks/mentions.ts +49 -49
  554. package/app/composables/workshop/event-blocks/text-utils.ts +100 -100
  555. package/app/composables/workshop/event-blocks/types.ts +40 -40
  556. package/app/composables/workshop/town/town-relay-props.ts +231 -231
  557. package/app/composables/workshop/town/town-view-types.ts +145 -145
  558. package/app/composables/workshop/town/useTownAgentBindings.ts +182 -182
  559. package/app/composables/workshop/town/useTownAgentChat.ts +203 -203
  560. package/app/composables/workshop/town/useTownAlarms.ts +36 -36
  561. package/app/composables/workshop/town/useTownCallouts.ts +174 -174
  562. package/app/composables/workshop/town/useTownChannels.ts +220 -220
  563. package/app/composables/workshop/town/useTownHealth.ts +66 -66
  564. package/app/composables/workshop/town/useTownHudTickers.ts +77 -77
  565. package/app/composables/workshop/town/useTownLayout.ts +277 -277
  566. package/app/composables/workshop/town/useTownNavMap.ts +301 -301
  567. package/app/composables/workshop/town/useTownNodeBindings.ts +345 -345
  568. package/app/composables/workshop/town/useTownPanelDrag.ts +91 -91
  569. package/app/composables/workshop/town/useTownRailData.ts +421 -421
  570. package/app/composables/workshop/town/useTownSceneControl.ts +92 -92
  571. package/app/composables/workshop/town/useTownSceneInput.ts +275 -275
  572. package/app/composables/workshop/town/useTownSceneRuntime.ts +390 -390
  573. package/app/composables/workshop/town/useTownSheets.ts +41 -41
  574. package/app/composables/workshop/town/useTownTrends.ts +93 -93
  575. package/app/composables/workshop/useChannelList.ts +88 -88
  576. package/app/composables/workshop/useChannelTerminals.ts +65 -65
  577. package/app/composables/workshop/useComposerMentions.ts +130 -130
  578. package/app/composables/workshop/useDcwStream.ts +374 -374
  579. package/app/composables/workshop/useDeviceTwinDcwWrite.ts +77 -77
  580. package/app/composables/workshop/useDeviceTwinPanel.ts +56 -56
  581. package/app/composables/workshop/useEscClose.ts +44 -44
  582. package/app/composables/workshop/useEventBlockView.ts +159 -159
  583. package/app/composables/workshop/useEventBlocks.ts +33 -33
  584. package/app/composables/workshop/useHitlAnswer.ts +184 -184
  585. package/app/composables/workshop/useLaneWidths.ts +27 -27
  586. package/app/composables/workshop/useOmpTerminalSession.ts +424 -424
  587. package/app/composables/workshop/usePluginAdmin.ts +152 -152
  588. package/app/composables/workshop/usePluginPanels.ts +72 -72
  589. package/app/composables/workshop/useRuntimeConfigDraft.ts +118 -118
  590. package/app/composables/workshop/useSettingsGroups.ts +243 -243
  591. package/app/composables/workshop/useTaskBoardColumns.ts +47 -47
  592. package/app/composables/workshop/useTerminalRenderer.ts +308 -308
  593. package/app/composables/workshop/useTranscriptEnterStage.ts +48 -48
  594. package/app/composables/workshop/useTranscriptHistory.ts +52 -52
  595. package/app/composables/workshop/useTranscriptScroll.ts +113 -113
  596. package/app/composables/workshop/useVisibleInterval.ts +42 -42
  597. package/app/composables/workshop/useWorkshopWs.ts +265 -265
  598. package/app/config/index.ts +1 -1
  599. package/app/middleware/locale-cookie.global.ts +22 -22
  600. package/app/pages/aml/api.ts +6 -6
  601. package/app/pages/aml/composables/useAmlDatasets.ts +38 -38
  602. package/app/pages/aml/composables/useAmlEntities.ts +57 -57
  603. package/app/pages/aml/composables/useAmlEnv.ts +191 -191
  604. package/app/pages/aml/composables/useAmlExperiments.ts +45 -45
  605. package/app/pages/aml/composables/useAmlFormat.ts +44 -44
  606. package/app/pages/aml/composables/useAmlJobs.ts +131 -131
  607. package/app/pages/aml/composables/useAmlModels.ts +56 -56
  608. package/app/pages/aml/composables/useAmlNotes.ts +47 -47
  609. package/app/pages/aml/composables/useAmlPredict.ts +93 -93
  610. package/app/pages/aml/constants.ts +63 -63
  611. package/app/pages/aml/index.vue +236 -236
  612. package/app/pages/composables/useDashboardCharts.ts +192 -192
  613. package/app/pages/composables/useDashboardData.ts +144 -144
  614. package/app/pages/daq/composables/useDaqAddNode.ts +126 -126
  615. package/app/pages/daq/composables/useDaqDetailBinding.ts +29 -29
  616. package/app/pages/daq/composables/useDaqDetailFrames.ts +42 -42
  617. package/app/pages/daq/composables/useDaqDetailNode.ts +53 -53
  618. package/app/pages/daq/composables/useDaqDetailParams.ts +138 -138
  619. package/app/pages/daq/composables/useDaqFilters.ts +187 -187
  620. package/app/pages/daq/composables/useDaqNodeWindow.ts +86 -86
  621. package/app/pages/daq/composables/useDaqOptimizations.ts +99 -99
  622. package/app/pages/daq/composables/useDaqTemplates.ts +152 -152
  623. package/app/pages/daq/index.vue +260 -260
  624. package/app/pages/dcw/composables/useDcwCards.ts +27 -27
  625. package/app/pages/dcw/composables/useDcwDetailScope.ts +145 -145
  626. package/app/pages/dcw/composables/useDcwDetailTemplates.ts +94 -94
  627. package/app/pages/dcw/composables/useDcwFilter.ts +29 -29
  628. package/app/pages/dcw/composables/useDcwLedger.ts +34 -34
  629. package/app/pages/dcw/composables/useDcwLineMutations.ts +115 -115
  630. package/app/pages/dcw/composables/useDcwLineRun.ts +60 -60
  631. package/app/pages/dcw/composables/useDcwProducts.ts +54 -54
  632. package/app/pages/dcw/composables/useDcwQuery.ts +68 -68
  633. package/app/pages/dcw/composables/useDcwQuickActions.ts +47 -47
  634. package/app/pages/dcw/composables/useDcwRecipes.ts +256 -256
  635. package/app/pages/dcw/composables/useDcwTemplates.ts +50 -50
  636. package/app/pages/dcw/index.vue +195 -195
  637. package/app/pages/dcw/types.ts +9 -9
  638. package/app/pages/index.vue +126 -126
  639. package/app/pages/logs/composables/useLogsFormat.ts +43 -43
  640. package/app/pages/logs/composables/useLogsScope.ts +39 -39
  641. package/app/pages/monitor/types.ts +61 -61
  642. package/app/pages/operations.vue +61 -61
  643. package/app/pages/permissions/index.vue +369 -369
  644. package/app/pages/tokens/composables/useTokenClipboard.ts +33 -33
  645. package/app/pages/tokens/composables/useTokenCreate.ts +93 -93
  646. package/app/pages/tokens/composables/useTokenRename.ts +54 -54
  647. package/app/pages/tokens/composables/useTokenReveal.ts +84 -84
  648. package/app/pages/tokens/composables/useTokensList.ts +60 -60
  649. package/app/pages/tokens.vue +111 -111
  650. package/app/pages/tools/index.vue +98 -98
  651. package/app/pages/workshop/agents.vue +130 -130
  652. package/app/pages/workshop/composables/useAgentHarnessOptions.ts +59 -59
  653. package/app/pages/workshop/composables/useAgentTemplateActions.ts +42 -42
  654. package/app/pages/workshop/composables/useAgentTemplateDialogState.ts +24 -24
  655. package/app/pages/workshop/composables/useAgentTemplateForm.ts +88 -88
  656. package/app/pages/workshop/composables/useAgentTemplatesCatalog.ts +92 -92
  657. package/app/pages/workshop/composables/useTeamActions.ts +44 -44
  658. package/app/pages/workshop/composables/useTeamAddMemberDialog.ts +49 -49
  659. package/app/pages/workshop/composables/useTeamCreateDialog.ts +67 -67
  660. package/app/pages/workshop/composables/useTeamDeployDialog.ts +49 -49
  661. package/app/pages/workshop/composables/useTeamDialogState.ts +46 -46
  662. package/app/pages/workshop/composables/useTeamPluginDialog.ts +72 -72
  663. package/app/pages/workshop/composables/useTeamsCatalog.ts +100 -100
  664. package/app/pages/workshop/composables/useWorkbenchWorkspaces.ts +123 -123
  665. package/app/pages/workshop/composables/useWorkspaceAuth.ts +31 -31
  666. package/app/pages/workshop/composables/useWorkspaceChannels.ts +62 -62
  667. package/app/pages/workshop/composables/useWorkspaceShell.ts +136 -136
  668. package/app/pages/workshop/schedules.vue +553 -553
  669. package/app/pages/workshop/w/[wsId].vue +221 -221
  670. package/app/plugins/aw-plugins.client.ts +213 -213
  671. package/app/plugins/esc-close.client.ts +31 -31
  672. package/app/stores/workshop/hitl.ts +183 -183
  673. package/app/stores/workshop/narrow-fetch.ts +23 -23
  674. package/app/utils/api-error.ts +75 -75
  675. package/app/utils/builtin-catalog.ts +104 -104
  676. package/app/utils/chart-trend.ts +97 -97
  677. package/app/utils/dcw-driver-badge.ts +16 -16
  678. package/app/utils/dcw-recipe-form.ts +26 -26
  679. package/cli/commands/tui.mjs +28 -28
  680. package/cli/commands/update.mjs +124 -124
  681. package/cli/core/child-lifecycle.mjs +136 -136
  682. package/cli/core/meta.mjs +38 -38
  683. package/cli/core/post-build.mjs +96 -96
  684. package/config.yml +1 -1
  685. package/docs/cli.en.md +2 -2
  686. package/docs/cli.md +2 -2
  687. package/docs/mcp.en.md +27 -27
  688. package/docs/multi-harness-architecture.md +248 -248
  689. package/docs/plugins.en.md +1 -1
  690. package/docs/plugins.md +1 -1
  691. package/docs/sdk.en.md +1 -1
  692. package/docs/sdk.md +1 -1
  693. package/docs/tui.md +43 -43
  694. package/i18n/dicts/_en.json +1551 -1551
  695. package/i18n/dicts/_en2.json +300 -300
  696. package/i18n/dicts/_en4.json +114 -114
  697. package/i18n/dicts/agentLanesView.json +61 -61
  698. package/i18n/dicts/appHeader.json +17 -17
  699. package/i18n/dicts/channelSessionList.json +51 -51
  700. package/i18n/dicts/chat.json +79 -79
  701. package/i18n/dicts/clusterTool.json +4 -4
  702. package/i18n/dicts/composer.json +38 -38
  703. package/i18n/dicts/ctpl.json +37 -37
  704. package/i18n/dicts/dcwDetail.json +219 -219
  705. package/i18n/dicts/lineOps.json +14 -14
  706. package/i18n/dicts/multiChannelView.json +13 -13
  707. package/i18n/dicts/notifications.json +13 -13
  708. package/i18n/dicts/taskInspectorDrawer.json +25 -25
  709. package/i18n/dicts/teamPlugins.json +10 -10
  710. package/i18n/dicts/townView.json +209 -209
  711. package/mcp/discovery.mjs +227 -227
  712. package/package.json +1 -1
  713. package/public/favicon.svg +14 -14
  714. package/public/robots.txt +3 -3
  715. package/scripts/_audit/audit-harness-adapters.md +664 -664
  716. package/scripts/_audit/aw-mcp-live-e2e.mjs +293 -293
  717. package/scripts/_audit/bump-version.mjs +51 -51
  718. package/scripts/_audit/detached-instance.mjs +112 -112
  719. package/scripts/_audit/detached-start.mjs +103 -103
  720. package/scripts/_audit/eda-ui-fix-acceptance.mjs +212 -212
  721. package/scripts/_audit/guard-upstream-liveness.mjs +104 -104
  722. package/scripts/_audit/http-api-authz-audit.md +657 -657
  723. package/scripts/_audit/kb-team-mock-e2e.mjs +146 -146
  724. package/scripts/_audit/kb-team-omp-e2e.mjs +229 -229
  725. package/scripts/_audit/run.mjs +21 -21
  726. package/scripts/_audit/runtime-audit.md +716 -716
  727. package/scripts/_audit/skills-guided-e2e.mjs +316 -316
  728. package/scripts/_audit/stability-soak.mjs +252 -252
  729. package/scripts/_audit/stubs/nuxt-imports.mjs +67 -67
  730. package/scripts/_audit/ts-register-hook.mjs +12 -12
  731. package/scripts/_audit/ts-resolve-hook.mjs +96 -96
  732. package/scripts/_aw-packaged-start.cjs +22 -22
  733. package/scripts/_aw0746-stage12.mjs +94 -94
  734. package/scripts/_aw0746-stage34.mjs +136 -136
  735. package/scripts/_aw0746-stage6b-train-sweep.mjs +145 -145
  736. package/scripts/_aw0746-stage6c-jobsmoke.mjs +69 -69
  737. package/scripts/_dbg-configroot-audit.mjs +86 -86
  738. package/scripts/_dbg-daq-intervals-func.mjs +115 -115
  739. package/scripts/_dbg-perms-e2e.mjs +142 -142
  740. package/scripts/_dbg-protocol-matrix.mjs +462 -462
  741. package/scripts/_dbg-render-regression.mjs +193 -193
  742. package/scripts/_dbg-schedule-e2e.mjs +262 -262
  743. package/scripts/_e2e-ui-functional.mjs +371 -371
  744. package/scripts/_i18n-en-cjk-scan.mjs +28 -28
  745. package/scripts/_i18n-en-verify.mjs +107 -107
  746. package/scripts/_i18n-extra-checks.mjs +53 -53
  747. package/scripts/_i18n-scan-hardcoded.mjs +180 -180
  748. package/scripts/_lib-aml-python-run.mjs +17 -17
  749. package/scripts/_lint-reflow.mjs +105 -105
  750. package/scripts/_loop-biax-campaign.mjs +130 -130
  751. package/scripts/_plc-sim-detached.cjs +22 -22
  752. package/scripts/_probe-daq-omp-task.mjs +100 -100
  753. package/scripts/_probe-daq-scope-default.mjs +123 -123
  754. package/scripts/_probe-model-channel-link.cjs +25 -25
  755. package/scripts/_probe-recipe-switch.mjs +92 -92
  756. package/scripts/_provision-injection-line.mjs +39 -39
  757. package/scripts/_run-matrix.ps1 +53 -53
  758. package/scripts/_sweep-button-contrast.mjs +87 -87
  759. package/scripts/acceptance-aml-hybrid-e2e.ts +396 -396
  760. package/scripts/acceptance-aml-hybrid-live.mjs +93 -93
  761. package/scripts/acceptance-aml-model-identity.ts +137 -137
  762. package/scripts/agent-daq-isolation-e2e.mjs +91 -91
  763. package/scripts/api-contract-smoke.mjs +126 -126
  764. package/scripts/ask-hitl-e2e.mjs +96 -96
  765. package/scripts/aw-expose.mjs +159 -159
  766. package/scripts/channel-interaction-smoke.mjs +80 -80
  767. package/scripts/data-studio-ui-e2e.mjs +163 -163
  768. package/scripts/demo-group-chat-all-real.ts +279 -279
  769. package/scripts/demo-group-chat-omp-cases.ts +210 -210
  770. package/scripts/demo-group-chat-omp.ts +184 -184
  771. package/scripts/demo-group-chat-order.ts +197 -197
  772. package/scripts/dev-modbus-simulator.mjs +55 -55
  773. package/scripts/docs-shots.mjs +36 -36
  774. package/scripts/e2e-agentteam-chat.mjs +473 -473
  775. package/scripts/e2e-agentteam-real-triage.mjs +421 -421
  776. package/scripts/e2e-aml-decoupled.mjs +162 -162
  777. package/scripts/e2e-aw-tui-global.mjs +277 -277
  778. package/scripts/e2e-closedloop/cleanup.mjs +27 -27
  779. package/scripts/e2e-closedloop/lib.mjs +109 -109
  780. package/scripts/e2e-closedloop/main.mjs +59 -59
  781. package/scripts/e2e-closedloop/scenarios-accounts.mjs +210 -210
  782. package/scripts/e2e-closedloop/scenarios-authz.mjs +196 -196
  783. package/scripts/e2e-closedloop/scenarios-daq-dcw.mjs +222 -222
  784. package/scripts/e2e-closedloop/scenarios-plugins.mjs +169 -169
  785. package/scripts/e2e-closedloop/state.mjs +10 -10
  786. package/scripts/e2e-config-groups.mjs +238 -238
  787. package/scripts/e2e-crash-cycle.mjs +108 -108
  788. package/scripts/e2e-full-closedloop.mjs +16 -16
  789. package/scripts/e2e-hil-multi-user.mjs +307 -307
  790. package/scripts/e2e-hil-restart.mjs +339 -339
  791. package/scripts/e2e-idd-results-ui.mjs +175 -0
  792. package/scripts/e2e-idd-results.mjs +48 -16
  793. package/scripts/e2e-injection-recipe-closedloop.mjs +203 -203
  794. package/scripts/e2e-line-governance.mjs +352 -352
  795. package/scripts/e2e-ontology.mjs +393 -393
  796. package/scripts/e2e-plc-plugin-closedloop.mjs +549 -549
  797. package/scripts/e2e-timezone-settings.mjs +57 -57
  798. package/scripts/full-stack-shots.mjs +145 -145
  799. package/scripts/full-tool-injection-harness-e2e.mjs +214 -214
  800. package/scripts/hitl-reject-e2e.mjs +131 -131
  801. package/scripts/line-log-smoke.mjs +260 -260
  802. package/scripts/live-aml-mockomp.mjs +304 -304
  803. package/scripts/live-aml-optloop-resume.mjs +322 -322
  804. package/scripts/live-aml-optloop.mjs +588 -588
  805. package/scripts/live-aml-stage9.mjs +169 -169
  806. package/scripts/live-aml-two-goals.mjs +315 -315
  807. package/scripts/live-optloop-two-modes.mjs +857 -857
  808. package/scripts/mes-agent-integration-e2e.mjs +361 -361
  809. package/scripts/ops-plugins-e2e.mjs +85 -85
  810. package/scripts/proof-omp-real.ts +189 -189
  811. package/scripts/scenario-suite-setup.mjs +337 -337
  812. package/scripts/scenario-suite-stability.mjs +144 -144
  813. package/scripts/smoke-optimization-verify.ts +72 -72
  814. package/scripts/team-coordination-e2e.mjs +96 -96
  815. package/scripts/test-agentteam-task-chat-flow.ts +420 -420
  816. package/scripts/test-agentteam-workflow.ts +472 -472
  817. package/scripts/test-aw-skills.mjs +102 -102
  818. package/scripts/test-cli-exit.mjs +343 -343
  819. package/scripts/test-daq-frame-race.mjs +358 -358
  820. package/scripts/test-data-root.mjs +208 -208
  821. package/scripts/test-events-index.mjs +176 -176
  822. package/scripts/test-group-chat-hardening.ts +265 -265
  823. package/scripts/test-group-chat-unit/lib.ts +186 -186
  824. package/scripts/test-group-chat-unit/main.ts +45 -45
  825. package/scripts/test-group-chat-unit/section-a-migration.ts +75 -75
  826. package/scripts/test-group-chat-unit/section-b-permission-matrix.ts +88 -88
  827. package/scripts/test-group-chat-unit/section-c-member-lifecycle.ts +64 -64
  828. package/scripts/test-group-chat-unit/section-d-mention-resolution.ts +36 -36
  829. package/scripts/test-group-chat-unit/section-e-chat-facts.ts +97 -97
  830. package/scripts/test-group-chat-unit/section-f-user-notifications.ts +52 -52
  831. package/scripts/test-group-chat-unit/section-g-member-projection.ts +44 -44
  832. package/scripts/test-group-chat-unit/section-h-outbox-consistency.ts +30 -30
  833. package/scripts/test-group-chat-unit/section-i-read-idempotency.ts +24 -24
  834. package/scripts/test-group-chat-unit/section-j-permission-scope.ts +150 -150
  835. package/scripts/test-group-chat-unit.ts +35 -35
  836. package/scripts/test-hitl-decision.ts +526 -526
  837. package/scripts/test-hitl-legacy-channel-auth.ts +143 -143
  838. package/scripts/test-hitl-registry.ts +112 -112
  839. package/scripts/test-log-flooding.mjs +160 -160
  840. package/scripts/test-lru.mjs +101 -101
  841. package/scripts/test-memory-month-query.mjs +70 -70
  842. package/scripts/test-plugin-hardening.mjs +90 -90
  843. package/scripts/test-plugin-lifecycle.mjs +173 -173
  844. package/scripts/test-rollback-index.mjs +137 -137
  845. package/scripts/test-schedule-runtime.ts +309 -309
  846. package/scripts/test-scheduler-loop/scenarios-supervise.ts +25 -25
  847. package/scripts/test-sdk-surface.mjs +158 -158
  848. package/scripts/test-serial-bridge.mjs +418 -418
  849. package/scripts/test-tui-commands.mjs +148 -148
  850. package/scripts/test-tui-reducers.mjs +72 -72
  851. package/scripts/three-system-e2e/lib.mjs +79 -79
  852. package/scripts/three-system-e2e/main.mjs +40 -40
  853. package/scripts/three-system-e2e/phases/phase-0-user-token.mjs +42 -42
  854. package/scripts/three-system-e2e/phases/phase-0a2-line-autoselect.mjs +35 -35
  855. package/scripts/three-system-e2e/phases/phase-0b-fixture-grants.mjs +39 -39
  856. package/scripts/three-system-e2e/phases/phase-0c-plugin-outbound-auth.mjs +95 -95
  857. package/scripts/three-system-e2e/phases/stage-1-health.mjs +47 -47
  858. package/scripts/three-system-e2e/phases/stage-2-5-team-plugins.mjs +84 -84
  859. package/scripts/three-system-e2e/phases/stage-2-teams-tools-hitl.mjs +184 -184
  860. package/scripts/three-system-e2e/phases/stage-3-diag.mjs +73 -73
  861. package/scripts/three-system-e2e/phases/stage-4-plugin-toggle.mjs +53 -53
  862. package/scripts/three-system-e2e/state.mjs +87 -87
  863. package/scripts/three-system-e2e.mjs +40 -40
  864. package/scripts/tool-face-batch-identity-e2e.mjs +222 -222
  865. package/scripts/tsconfig.json +14 -14
  866. package/scripts/tui-smoke.mjs +100 -100
  867. package/scripts/typecheck.mjs +75 -75
  868. package/scripts/ui/admin-shots.mjs +46 -46
  869. package/scripts/ui/bump-microfont.mjs +39 -39
  870. package/scripts/ui/linkcheck2.mjs +37 -37
  871. package/scripts/ui/live-render-check.mjs +72 -72
  872. package/scripts/ui/md-lint.mjs +80 -80
  873. package/scripts/ui/perf-audit.mjs +132 -132
  874. package/scripts/ui/readme-assets.mjs +30 -30
  875. package/scripts/ui/readme-shots.mjs +42 -42
  876. package/scripts/ui/record-demo.mjs +557 -557
  877. package/scripts/ui/record.mjs +225 -225
  878. package/scripts/ui/seed-admin.mjs +68 -68
  879. package/scripts/ui/seed-demo.mjs +83 -83
  880. package/scripts/ui/seed-industrial-demo.mjs +171 -171
  881. package/scripts/ui/shot-hero.mjs +25 -25
  882. package/scripts/ui/shots.mjs +75 -75
  883. package/scripts/ui/sim-ui-shot.mjs +16 -16
  884. package/scripts/ui/smoke-refactor.mjs +258 -258
  885. package/scripts/ui/verify-nav.mjs +51 -51
  886. package/scripts/ui/verify-responsive.mjs +285 -285
  887. package/sdk/client.d.mts +110 -110
  888. package/sdk/examples/line-sentinel/index.mjs +105 -105
  889. package/sdk/examples/ops-notifier/index.mjs +34 -34
  890. package/sdk/examples/sample-insight/index.mjs +39 -39
  891. package/server/api/plugins/[name]/[...path].ts +5 -1
  892. package/server/api/plugins/client/[name].get.ts +18 -18
  893. package/server/api/plugins/i18n.get.ts +12 -12
  894. package/server/api/plugins/manifest.get.ts +10 -10
  895. package/server/api/system/backup/list.get.ts +32 -32
  896. package/server/api/system/backup/run.post.ts +21 -21
  897. package/server/api/system/config-groups/[id].delete.ts +21 -21
  898. package/server/api/system/config-groups/[id].patch.ts +26 -26
  899. package/server/api/system/config-groups/index.get.ts +21 -21
  900. package/server/api/system/config-groups/index.post.ts +33 -33
  901. package/server/api/system/timezone.get.ts +20 -20
  902. package/server/api/users/tokens/[id]/token.get.ts +11 -11
  903. package/server/api/workshop/[...path].ts +13 -13
  904. package/server/api/workshop/agent-tools/approvals/index.get.ts +43 -43
  905. package/server/api/workshop/agent-tools/bindings/[id].delete.ts +26 -26
  906. package/server/api/workshop/agent-tools/bindings/grant.post.ts +45 -45
  907. package/server/api/workshop/agent-tools/bindings/index.get.ts +41 -41
  908. package/server/api/workshop/agent-tools/bindings/revoke.post.ts +42 -42
  909. package/server/api/workshop/aml/datasets/[id]/preview.get.ts +68 -68
  910. package/server/api/workshop/aml/datasets/[id].delete.ts +39 -39
  911. package/server/api/workshop/aml/datasets/[id].get.ts +53 -53
  912. package/server/api/workshop/aml/datasets/[id].patch.ts +30 -30
  913. package/server/api/workshop/aml/datasets/index.get.ts +20 -20
  914. package/server/api/workshop/aml/datasets/index.post.ts +27 -27
  915. package/server/api/workshop/aml/entities/index.get.ts +13 -13
  916. package/server/api/workshop/aml/entities/prune.post.ts +28 -28
  917. package/server/api/workshop/aml/env/index.get.ts +13 -13
  918. package/server/api/workshop/aml/env/recheck.post.ts +14 -14
  919. package/server/api/workshop/aml/env/uv.post.ts +21 -21
  920. package/server/api/workshop/aml/env/venv.post.ts +24 -24
  921. package/server/api/workshop/aml/experiments/index.get.ts +35 -35
  922. package/server/api/workshop/aml/index.get.ts +37 -37
  923. package/server/api/workshop/aml/jobs/[id]/cancel.post.ts +21 -21
  924. package/server/api/workshop/aml/jobs/[id]/logs.get.ts +23 -23
  925. package/server/api/workshop/aml/jobs/[id]/retry.post.ts +20 -20
  926. package/server/api/workshop/aml/jobs/[id].delete.ts +44 -44
  927. package/server/api/workshop/aml/jobs/[id].get.ts +23 -23
  928. package/server/api/workshop/aml/jobs/index.get.ts +26 -26
  929. package/server/api/workshop/aml/models/[id]/predict.post.ts +24 -24
  930. package/server/api/workshop/aml/models/[id]/promote.post.ts +30 -30
  931. package/server/api/workshop/aml/models/index.get.ts +48 -48
  932. package/server/api/workshop/aml/training-plans/[id]/train.post.ts +18 -18
  933. package/server/api/workshop/aml/training-plans/[id].delete.ts +18 -18
  934. package/server/api/workshop/aml/training-plans/[id].patch.ts +30 -30
  935. package/server/api/workshop/aml/training-plans/index.get.ts +9 -9
  936. package/server/api/workshop/aml/training-plans/index.post.ts +43 -43
  937. package/server/api/workshop/approvals/[id]/decide.post.ts +30 -30
  938. package/server/api/workshop/approvals/index.get.ts +22 -22
  939. package/server/api/workshop/audit.get.ts +43 -43
  940. package/server/api/workshop/channels/[id]/chat/messages/[messageId]/read.post.ts +22 -22
  941. package/server/api/workshop/channels/[id]/chat/messages/index.get.ts +29 -29
  942. package/server/api/workshop/channels/[id]/chat/messages/index.post.ts +51 -51
  943. package/server/api/workshop/channels/[id]/chat/permissions.get.ts +35 -35
  944. package/server/api/workshop/channels/[id]/index.patch.ts +64 -64
  945. package/server/api/workshop/channels/[id]/members/[userId]/approve.post.ts +20 -20
  946. package/server/api/workshop/channels/[id]/members/[userId].delete.ts +21 -21
  947. package/server/api/workshop/channels/[id]/members/index.get.ts +23 -23
  948. package/server/api/workshop/channels/[id]/members/leave.post.ts +20 -20
  949. package/server/api/workshop/channels/[id]/twin-profile.get.ts +45 -45
  950. package/server/api/workshop/channels/[id]/twin-profile.patch.ts +72 -72
  951. package/server/api/workshop/daq/[id]/test.post.ts +1 -1
  952. package/server/api/workshop/daq/alarms.get.ts +16 -16
  953. package/server/api/workshop/dcw/[id]/write.post.ts +4 -4
  954. package/server/api/workshop/dcw/[id].delete.ts +41 -41
  955. package/server/api/workshop/dcw/[id].patch.ts +40 -40
  956. package/server/api/workshop/dcw/mes-test-read.post.ts +24 -24
  957. package/server/api/workshop/dcw/params/[id]/read.post.ts +17 -17
  958. package/server/api/workshop/dcw/params/[id]/write.post.ts +21 -21
  959. package/server/api/workshop/dcw/params/[id].delete.ts +19 -19
  960. package/server/api/workshop/dcw/params/[id].patch.ts +23 -23
  961. package/server/api/workshop/dcw/params/index.get.ts +27 -27
  962. package/server/api/workshop/dcw/params/index.post.ts +25 -25
  963. package/server/api/workshop/dcw/products/[id].delete.ts +16 -16
  964. package/server/api/workshop/dcw/products/[id].patch.ts +17 -17
  965. package/server/api/workshop/dcw/recipes/[id]/index.patch.ts +22 -22
  966. package/server/api/workshop/dcw/recipes/[id]/versions.get.ts +14 -14
  967. package/server/api/workshop/dcw/recipes/[id].delete.ts +25 -25
  968. package/server/api/workshop/dcw/recipes/index.get.ts +12 -12
  969. package/server/api/workshop/dcw/runs/[id]/close.post.ts +15 -15
  970. package/server/api/workshop/dcw/templates/[key].delete.ts +14 -14
  971. package/server/api/workshop/dcw/templates/[key].patch.ts +16 -16
  972. package/server/api/workshop/dcw/templates/index.post.ts +15 -15
  973. package/server/api/workshop/dcw/test-driver.post.ts +16 -16
  974. package/server/api/workshop/device-twins/[id].delete.ts +25 -25
  975. package/server/api/workshop/eda/runs/[id]/labels.patch.ts +25 -25
  976. package/server/api/workshop/exp/confirmations/[id]/decide.post.ts +41 -41
  977. package/server/api/workshop/exp/confirmations/index.get.ts +25 -25
  978. package/server/api/workshop/harnesses/[id]/providers.get.ts +16 -16
  979. package/server/api/workshop/hitl/respond.post.ts +94 -94
  980. package/server/api/workshop/notifications/index.get.ts +60 -60
  981. package/server/api/workshop/notifications/read.post.ts +31 -31
  982. package/server/api/workshop/ontology/drafts/[draftId]/subgraph.ts +24 -24
  983. package/server/api/workshop/plugins/[name]/disable.post.ts +21 -21
  984. package/server/api/workshop/plugins/[name]/enable.post.ts +21 -21
  985. package/server/api/workshop/plugins/[name]/index.get.ts +14 -14
  986. package/server/api/workshop/schedules/[id]/run.post.ts +15 -15
  987. package/server/api/workshop/schedules/[id]/runs.get.ts +15 -15
  988. package/server/api/workshop/schedules/[id].delete.ts +14 -14
  989. package/server/api/workshop/schedules/[id].get.ts +13 -13
  990. package/server/api/workshop/schedules/[id].patch.ts +29 -29
  991. package/server/api/workshop/schedules/index.get.ts +12 -12
  992. package/server/api/workshop/schedules/index.post.ts +32 -32
  993. package/server/api/workshop/tasks/[id]/reassign.post.ts +32 -32
  994. package/server/api/workshop/tasks/[id]/update.post.ts +35 -35
  995. package/server/api/workshop/teams/[id]/plugins/index.get.ts +36 -36
  996. package/server/api/workshop/teams/[id]/plugins/index.put.ts +42 -42
  997. package/server/api/workshop/ws/audience.ts +56 -56
  998. package/server/api/workshop/ws/db-buffer.ts +68 -68
  999. package/server/api/workshop/ws/event-mapping.ts +47 -47
  1000. package/server/api/workshop/ws/handlers.ts +132 -132
  1001. package/server/api/workshop/ws/hub.ts +133 -133
  1002. package/server/api/workshop/ws/index.ts +23 -23
  1003. package/server/api/workshop/ws/notification-uplink.ts +77 -77
  1004. package/server/api/workshop/ws/shared.ts +94 -94
  1005. package/server/api/workshop/ws/streams.ts +146 -146
  1006. package/server/middleware/00-security-headers.ts +38 -38
  1007. package/server/middleware/01-rate-guard.ts +101 -101
  1008. package/server/plugins/aml-twin-worker.ts +32 -32
  1009. package/server/plugins/dev-stability-guard.ts +42 -42
  1010. package/server/plugins-builtin/diag-bridge/client.mjs +32 -12
  1011. package/server/plugins-builtin/diag-bridge/host/constants.mjs +25 -25
  1012. package/server/plugins-builtin/diag-bridge/host/exports.mjs +104 -104
  1013. package/server/plugins-builtin/diag-bridge/host/helpers.mjs +39 -9
  1014. package/server/plugins-builtin/diag-bridge/host/index.mjs +15 -15
  1015. package/server/plugins-builtin/diag-bridge/host/intents.mjs +62 -62
  1016. package/server/plugins-builtin/diag-bridge/host/plugin.mjs +60 -26
  1017. package/server/plugins-builtin/diag-bridge/host/snapshot.mjs +93 -93
  1018. package/server/plugins-builtin/diag-bridge/index.mjs +9 -9
  1019. package/server/plugins-builtin/serial-bridge/client.mjs +211 -211
  1020. package/server/plugins-builtin/serial-bridge/drivers.mjs +409 -409
  1021. package/server/plugins-builtin/serial-bridge/i18n.json +62 -62
  1022. package/server/plugins-builtin/serial-bridge/index.mjs +247 -247
  1023. package/server/plugins-builtin/serial-bridge/lib.mjs +208 -208
  1024. package/server/plugins-builtin/serial-bridge/rtu.mjs +168 -168
  1025. package/server/services/system-config/contracts.ts +29 -29
  1026. package/server/services/system-config/dispose.ts +19 -19
  1027. package/server/services/system-config/facade.ts +26 -26
  1028. package/server/services/system-config/groups.ts +108 -108
  1029. package/server/services/system-config/index.ts +21 -21
  1030. package/server/services/system-config/init.ts +26 -26
  1031. package/server/services/system-config/mutate.ts +103 -103
  1032. package/server/services/system-config/plugins.ts +104 -104
  1033. package/server/services/system-config/snapshot.ts +59 -59
  1034. package/server/services/system-config/state.ts +79 -79
  1035. package/server/services/system-config/types.ts +58 -58
  1036. package/server/services/workshop/agents/adapters/omp-rpc-client/api.ts +111 -111
  1037. package/server/services/workshop/agents/adapters/omp-rpc-client/contracts.ts +22 -22
  1038. package/server/services/workshop/agents/adapters/omp-rpc-client/facade.ts +7 -7
  1039. package/server/services/workshop/agents/adapters/omp-rpc-client/frames.ts +0 -18
  1040. package/server/services/workshop/agents/adapters/omp-rpc-client/helpers.ts +38 -38
  1041. package/server/services/workshop/agents/adapters/omp-rpc-client/index.ts +25 -25
  1042. package/server/services/workshop/agents/adapters/omp-rpc-client/start.ts +70 -70
  1043. package/server/services/workshop/agents/adapters/omp-rpc-client/state.ts +65 -65
  1044. package/server/services/workshop/agents/adapters/omp-rpc-client/stdout.ts +92 -92
  1045. package/server/services/workshop/agents/adapters/omp-rpc-client/usage.ts +47 -47
  1046. package/server/services/workshop/agents/agent-badge.ts +38 -38
  1047. package/server/services/workshop/agents/binding-authz.ts +60 -60
  1048. package/server/services/workshop/agents/binding-mode.ts +51 -51
  1049. package/server/services/workshop/agents/codex-agent/client.ts +170 -170
  1050. package/server/services/workshop/agents/codex-agent/core.ts +119 -119
  1051. package/server/services/workshop/agents/codex-agent/facade.ts +8 -8
  1052. package/server/services/workshop/agents/codex-agent/helpers.ts +13 -13
  1053. package/server/services/workshop/agents/codex-agent/hitl.ts +138 -138
  1054. package/server/services/workshop/agents/codex-agent/index.ts +14 -14
  1055. package/server/services/workshop/agents/codex-agent/turn.ts +367 -367
  1056. package/server/services/workshop/agents/codex-agent/types.ts +42 -42
  1057. package/server/services/workshop/agents/harness-process.ts +3 -3
  1058. package/server/services/workshop/agents/harness-terminal/api.ts +197 -197
  1059. package/server/services/workshop/agents/harness-terminal/index.ts +17 -17
  1060. package/server/services/workshop/agents/harness-terminal/io.ts +120 -120
  1061. package/server/services/workshop/agents/harness-terminal/park.ts +55 -55
  1062. package/server/services/workshop/agents/harness-terminal/sanitize.ts +98 -98
  1063. package/server/services/workshop/agents/harness-terminal/session.ts +124 -124
  1064. package/server/services/workshop/agents/harness-terminal/shared.ts +74 -74
  1065. package/server/services/workshop/agents/hitl-capabilities.ts +312 -312
  1066. package/server/services/workshop/agents/hitl-decision/answers.ts +32 -32
  1067. package/server/services/workshop/agents/hitl-decision/decide.ts +268 -268
  1068. package/server/services/workshop/agents/hitl-decision/payload.ts +45 -45
  1069. package/server/services/workshop/agents/hitl-decision/shared.ts +108 -108
  1070. package/server/services/workshop/agents/hitl-decision/visibility.ts +94 -94
  1071. package/server/services/workshop/agents/host-tool-bridge/tools/progress.ts +84 -84
  1072. package/server/services/workshop/agents/host-tool-bridge/tools/team-delegation.ts +104 -104
  1073. package/server/services/workshop/agents/host-tool-bridge/tools/team.ts +70 -70
  1074. package/server/services/workshop/agents/industrial/aml-activity.ts +131 -131
  1075. package/server/services/workshop/agents/industrial/audit-query.ts +66 -66
  1076. package/server/services/workshop/agents/industrial/daq-tools.ts +352 -352
  1077. package/server/services/workshop/agents/industrial/exp-tools.ts +104 -104
  1078. package/server/services/workshop/agents/industrial/ops-tools.ts +16 -54
  1079. package/server/services/workshop/agents/industrial/param-tools.ts +69 -69
  1080. package/server/services/workshop/agents/industrial/recipe-gate.ts +6 -19
  1081. package/server/services/workshop/agents/industrial/recipe-propose-tools.ts +1 -1
  1082. package/server/services/workshop/agents/node-bindings.repo.ts +207 -207
  1083. package/server/services/workshop/agents/node-delegation.ts +159 -159
  1084. package/server/services/workshop/agents/omp-agent/core.ts +146 -146
  1085. package/server/services/workshop/agents/omp-agent/facade.ts +8 -8
  1086. package/server/services/workshop/agents/omp-agent/helpers.ts +37 -37
  1087. package/server/services/workshop/agents/omp-agent/index.ts +16 -16
  1088. package/server/services/workshop/agents/omp-agent/tools-steer.ts +1 -18
  1089. package/server/services/workshop/agents/omp-agent/types.ts +45 -45
  1090. package/server/services/workshop/agents/opencode-agent/core.ts +77 -77
  1091. package/server/services/workshop/agents/opencode-agent/facade.ts +8 -8
  1092. package/server/services/workshop/agents/opencode-agent/helpers.ts +29 -29
  1093. package/server/services/workshop/agents/opencode-agent/hitl.ts +113 -113
  1094. package/server/services/workshop/agents/opencode-agent/index.ts +16 -16
  1095. package/server/services/workshop/agents/opencode-agent/lifecycle.ts +44 -44
  1096. package/server/services/workshop/agents/opencode-agent/server.ts +244 -244
  1097. package/server/services/workshop/agents/opencode-agent/turn.ts +278 -278
  1098. package/server/services/workshop/agents/opencode-agent/types.ts +54 -54
  1099. package/server/services/workshop/agents/tool-classes.ts +44 -44
  1100. package/server/services/workshop/aml/clean.ts +120 -120
  1101. package/server/services/workshop/aml/entity.ts +367 -367
  1102. package/server/services/workshop/aml/job-orchestrator/broadcast.ts +37 -37
  1103. package/server/services/workshop/aml/job-orchestrator/control.ts +94 -94
  1104. package/server/services/workshop/aml/job-orchestrator/failure.ts +96 -96
  1105. package/server/services/workshop/aml/job-orchestrator/index.ts +22 -22
  1106. package/server/services/workshop/aml/job-orchestrator/process.ts +101 -101
  1107. package/server/services/workshop/aml/job-orchestrator/shared.ts +53 -53
  1108. package/server/services/workshop/aml/job-orchestrator/status.ts +20 -20
  1109. package/server/services/workshop/aml/job-orchestrator/tick.ts +37 -37
  1110. package/server/services/workshop/aml/python/train-example.py +92 -92
  1111. package/server/services/workshop/aml/runtime.ts +137 -137
  1112. package/server/services/workshop/aml/stats.ts +140 -140
  1113. package/server/services/workshop/aml/twin/calibration-worker.ts +150 -150
  1114. package/server/services/workshop/aml/twin/model-backed-provider.ts +332 -332
  1115. package/server/services/workshop/aml/twin/physics-spec-draft.ts +185 -185
  1116. package/server/services/workshop/aml/twin/prompt-composer.ts +143 -143
  1117. package/server/services/workshop/aml/twin/training-plans.ts +260 -260
  1118. package/server/services/workshop/aml/twin/write-guard.ts +19 -19
  1119. package/server/services/workshop/assets/character-asset.repo.ts +1 -1
  1120. package/server/services/workshop/assets/device-twin.repo.ts +1 -1
  1121. package/server/services/workshop/daq/bus/index.ts +5 -12
  1122. package/server/services/workshop/daq/daq-controller/contracts.ts +39 -39
  1123. package/server/services/workshop/daq/daq-controller/facade.ts +28 -28
  1124. package/server/services/workshop/daq/daq-controller/frames.ts +137 -137
  1125. package/server/services/workshop/daq/daq-controller/helpers.ts +52 -52
  1126. package/server/services/workshop/daq/daq-controller/index.ts +22 -22
  1127. package/server/services/workshop/daq/daq-controller/runtime-control.ts +72 -72
  1128. package/server/services/workshop/daq/daq-controller/sweep-alarms.ts +176 -176
  1129. package/server/services/workshop/daq/daq-controller/tsdb-twin.ts +138 -138
  1130. package/server/services/workshop/daq/drivers/http.ts +95 -95
  1131. package/server/services/workshop/daq/drivers/mock.ts +130 -130
  1132. package/server/services/workshop/daq/drivers/modbus-rtu.ts +67 -67
  1133. package/server/services/workshop/daq/drivers/modbus-tcp.ts +307 -307
  1134. package/server/services/workshop/daq/drivers/opcua.ts +227 -227
  1135. package/server/services/workshop/daq/drivers/s7-stub.ts +29 -29
  1136. package/server/services/workshop/daq/host-bindings.ts +71 -71
  1137. package/server/services/workshop/daq/host-ports.ts +65 -65
  1138. package/server/services/workshop/db/aml-team-seeds.ts +118 -118
  1139. package/server/services/workshop/db/backup-registry.ts +33 -33
  1140. package/server/services/workshop/db/channel-member.repo.ts +122 -122
  1141. package/server/services/workshop/db/channel.repo.ts +203 -203
  1142. package/server/services/workshop/db/chat-message.repo.ts +233 -233
  1143. package/server/services/workshop/db/database/index.ts +18 -18
  1144. package/server/services/workshop/db/database/json.ts +14 -14
  1145. package/server/services/workshop/db/database/open.ts +97 -97
  1146. package/server/services/workshop/db/database/seed-data.ts +60 -60
  1147. package/server/services/workshop/db/hitl-request.repo.ts +221 -221
  1148. package/server/services/workshop/db/notification.repo.ts +199 -199
  1149. package/server/services/workshop/db/readonly.ts +30 -30
  1150. package/server/services/workshop/db/scheduled-task.repo.ts +235 -235
  1151. package/server/services/workshop/db/transaction.ts +72 -72
  1152. package/server/services/workshop/dcw/dcw-controller/contracts.ts +16 -16
  1153. package/server/services/workshop/dcw/dcw-controller/control.ts +78 -78
  1154. package/server/services/workshop/dcw/dcw-controller/facade.ts +19 -19
  1155. package/server/services/workshop/dcw/dcw-controller/index.ts +22 -22
  1156. package/server/services/workshop/dcw/dcw-controller/params.ts +97 -97
  1157. package/server/services/workshop/dcw/dcw-controller/products.ts +103 -103
  1158. package/server/services/workshop/dcw/dcw-controller/write-audit.ts +49 -49
  1159. package/server/services/workshop/dcw/dcw-templates.ts +136 -136
  1160. package/server/services/workshop/dcw/param-conversion.ts +78 -78
  1161. package/server/services/workshop/dcw/param-map.repo.ts +349 -349
  1162. package/server/services/workshop/dcw/plugin-bridge.ts +45 -45
  1163. package/server/services/workshop/dcw/recipe-rollback-manager/contracts.ts +26 -26
  1164. package/server/services/workshop/dcw/recipe-rollback-manager/facade.ts +13 -13
  1165. package/server/services/workshop/dcw/recipe-rollback-manager/helpers.ts +30 -30
  1166. package/server/services/workshop/dcw/recipe-rollback-manager/index.ts +17 -17
  1167. package/server/services/workshop/dcw/recipe-rollback-manager/internal.ts +33 -33
  1168. package/server/services/workshop/dcw/recipe-rollback-manager/judge.ts +52 -52
  1169. package/server/services/workshop/dcw/recipe-rollback-manager/lock.ts +137 -137
  1170. package/server/services/workshop/dcw/recipe-rollback-manager/rollback.ts +190 -190
  1171. package/server/services/workshop/dcw/recipe-rollback-manager/state.ts +21 -21
  1172. package/server/services/workshop/dcw/recipe-rollback-manager/sweep.ts +77 -77
  1173. package/server/services/workshop/dcw/recipe-rollback-manager/types.ts +3 -3
  1174. package/server/services/workshop/dcw/recipe-rollback-manager/views.ts +214 -214
  1175. package/server/services/workshop/exp/exp-collector.ts +275 -275
  1176. package/server/services/workshop/exp/exp-state.repo.ts +339 -339
  1177. package/server/services/workshop/mes/mes-controller.ts +1155 -1155
  1178. package/server/services/workshop/mes/mes-hook.ts +567 -567
  1179. package/server/services/workshop/ontology/subgraph.core.ts +300 -300
  1180. package/server/services/workshop/ontology/subgraph.service.ts +113 -113
  1181. package/server/services/workshop/plugins/host/api.mjs +90 -90
  1182. package/server/services/workshop/plugins/host/config.mjs +135 -135
  1183. package/server/services/workshop/plugins/host/index.mjs +23 -23
  1184. package/server/services/workshop/plugins/host/init.mjs +109 -109
  1185. package/server/services/workshop/plugins/host/load.mjs +321 -321
  1186. package/server/services/workshop/plugins/host/reload.mjs +94 -94
  1187. package/server/services/workshop/plugins/host/rollback.mjs +72 -72
  1188. package/server/services/workshop/plugins/host/state.mjs +54 -54
  1189. package/server/services/workshop/plugins/host/toggle.mjs +64 -64
  1190. package/server/services/workshop/plugins/host.mjs +9 -9
  1191. package/server/services/workshop/runtime/agent-runtime/facade.ts +7 -7
  1192. package/server/services/workshop/runtime/agent-runtime/helpers.ts +18 -18
  1193. package/server/services/workshop/runtime/agent-runtime/index.ts +19 -19
  1194. package/server/services/workshop/runtime/agent-runtime/lifecycle.ts +137 -137
  1195. package/server/services/workshop/runtime/chat-mention.ts +164 -164
  1196. package/server/services/workshop/runtime/chat-projection.ts +246 -246
  1197. package/server/services/workshop/runtime/manager/admin-agents.ts +268 -268
  1198. package/server/services/workshop/runtime/manager/bus.ts +182 -182
  1199. package/server/services/workshop/runtime/manager/channel-template-constants.ts +20 -20
  1200. package/server/services/workshop/runtime/manager/chat-reply.ts +181 -181
  1201. package/server/services/workshop/runtime/manager/chat.ts +384 -384
  1202. package/server/services/workshop/runtime/manager/facade.ts +24 -24
  1203. package/server/services/workshop/runtime/manager/helpers.ts +119 -119
  1204. package/server/services/workshop/runtime/manager/index.ts +42 -42
  1205. package/server/services/workshop/runtime/manager/internal.ts +73 -73
  1206. package/server/services/workshop/runtime/manager/notifications.ts +108 -108
  1207. package/server/services/workshop/runtime/manager/teams.ts +148 -148
  1208. package/server/services/workshop/runtime/memory/contracts.ts +18 -18
  1209. package/server/services/workshop/runtime/memory/facade.ts +10 -10
  1210. package/server/services/workshop/runtime/memory/helpers.ts +196 -196
  1211. package/server/services/workshop/runtime/memory/index.ts +27 -27
  1212. package/server/services/workshop/runtime/memory/score.ts +33 -33
  1213. package/server/services/workshop/runtime/memory/state.ts +40 -40
  1214. package/server/services/workshop/runtime/monitor.ts +3 -3
  1215. package/server/services/workshop/runtime/platform-notice.ts +113 -113
  1216. package/server/services/workshop/runtime/schedule-runtime.ts +347 -347
  1217. package/server/services/workshop/runtime/scheduler-loop/contracts.ts +29 -29
  1218. package/server/services/workshop/runtime/scheduler-loop/facade.ts +7 -7
  1219. package/server/services/workshop/runtime/scheduler-loop/helpers.ts +14 -14
  1220. package/server/services/workshop/runtime/scheduler-loop/index.ts +16 -16
  1221. package/server/services/workshop/runtime/task-engine/facade.ts +7 -7
  1222. package/server/services/workshop/runtime/task-engine/index.ts +15 -15
  1223. package/server/services/workshop/runtime/task-engine/types.ts +3 -3
  1224. package/server/services/workshop/runtime/user-notification-hub.ts +192 -192
  1225. package/server/types/pg.d.ts +49 -49
  1226. package/server/utils/approval-gate.ts +67 -67
  1227. package/server/utils/mojibake-guard.ts +29 -29
  1228. package/server/utils/stability-severity.ts +77 -77
  1229. package/shared/config/groups.mjs +241 -241
  1230. package/shared/dcw-protocol/catalog.ts +232 -232
  1231. package/shared/dcw-protocol/closed-loop.ts +137 -137
  1232. package/shared/lru.mjs +97 -97
  1233. package/tui/README.md +74 -74
  1234. package/tui/aw-tui.mjs +445 -445
  1235. package/tui/commands/index.mjs +287 -287
  1236. package/tui/components/chat-log.mjs +42 -42
  1237. package/tui/components/monitor-pane.mjs +39 -39
  1238. package/tui/components/root.mjs +53 -53
  1239. package/tui/components/status-bar.mjs +33 -33
  1240. package/tui/lib/api.mjs +82 -82
  1241. package/tui/lib/pickers.mjs +121 -121
  1242. package/tui/lib/reducers.mjs +218 -218
  1243. package/tui/lib/state.mjs +86 -86
  1244. package/tui/lib/virtual-terminal.mjs +48 -48
  1245. package/tui/lib/ws.mjs +125 -125
  1246. package/tui/theme.mjs +38 -38
  1247. package/.output/.AgentWorkShop/aml-python/__pycache__/aml_eval.cpython-312.pyc +0 -0
  1248. package/.output/.AgentWorkShop/aml-python/__pycache__/amlkit.cpython-312.pyc +0 -0
  1249. package/.output/.AgentWorkShop/aml-python/__pycache__/train-example.cpython-312.pyc +0 -0
  1250. package/.output/.AgentWorkShop/aml-python/__pycache__/train-hybrid-example.cpython-312.pyc +0 -0
  1251. package/.output/public/_nuxt/BRYBzVMJ.js +0 -1
  1252. package/.output/public/_nuxt/BW2uTUx52.js +0 -2
  1253. package/.output/public/_nuxt/BtZKe9ZV.js +0 -1
  1254. package/.output/public/_nuxt/CfFUK6932.js +0 -2
  1255. package/.output/public/_nuxt/DhW7cFOa.js +0 -1
  1256. package/.output/public/_nuxt/OmpTerminalPanel.ComMDrA8.css +0 -1
  1257. package/.output/public/_nuxt/PluginSlot.CGH0vb95.css +0 -1
  1258. package/.output/public/_nuxt/TownView.CC3t-Dte.css +0 -1
  1259. package/.output/public/_nuxt/aml.PalMp-5n.css +0 -1
  1260. package/.output/public/_nuxt/builds/meta/fa0af8b5-3929-428d-a6de-3b5cc6b8248f.json +0 -1
  1261. package/.output/public/_nuxt/permissions.DxuOOIqQ.css +0 -1
  1262. package/.output/public/_nuxt/schedules.BXNJ9q_I.css +0 -1
  1263. package/.output/public/_nuxt/tools.BwXFAb-X.css +0 -1
  1264. package/.output/server/chunks/build/AuthGate-nF1evO4v.mjs +0 -716
  1265. package/.output/server/chunks/build/AuthGate-nF1evO4v.mjs.map +0 -1
  1266. package/.output/server/chunks/build/FormItemContext-BlyzocS0.mjs +0 -72
  1267. package/.output/server/chunks/build/FormItemContext-BlyzocS0.mjs.map +0 -1
  1268. package/.output/server/chunks/build/OmpTerminalPanel-BhvhQ1gG.mjs +0 -942
  1269. package/.output/server/chunks/build/OmpTerminalPanel-BhvhQ1gG.mjs.map +0 -1
  1270. package/.output/server/chunks/build/PluginSlot-BUKXwV2X.mjs +0 -141
  1271. package/.output/server/chunks/build/PluginSlot-BUKXwV2X.mjs.map +0 -1
  1272. package/.output/server/chunks/build/TownView-BWMDbosY.mjs +0 -6489
  1273. package/.output/server/chunks/build/TownView-BWMDbosY.mjs.map +0 -1
  1274. package/.output/server/chunks/build/_id_-BK-t8nRG.mjs +0 -392
  1275. package/.output/server/chunks/build/_id_-BK-t8nRG.mjs.map +0 -1
  1276. package/.output/server/chunks/build/_id_-CZPlPDm4.mjs +0 -2045
  1277. package/.output/server/chunks/build/_id_-CZPlPDm4.mjs.map +0 -1
  1278. package/.output/server/chunks/build/_wsId_-BPy-Aj9L.mjs +0 -14297
  1279. package/.output/server/chunks/build/_wsId_-BPy-Aj9L.mjs.map +0 -1
  1280. package/.output/server/chunks/build/agents-CpNLdI8E.mjs +0 -1078
  1281. package/.output/server/chunks/build/agents-CpNLdI8E.mjs.map +0 -1
  1282. package/.output/server/chunks/build/alert-D0ivtTGy.mjs +0 -263
  1283. package/.output/server/chunks/build/alert-D0ivtTGy.mjs.map +0 -1
  1284. package/.output/server/chunks/build/aml-DRAFRcGU.mjs +0 -814
  1285. package/.output/server/chunks/build/aml-DRAFRcGU.mjs.map +0 -1
  1286. package/.output/server/chunks/build/analysis-p-dBkjoK.mjs +0 -533
  1287. package/.output/server/chunks/build/analysis-p-dBkjoK.mjs.map +0 -1
  1288. package/.output/server/chunks/build/api-B4Om0mEc.mjs.map +0 -1
  1289. package/.output/server/chunks/build/api-BEW_ebY_.mjs.map +0 -1
  1290. package/.output/server/chunks/build/api-BsAgXWxi.mjs.map +0 -1
  1291. package/.output/server/chunks/build/api-error-BwAQLw44.mjs +0 -47
  1292. package/.output/server/chunks/build/api-error-BwAQLw44.mjs.map +0 -1
  1293. package/.output/server/chunks/build/apiClient-BvXtNzC8.mjs +0 -81
  1294. package/.output/server/chunks/build/apiClient-BvXtNzC8.mjs.map +0 -1
  1295. package/.output/server/chunks/build/board-Dl2Ar22r.mjs +0 -178
  1296. package/.output/server/chunks/build/board-Dl2Ar22r.mjs.map +0 -1
  1297. package/.output/server/chunks/build/card-Cqk0Ur-L.mjs +0 -953
  1298. package/.output/server/chunks/build/card-Cqk0Ur-L.mjs.map +0 -1
  1299. package/.output/server/chunks/build/channel-templates-ByHOQQkO.mjs +0 -942
  1300. package/.output/server/chunks/build/channel-templates-ByHOQQkO.mjs.map +0 -1
  1301. package/.output/server/chunks/build/checkbox-CrT4cnfu.mjs +0 -439
  1302. package/.output/server/chunks/build/checkbox-CrT4cnfu.mjs.map +0 -1
  1303. package/.output/server/chunks/build/client-only-qNA2OVV_.mjs +0 -43
  1304. package/.output/server/chunks/build/client-only-qNA2OVV_.mjs.map +0 -1
  1305. package/.output/server/chunks/build/core-CgTOPS4t.mjs +0 -294
  1306. package/.output/server/chunks/build/core-CgTOPS4t.mjs.map +0 -1
  1307. package/.output/server/chunks/build/daq-CdxcfY_G.mjs +0 -1266
  1308. package/.output/server/chunks/build/daq-CdxcfY_G.mjs.map +0 -1
  1309. package/.output/server/chunks/build/data-D8uX1dnm.mjs +0 -481
  1310. package/.output/server/chunks/build/data-D8uX1dnm.mjs.map +0 -1
  1311. package/.output/server/chunks/build/dcw-BlDQtS4q.mjs +0 -505
  1312. package/.output/server/chunks/build/dcw-BlDQtS4q.mjs.map +0 -1
  1313. package/.output/server/chunks/build/default-CNWS6NUw.mjs +0 -2353
  1314. package/.output/server/chunks/build/default-CNWS6NUw.mjs.map +0 -1
  1315. package/.output/server/chunks/build/descriptions-BNlfKG9y.mjs +0 -406
  1316. package/.output/server/chunks/build/descriptions-BNlfKG9y.mjs.map +0 -1
  1317. package/.output/server/chunks/build/drawer-Caji0PLs.mjs +0 -834
  1318. package/.output/server/chunks/build/drawer-Caji0PLs.mjs.map +0 -1
  1319. package/.output/server/chunks/build/dropdown-BNwTVGde.mjs +0 -14
  1320. package/.output/server/chunks/build/dropdown-BNwTVGde.mjs.map +0 -1
  1321. package/.output/server/chunks/build/dropdown-Cd-xPhR6.mjs +0 -540
  1322. package/.output/server/chunks/build/dropdown-Cd-xPhR6.mjs.map +0 -1
  1323. package/.output/server/chunks/build/es-Bxu10NJ2.mjs.map +0 -1
  1324. package/.output/server/chunks/build/firstNotUndefined-8H5_qHUu.mjs +0 -2448
  1325. package/.output/server/chunks/build/firstNotUndefined-8H5_qHUu.mjs.map +0 -1
  1326. package/.output/server/chunks/build/form-D_UpWPN4.mjs +0 -4712
  1327. package/.output/server/chunks/build/form-D_UpWPN4.mjs.map +0 -1
  1328. package/.output/server/chunks/build/hasIn-DBdElbjM.mjs +0 -553
  1329. package/.output/server/chunks/build/hasIn-DBdElbjM.mjs.map +0 -1
  1330. package/.output/server/chunks/build/hitl-Bd30yr1J.mjs +0 -132
  1331. package/.output/server/chunks/build/hitl-Bd30yr1J.mjs.map +0 -1
  1332. package/.output/server/chunks/build/input-GtPuSEgt.mjs +0 -2181
  1333. package/.output/server/chunks/build/input-GtPuSEgt.mjs.map +0 -1
  1334. package/.output/server/chunks/build/input-number-BNlNDK7H.mjs +0 -1120
  1335. package/.output/server/chunks/build/input-number-BNlNDK7H.mjs.map +0 -1
  1336. package/.output/server/chunks/build/interval-DvHBIIZh.mjs +0 -9
  1337. package/.output/server/chunks/build/interval-DvHBIIZh.mjs.map +0 -1
  1338. package/.output/server/chunks/build/isNumeric-CP7q_yhz.mjs +0 -7
  1339. package/.output/server/chunks/build/isNumeric-CP7q_yhz.mjs.map +0 -1
  1340. package/.output/server/chunks/build/logs-pRb-TMWa.mjs +0 -427
  1341. package/.output/server/chunks/build/logs-pRb-TMWa.mjs.map +0 -1
  1342. package/.output/server/chunks/build/menu-BXt-X0dt.mjs +0 -1952
  1343. package/.output/server/chunks/build/menu-BXt-X0dt.mjs.map +0 -1
  1344. package/.output/server/chunks/build/monitor-Cq6hRFeQ.mjs +0 -2253
  1345. package/.output/server/chunks/build/monitor-Cq6hRFeQ.mjs.map +0 -1
  1346. package/.output/server/chunks/build/ontology-DK0Mf0zT.mjs +0 -1406
  1347. package/.output/server/chunks/build/ontology-DK0Mf0zT.mjs.map +0 -1
  1348. package/.output/server/chunks/build/operations-SMQrRAcr.mjs +0 -311
  1349. package/.output/server/chunks/build/operations-SMQrRAcr.mjs.map +0 -1
  1350. package/.output/server/chunks/build/optimizer-BlWTsM-W.mjs +0 -202
  1351. package/.output/server/chunks/build/optimizer-BlWTsM-W.mjs.map +0 -1
  1352. package/.output/server/chunks/build/pages-AFRP4-EL.mjs +0 -542
  1353. package/.output/server/chunks/build/pages-AFRP4-EL.mjs.map +0 -1
  1354. package/.output/server/chunks/build/pagination-DTAconUo.mjs +0 -1346
  1355. package/.output/server/chunks/build/pagination-DTAconUo.mjs.map +0 -1
  1356. package/.output/server/chunks/build/permissions-DgXQZSyx.mjs +0 -637
  1357. package/.output/server/chunks/build/permissions-DgXQZSyx.mjs.map +0 -1
  1358. package/.output/server/chunks/build/plugins-LRjaSEZy.mjs +0 -272
  1359. package/.output/server/chunks/build/plugins-LRjaSEZy.mjs.map +0 -1
  1360. package/.output/server/chunks/build/popconfirm-DxYPGRgS.mjs +0 -340
  1361. package/.output/server/chunks/build/popconfirm-DxYPGRgS.mjs.map +0 -1
  1362. package/.output/server/chunks/build/responsiveObserve-DM3hpzhU.mjs +0 -78
  1363. package/.output/server/chunks/build/responsiveObserve-DM3hpzhU.mjs.map +0 -1
  1364. package/.output/server/chunks/build/schedules-dSnr8url.mjs +0 -7172
  1365. package/.output/server/chunks/build/schedules-dSnr8url.mjs.map +0 -1
  1366. package/.output/server/chunks/build/segmented-D3HWtHPw.mjs +0 -341
  1367. package/.output/server/chunks/build/segmented-D3HWtHPw.mjs.map +0 -1
  1368. package/.output/server/chunks/build/select-B3Dsb9yq.mjs +0 -3923
  1369. package/.output/server/chunks/build/select-B3Dsb9yq.mjs.map +0 -1
  1370. package/.output/server/chunks/build/settings-BrIhnS2Z.mjs +0 -1014
  1371. package/.output/server/chunks/build/settings-BrIhnS2Z.mjs.map +0 -1
  1372. package/.output/server/chunks/build/space-Dwu2Skt8.mjs +0 -110
  1373. package/.output/server/chunks/build/space-Dwu2Skt8.mjs.map +0 -1
  1374. package/.output/server/chunks/build/spin-C2cuvGth.mjs +0 -357
  1375. package/.output/server/chunks/build/spin-C2cuvGth.mjs.map +0 -1
  1376. package/.output/server/chunks/build/studio-cdoNCfyy.mjs +0 -332
  1377. package/.output/server/chunks/build/studio-cdoNCfyy.mjs.map +0 -1
  1378. package/.output/server/chunks/build/switch-CyR-H6Fb.mjs +0 -377
  1379. package/.output/server/chunks/build/switch-CyR-H6Fb.mjs.map +0 -1
  1380. package/.output/server/chunks/build/table-CmVD-cA9.mjs +0 -7546
  1381. package/.output/server/chunks/build/table-CmVD-cA9.mjs.map +0 -1
  1382. package/.output/server/chunks/build/tabs-Vg0e7cZE.mjs +0 -1924
  1383. package/.output/server/chunks/build/tabs-Vg0e7cZE.mjs.map +0 -1
  1384. package/.output/server/chunks/build/tag-y0sn-xv9.mjs +0 -1156
  1385. package/.output/server/chunks/build/tag-y0sn-xv9.mjs.map +0 -1
  1386. package/.output/server/chunks/build/teams-B1d32eHK.mjs +0 -1203
  1387. package/.output/server/chunks/build/teams-B1d32eHK.mjs.map +0 -1
  1388. package/.output/server/chunks/build/tokens-GYaGJ35Z.mjs +0 -1062
  1389. package/.output/server/chunks/build/tokens-GYaGJ35Z.mjs.map +0 -1
  1390. package/.output/server/chunks/build/tools-s_9U1Djj.mjs +0 -487
  1391. package/.output/server/chunks/build/tools-s_9U1Djj.mjs.map +0 -1
  1392. package/.output/server/chunks/build/tooltip-C2n2nNiQ.mjs +0 -920
  1393. package/.output/server/chunks/build/tooltip-C2n2nNiQ.mjs.map +0 -1
  1394. package/.output/server/chunks/build/town-B5aoiG98.mjs +0 -133
  1395. package/.output/server/chunks/build/town-B5aoiG98.mjs.map +0 -1
  1396. package/.output/server/chunks/build/useAgentHarnessOptions-DOrQHeBh.mjs +0 -124
  1397. package/.output/server/chunks/build/useAgentHarnessOptions-DOrQHeBh.mjs.map +0 -1
  1398. package/.output/server/chunks/build/useAgentTemplateActions-CzlplRWh.mjs +0 -77
  1399. package/.output/server/chunks/build/useAgentTemplateActions-CzlplRWh.mjs.map +0 -1
  1400. package/.output/server/chunks/build/useAgentTemplateForm-DQo1enf2.mjs +0 -117
  1401. package/.output/server/chunks/build/useAgentTemplateForm-DQo1enf2.mjs.map +0 -1
  1402. package/.output/server/chunks/build/useAgentTemplatesCatalog-DP-iMmqz.mjs +0 -133
  1403. package/.output/server/chunks/build/useAgentTemplatesCatalog-DP-iMmqz.mjs.map +0 -1
  1404. package/.output/server/chunks/build/useAmlDatasets-DeoE1idn.mjs +0 -92
  1405. package/.output/server/chunks/build/useAmlDatasets-DeoE1idn.mjs.map +0 -1
  1406. package/.output/server/chunks/build/useAmlEntities-BJhvdqHJ.mjs +0 -86
  1407. package/.output/server/chunks/build/useAmlEntities-BJhvdqHJ.mjs.map +0 -1
  1408. package/.output/server/chunks/build/useAmlEnv-CDIZ6xTe.mjs +0 -194
  1409. package/.output/server/chunks/build/useAmlEnv-CDIZ6xTe.mjs.map +0 -1
  1410. package/.output/server/chunks/build/useAmlExperiments-Dloi834i.mjs +0 -89
  1411. package/.output/server/chunks/build/useAmlExperiments-Dloi834i.mjs.map +0 -1
  1412. package/.output/server/chunks/build/useAmlJobs-BF9LpwXz.mjs +0 -267
  1413. package/.output/server/chunks/build/useAmlJobs-BF9LpwXz.mjs.map +0 -1
  1414. package/.output/server/chunks/build/useAmlModels-_bweOr3R.mjs +0 -93
  1415. package/.output/server/chunks/build/useAmlModels-_bweOr3R.mjs.map +0 -1
  1416. package/.output/server/chunks/build/useAmlNotes-DQj980iX.mjs +0 -86
  1417. package/.output/server/chunks/build/useAmlNotes-DQj980iX.mjs.map +0 -1
  1418. package/.output/server/chunks/build/useAmlPredict-DHNgDSJn.mjs +0 -130
  1419. package/.output/server/chunks/build/useAmlPredict-DHNgDSJn.mjs.map +0 -1
  1420. package/.output/server/chunks/build/useAnalysisFeed-BrEGV_9x.mjs +0 -129
  1421. package/.output/server/chunks/build/useAnalysisFeed-BrEGV_9x.mjs.map +0 -1
  1422. package/.output/server/chunks/build/useDaqAddNode-D_Rkju0f.mjs +0 -142
  1423. package/.output/server/chunks/build/useDaqAddNode-D_Rkju0f.mjs.map +0 -1
  1424. package/.output/server/chunks/build/useDaqDetailBinding-DCWaLKXT.mjs +0 -70
  1425. package/.output/server/chunks/build/useDaqDetailBinding-DCWaLKXT.mjs.map +0 -1
  1426. package/.output/server/chunks/build/useDaqDetailFrames-BOIcOJRB.mjs +0 -79
  1427. package/.output/server/chunks/build/useDaqDetailFrames-BOIcOJRB.mjs.map +0 -1
  1428. package/.output/server/chunks/build/useDaqDetailHistory-D6WulPVs.mjs +0 -176
  1429. package/.output/server/chunks/build/useDaqDetailHistory-D6WulPVs.mjs.map +0 -1
  1430. package/.output/server/chunks/build/useDaqDetailNode-DeOsDxK5.mjs +0 -99
  1431. package/.output/server/chunks/build/useDaqDetailNode-DeOsDxK5.mjs.map +0 -1
  1432. package/.output/server/chunks/build/useDaqDetailParams-Cm9a9r5G.mjs +0 -159
  1433. package/.output/server/chunks/build/useDaqDetailParams-Cm9a9r5G.mjs.map +0 -1
  1434. package/.output/server/chunks/build/useDaqFilters-CctmO03p.mjs +0 -222
  1435. package/.output/server/chunks/build/useDaqFilters-CctmO03p.mjs.map +0 -1
  1436. package/.output/server/chunks/build/useDaqOptimizations-CmX_dpBc.mjs +0 -136
  1437. package/.output/server/chunks/build/useDaqOptimizations-CmX_dpBc.mjs.map +0 -1
  1438. package/.output/server/chunks/build/useDaqStream-B9ZBVQrI.mjs +0 -395
  1439. package/.output/server/chunks/build/useDaqStream-B9ZBVQrI.mjs.map +0 -1
  1440. package/.output/server/chunks/build/useDaqTemplates-CK37sMfi.mjs +0 -187
  1441. package/.output/server/chunks/build/useDaqTemplates-CK37sMfi.mjs.map +0 -1
  1442. package/.output/server/chunks/build/useDashboardData-B36wVWo2.mjs +0 -153
  1443. package/.output/server/chunks/build/useDashboardData-B36wVWo2.mjs.map +0 -1
  1444. package/.output/server/chunks/build/useDcwAddNode-DACVcEHs.mjs +0 -219
  1445. package/.output/server/chunks/build/useDcwAddNode-DACVcEHs.mjs.map +0 -1
  1446. package/.output/server/chunks/build/useDcwCards-SaiImIYQ.mjs.map +0 -1
  1447. package/.output/server/chunks/build/useDcwDetailScope-DLOklSMO.mjs +0 -184
  1448. package/.output/server/chunks/build/useDcwDetailScope-DLOklSMO.mjs.map +0 -1
  1449. package/.output/server/chunks/build/useDcwDetailTemplates-ClmIdZ40.mjs +0 -148
  1450. package/.output/server/chunks/build/useDcwDetailTemplates-ClmIdZ40.mjs.map +0 -1
  1451. package/.output/server/chunks/build/useDcwFilter-CPMyCltx.mjs +0 -71
  1452. package/.output/server/chunks/build/useDcwFilter-CPMyCltx.mjs.map +0 -1
  1453. package/.output/server/chunks/build/useDcwLedger-0ie-0WTc.mjs.map +0 -1
  1454. package/.output/server/chunks/build/useDcwLineMutations-DNxo66yM.mjs +0 -137
  1455. package/.output/server/chunks/build/useDcwLineMutations-DNxo66yM.mjs.map +0 -1
  1456. package/.output/server/chunks/build/useDcwLineRun-CHskwscT.mjs +0 -104
  1457. package/.output/server/chunks/build/useDcwLineRun-CHskwscT.mjs.map +0 -1
  1458. package/.output/server/chunks/build/useDcwParamApprovals-DtScUc-W.mjs +0 -121
  1459. package/.output/server/chunks/build/useDcwParamApprovals-DtScUc-W.mjs.map +0 -1
  1460. package/.output/server/chunks/build/useDcwProducts-BMaxzLu6.mjs +0 -93
  1461. package/.output/server/chunks/build/useDcwProducts-BMaxzLu6.mjs.map +0 -1
  1462. package/.output/server/chunks/build/useDcwQuery-TVU3Eo0M.mjs +0 -98
  1463. package/.output/server/chunks/build/useDcwQuery-TVU3Eo0M.mjs.map +0 -1
  1464. package/.output/server/chunks/build/useDcwQuickActions-BREFmR9T.mjs +0 -88
  1465. package/.output/server/chunks/build/useDcwQuickActions-BREFmR9T.mjs.map +0 -1
  1466. package/.output/server/chunks/build/useDcwRecipes-Bc9urA1N.mjs +0 -258
  1467. package/.output/server/chunks/build/useDcwRecipes-Bc9urA1N.mjs.map +0 -1
  1468. package/.output/server/chunks/build/useDcwStream-Dir5ufAU.mjs +0 -452
  1469. package/.output/server/chunks/build/useDcwStream-Dir5ufAU.mjs.map +0 -1
  1470. package/.output/server/chunks/build/useDcwTemplates-BzagZztS.mjs +0 -91
  1471. package/.output/server/chunks/build/useDcwTemplates-BzagZztS.mjs.map +0 -1
  1472. package/.output/server/chunks/build/useDcwWrites-BROwTLCn.mjs +0 -140
  1473. package/.output/server/chunks/build/useDcwWrites-BROwTLCn.mjs.map +0 -1
  1474. package/.output/server/chunks/build/useDeviceTwins-BqwVJaZg.mjs +0 -128
  1475. package/.output/server/chunks/build/useDeviceTwins-BqwVJaZg.mjs.map +0 -1
  1476. package/.output/server/chunks/build/useExpConfirmations-BM626N4p.mjs +0 -107
  1477. package/.output/server/chunks/build/useExpConfirmations-BM626N4p.mjs.map +0 -1
  1478. package/.output/server/chunks/build/useLocalTime-uVSM44Um.mjs +0 -55
  1479. package/.output/server/chunks/build/useLocalTime-uVSM44Um.mjs.map +0 -1
  1480. package/.output/server/chunks/build/useLogsManual-cVBZQ_Mt.mjs +0 -88
  1481. package/.output/server/chunks/build/useLogsManual-cVBZQ_Mt.mjs.map +0 -1
  1482. package/.output/server/chunks/build/useLogsQuery-D7hrJ3yn.mjs +0 -150
  1483. package/.output/server/chunks/build/useLogsQuery-D7hrJ3yn.mjs.map +0 -1
  1484. package/.output/server/chunks/build/useLogsScope-aaPQeTRm.mjs +0 -83
  1485. package/.output/server/chunks/build/useLogsScope-aaPQeTRm.mjs.map +0 -1
  1486. package/.output/server/chunks/build/useMonitorData-DIkiLr_h.mjs +0 -135
  1487. package/.output/server/chunks/build/useMonitorData-DIkiLr_h.mjs.map +0 -1
  1488. package/.output/server/chunks/build/useMonitorFormat-CyURtH8N.mjs +0 -91
  1489. package/.output/server/chunks/build/useMonitorFormat-CyURtH8N.mjs.map +0 -1
  1490. package/.output/server/chunks/build/useOperationsFeed-Ci4mZAn_.mjs +0 -195
  1491. package/.output/server/chunks/build/useOperationsFeed-Ci4mZAn_.mjs.map +0 -1
  1492. package/.output/server/chunks/build/useOpsLog-C-M6Eace.mjs +0 -149
  1493. package/.output/server/chunks/build/useOpsLog-C-M6Eace.mjs.map +0 -1
  1494. package/.output/server/chunks/build/useRecipeDispatchApprovals-BYtiqfeb.mjs +0 -156
  1495. package/.output/server/chunks/build/useRecipeDispatchApprovals-BYtiqfeb.mjs.map +0 -1
  1496. package/.output/server/chunks/build/useTeamActions-I_8QWp9w.mjs +0 -79
  1497. package/.output/server/chunks/build/useTeamActions-I_8QWp9w.mjs.map +0 -1
  1498. package/.output/server/chunks/build/useTeamAddMemberDialog-BLn4nTuy.mjs +0 -84
  1499. package/.output/server/chunks/build/useTeamAddMemberDialog-BLn4nTuy.mjs.map +0 -1
  1500. package/.output/server/chunks/build/useTeamCreateDialog-Bp5qKtpI.mjs +0 -97
  1501. package/.output/server/chunks/build/useTeamCreateDialog-Bp5qKtpI.mjs.map +0 -1
  1502. package/.output/server/chunks/build/useTeamDeployDialog-DwIaz6Cx.mjs +0 -80
  1503. package/.output/server/chunks/build/useTeamDeployDialog-DwIaz6Cx.mjs.map +0 -1
  1504. package/.output/server/chunks/build/useTeamPluginDialog-B932gZOI.mjs +0 -103
  1505. package/.output/server/chunks/build/useTeamPluginDialog-B932gZOI.mjs.map +0 -1
  1506. package/.output/server/chunks/build/useTeamsCatalog-DBwaLQBw.mjs +0 -123
  1507. package/.output/server/chunks/build/useTeamsCatalog-DBwaLQBw.mjs.map +0 -1
  1508. package/.output/server/chunks/build/useTokenCreate-Ctl0YGhL.mjs +0 -115
  1509. package/.output/server/chunks/build/useTokenCreate-Ctl0YGhL.mjs.map +0 -1
  1510. package/.output/server/chunks/build/useTokenRename-Cm3ypSfN.mjs +0 -87
  1511. package/.output/server/chunks/build/useTokenRename-Cm3ypSfN.mjs.map +0 -1
  1512. package/.output/server/chunks/build/useTokenReveal-CeoWL5Mt.mjs +0 -118
  1513. package/.output/server/chunks/build/useTokenReveal-CeoWL5Mt.mjs.map +0 -1
  1514. package/.output/server/chunks/build/useTokensList-CNIzON3u.mjs +0 -92
  1515. package/.output/server/chunks/build/useTokensList-CNIzON3u.mjs.map +0 -1
  1516. package/.output/server/chunks/build/useWorkbenchAuth-CY-bVFMu.mjs +0 -141
  1517. package/.output/server/chunks/build/useWorkbenchAuth-CY-bVFMu.mjs.map +0 -1
  1518. package/.output/server/chunks/build/useWorkbenchWorkspaces-DhZQFss9.mjs +0 -138
  1519. package/.output/server/chunks/build/useWorkbenchWorkspaces-DhZQFss9.mjs.map +0 -1
  1520. package/.output/server/chunks/build/useWorkshopApi-CaSItJVq.mjs +0 -119
  1521. package/.output/server/chunks/build/useWorkshopApi-CaSItJVq.mjs.map +0 -1
  1522. package/.output/server/chunks/build/useWorkshopWs-YQ5URrbt.mjs +0 -1659
  1523. package/.output/server/chunks/build/useWorkshopWs-YQ5URrbt.mjs.map +0 -1
  1524. package/.output/server/chunks/build/useWorkspaceAuth-Dlvj9csD.mjs.map +0 -1
  1525. package/.output/server/chunks/build/useWorkspaceChannels-CPFepxTN.mjs +0 -92
  1526. package/.output/server/chunks/build/useWorkspaceChannels-CPFepxTN.mjs.map +0 -1
  1527. package/.output/server/chunks/build/useWorkspaceShell-BCypjjjE.mjs +0 -168
  1528. package/.output/server/chunks/build/useWorkspaceShell-BCypjjjE.mjs.map +0 -1
  1529. package/.output/server/chunks/build/users-DjiVC_tS.mjs +0 -569
  1530. package/.output/server/chunks/build/users-DjiVC_tS.mjs.map +0 -1
  1531. package/.output/server/chunks/build/workshop-1gKeDASV.mjs +0 -546
  1532. package/.output/server/chunks/build/workshop-1gKeDASV.mjs.map +0 -1
  1533. package/app/.mimosa/hook-state/sess_05189059-e42d-4188-8911-4f7baabe009b.json +0 -1
  1534. package/app/.mimosa/hook-state/sess_05189059-e42d-4188-8911-4f7baabe009b.mtg0vz68-49792-75b0709555.baseline/1459e6269990a5d229b9228c8b2f62ffaa7d350068380ae8b875fee0db45cca6.source +0 -180
  1535. package/app/.mimosa/hook-state/sess_05189059-e42d-4188-8911-4f7baabe009b.mtg0vz68-49792-75b0709555.baseline/c2991e909c70c5c12b90a407c7adcf63384c51668a2b334e6e047fa675c268fe.source +0 -305
  1536. package/app/.mimosa/hook-state/sess_05189059-e42d-4188-8911-4f7baabe009b.mtg0vz68-49792-75b0709555.baseline/e09129039d1e27e3fac24becc9bdafd2d1a7c8049bff24173df007be865f0165.source +0 -264
  1537. package/app/.mimosa/hook-status/sess_05189059-e42d-4188-8911-4f7baabe009b-28ef7c75ea.json +0 -14
  1538. package/scripts/e2e-direct-rest-simulator-paper.mjs +0 -624
  1539. package/scripts/e2e-pi-simulator-paper.mjs +0 -2316
  1540. package/scripts/e2e-registered-harness-simulator-paper.mjs +0 -1926
  1541. package/scripts/e2e-simulator-optimizer-paper.mjs +0 -264
  1542. package/scripts/fixtures/omp-paper-harness.mjs +0 -163
  1543. package/server/.mimosa/hook-state/sess_869e5bfd-07f4-4b6e-a991-6221fcf6b7d2.json +0 -1
  1544. package/server/.mimosa/hook-state/sess_869e5bfd-07f4-4b6e-a991-6221fcf6b7d2.mvhn1irp-99488-e3fdc1cbfc.baseline/942d2679b87b96c612b4f2a425c3ccc5b6f3234f0cf589a8441602f866fbe277.source +0 -41
  1545. package/server/.mimosa/hook-state/sess_869e5bfd-07f4-4b6e-a991-6221fcf6b7d2.mvhn1irp-99488-e3fdc1cbfc.baseline/dd617a82339d2c61e49e28e416aabeb2fc100fb3cb1beca18d02dfb833214af6.source +0 -51
  1546. package/server/.mimosa/hook-status/sess_869e5bfd-07f4-4b6e-a991-6221fcf6b7d2-e67b6b91bf.json +0 -14
  1547. package/server/services/workshop/.mimosa/hook-state/sess_fed429fb-c8b7-4a50-bbd6-45afc580893f.json +0 -1
  1548. package/server/services/workshop/.mimosa/hook-status/sess_fed429fb-c8b7-4a50-bbd6-45afc580893f-e6b75bbfe6.json +0 -14
  1549. package/server/services/workshop/agents/omp-agent/supervision-history.ts +0 -38
  1550. package/server/services/workshop/aml/python/__pycache__/aml_eval.cpython-312.pyc +0 -0
  1551. package/server/services/workshop/aml/python/__pycache__/amlkit.cpython-312.pyc +0 -0
  1552. package/server/services/workshop/aml/python/__pycache__/train-example.cpython-312.pyc +0 -0
  1553. package/server/services/workshop/aml/python/__pycache__/train-hybrid-example.cpython-312.pyc +0 -0
  1554. package/server/services/workshop/optimization/python/.mimosa/hook-state/session_187ec97f45d4bd02369bbe94da527cf1.json +0 -1
  1555. package/server/services/workshop/optimization/python/.mimosa/hook-state/session_187ec97f45d4bd02369bbe94da527cf1.mvjqkcs6-68688-fb7131a89c.baseline/190a6772a4e43801737b4ba6072eb9d53d3099b5d8a9e6f57bc5e8592a26a6c4.source +0 -274
  1556. package/server/services/workshop/optimization/python/.mimosa/hook-status/session_187ec97f45d4bd02369bbe94da527cf1-01ed7f04fa.json +0 -14
  1557. package/server/services/workshop/optimization/python/__pycache__/problems.cpython-312.pyc +0 -0
  1558. /package/.output/public/_nuxt/{9j2J4k4w.js → 9j2J4k4w2.js} +0 -0
  1559. /package/.output/public/_nuxt/{BY3Lbz3h2.js → BY3Lbz3h.js} +0 -0
  1560. /package/.output/public/_nuxt/{Iub61dX92.js → Iub61dX9.js} +0 -0
  1561. /package/.output/public/_nuxt/{Q-JpBT032.js → Q-JpBT03.js} +0 -0
  1562. /package/.output/public/_nuxt/{dVw8IHY62.js → dVw8IHY6.js} +0 -0
  1563. /package/.output/public/_nuxt/{k9b520K-.js → k9b520K-2.js} +0 -0
@@ -1,2316 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * Bounded integration evidence for AgentWorkShop's registered `pi` harness.
4
- * Pi receives a deterministic OpenAI-compatible model response from a local
5
- * loopback fixture; the actual Pi CLI, Pi extension, AgentWorkShop bridge,
6
- * protected approval API, simulator, device readback, and run-tagged sampling
7
- * remain in the execution path. No external model or provider is used.
8
- */
9
- import { spawn, spawnSync } from 'node:child_process'
10
- import { createHash, randomBytes } from 'node:crypto'
11
- import { chmodSync, closeSync, copyFileSync, cpSync, existsSync, mkdirSync, mkdtempSync, openSync, readFileSync, readdirSync, symlinkSync, writeFileSync } from 'node:fs'
12
- import { createServer } from 'node:net'
13
- import { createServer as createHttpServer } from 'node:http'
14
- import { dirname, isAbsolute, join, relative, resolve, sep } from 'node:path'
15
- import { fileURLToPath } from 'node:url'
16
- import { setTimeout as delay } from 'node:timers/promises'
17
- import { resolveRunMode } from '../shared/config/home.mjs'
18
-
19
- const REPO = resolve(dirname(fileURLToPath(import.meta.url)), '..')
20
- const AW_PORT = 3997
21
- const SIM_PORT = 4020
22
- const MODEL_API_PORT = 4021
23
- const MQTT_PORT = 18840
24
- const OFFLINE_TSDB_PORT = 45321
25
- const OFFLINE_OBJECTSTORE_PORT = 45322
26
- const OFFLINE_APP_MQTT_QUEUE_PORT = 45323
27
- const FORBIDDEN_PORT = 4010
28
- const APP_BASE = `http://127.0.0.1:${AW_PORT}`
29
- const SIM_BASE = `http://127.0.0.1:${SIM_PORT}`
30
- const SIM_SOURCE = resolve(REPO, 'plc-node-simulator')
31
- const VERSION = JSON.parse(readFileSync(join(REPO, 'package.json'), 'utf8')).version
32
- const TAG = `pi${Date.now().toString(36)}`
33
- mkdirSync(join(REPO, '.omc'), { recursive: true })
34
- const ROOT = mkdtempSync(join(REPO, '.omc', 'registered-pi-paper-'))
35
- const HOME = join(ROOT, 'aw-home')
36
- const EVIDENCE_PATH = join(ROOT, 'evidence.json')
37
- const PI_AGENT_DIR = join(HOME, 'pi-agent')
38
- const OUTPUT_BASE = join(REPO, 'docs', 'audit', 'evidence', '2026-10-25-current-cross-scene')
39
- const OUTPUT_DIR = join(OUTPUT_BASE, `r23-pi-registered-harness-${new Date().toISOString().replace(/[-:.]/g, '').replace('T', '-').slice(0, 15)}-${randomBytes(3).toString('hex')}`)
40
- const PI_MODELS_PATH = join(PI_AGENT_DIR, 'models.json')
41
- const SIM_ROOT = join(ROOT, 'simulator')
42
- const SIM_LOG = join(ROOT, 'simulator.log')
43
- const APP_LOG = join(ROOT, 'agentworkshop.log')
44
- const EMPTY_DOTENV = join(HOME, 'empty.env')
45
- const ISOLATED_PROMPTS_DIR = join(HOME, 'prompts')
46
- const NUXT_CLI = join(REPO, 'node_modules', 'nuxt', 'bin', 'nuxt.mjs')
47
- const RAG_BRIDGE_DISABLED_BASE_URL = 'http://paper-harness-outbound-disabled.invalid'
48
- const SIM_LOG_FD = openSync(SIM_LOG, 'a')
49
- const APP_LOG_FD = openSync(APP_LOG, 'a')
50
- const HARNESS_MODE = 'pi-local-fixture'
51
- const PI_PROVIDER = 'agentworkshop-local'
52
- const PI_MODEL = 'aw-deterministic-paper-fixture'
53
- const PI_COMMAND = join(dirname(process.execPath), 'pi.cmd')
54
- const PI_CLI_PACKAGE_PATH = join(dirname(process.execPath), 'node_modules', '@mariozechner', 'pi-coding-agent', 'package.json')
55
- const PI_APPROVAL_TIMEOUT_MS = 180_000
56
- const PI_TASK_COMPLETION_TIMEOUT_MS = 180_000
57
- const PI_PROMPT_TIMEOUT_MS = 180_000
58
- // Keep the shared evidence helpers usable while this runner selects only the
59
- // local Pi fixture mode; no OMP CLI or external model is invoked.
60
- const REAL_OMP_PROVIDER = PI_PROVIDER
61
- const REAL_OMP_MODEL = PI_MODEL
62
- const REAL_OMP_TRIALS_PER_SCENE = 1
63
- const REAL_OMP_APPROVAL_TIMEOUT_MS = PI_APPROVAL_TIMEOUT_MS
64
- const REAL_OMP_TASK_COMPLETION_TIMEOUT_MS = PI_TASK_COMPLETION_TIMEOUT_MS
65
- const PI_API_TRACE_PATH = join(ROOT, 'pi-model-api-trace.json')
66
- const piApiTrace = []
67
- let piFixtureTarget = null
68
- let piApiServer
69
-
70
- const evidence = {
71
- schemaVersion: 1,
72
- experiment: {
73
- id: TAG,
74
- projectVersion: VERSION,
75
- campaign: 'Pi registered-harness local-fixture cross-scene E2E',
76
- harnessMode: HARNESS_MODE,
77
- provider: PI_PROVIDER,
78
- model: PI_MODEL,
79
- trialsPerScene: 1,
80
- runOutcomes: [],
81
- modelFixture: 'deterministic local OpenAI-compatible streaming API; fixture scripts one recipe_trial call and one complete_task call per scene; no LLM or external provider',
82
- startedAt: new Date().toISOString(),
83
- postTrialSnapshotDelaySeconds: 20,
84
- scenes: [],
85
- },
86
- isolation: {
87
- result: 'pending',
88
- awHome: 'fresh isolated AW_HOME',
89
- appBase: APP_BASE,
90
- simulatorBase: SIM_BASE,
91
- simulatorMqttLoopbackPort: MQTT_PORT,
92
- appMqttQueueOfflineProbePort: OFFLINE_APP_MQTT_QUEUE_PORT,
93
- explicitLoopbackOnly: true,
94
- externalLlmDisabled: true,
95
- modelApiBase: `http://127.0.0.1:${MODEL_API_PORT}/v1`,
96
- forbiddenServicePortExcluded: true,
97
- checks: [],
98
- },
99
- checks: [],
100
- status: 'running',
101
- }
102
-
103
- let appProcess
104
- let simProcess
105
- let currentStage = 'preflight'
106
- let currentScene
107
- let authToken
108
- let syntheticAdminId
109
- let isolatedPluginNames = []
110
- let expectedPluginNames = []
111
- const allowedEnabledPluginNames = ['rag-bridge']
112
- let projectPluginTreeAtPrepare
113
- let projectPromptTreeAtPrepare
114
- let promptTreeAtPrepare
115
- const generatedSessionPassword = randomBytes(32).toString('hex')
116
- const children = new Set()
117
- const allocatedDevicePorts = []
118
- const CHILD_OS_ENV_KEYS = process.platform === 'win32'
119
- ? ['PATH', 'PATHEXT', 'SystemRoot', 'WINDIR', 'TEMP', 'TMP', 'USERPROFILE', 'APPDATA', 'LOCALAPPDATA', 'HOMEDRIVE', 'HOMEPATH', 'ProgramData']
120
- : ['PATH', 'HOME', 'TMPDIR', 'TMP', 'TEMP', 'LANG', 'LC_ALL']
121
- const CHILD_EXTRA_ENV_KEYS = new Set(['SIM_PORT', 'MQTT_BROKER_PORT'])
122
- const RELEASE_CHECK_SUFFIXES = ['-process-stopped', '-port-released']
123
-
124
- function check(id, pass, detail = {}) {
125
- evidence.checks.push({ id, status: pass ? 'pass' : 'fail', detail })
126
- if (!pass) throw new Error(`check failed: ${id}`)
127
- }
128
-
129
- function noteIsolation(id, pass, detail = {}) {
130
- evidence.isolation.checks.push({ id, status: pass ? 'pass' : 'fail', detail })
131
- if (!pass) throw new Error(`isolation preflight failed: ${id}`)
132
- }
133
-
134
- function safeText(value, limit = 500) {
135
- let text = String(value ?? '')
136
- if (authToken) text = text.split(authToken).join('[REDACTED]')
137
- text = text.replace(/\but-[a-f\d]{32}\b/gi, '[REDACTED_TOKEN]')
138
- text = text.replace(/\bBearer\s+[^\s,;]+/gi, 'Bearer [REDACTED]')
139
- text = text.replace(/\b(?:api[_-]?key|access[_-]?token|client[_-]?secret|password|secret)\s*[:=]\s*["']?[^\s,"'}]+/gi, '[REDACTED_CREDENTIAL]')
140
- text = text.replace(/\bsk-[A-Za-z0-9_-]{16,}\b/g, '[REDACTED_CREDENTIAL]')
141
- return text.slice(0, limit)
142
- }
143
-
144
- function compactError(error) {
145
- const message = error instanceof Error ? error.message : String(error)
146
- return { name: error instanceof Error ? error.name : 'Error', message: safeText(message) }
147
- }
148
-
149
- async function readRequestJson(req) {
150
- const chunks = []
151
- let bytes = 0
152
- for await (const chunk of req) {
153
- bytes += chunk.length
154
- if (bytes > 2_000_000) throw new Error('model fixture rejected request larger than 2 MB')
155
- chunks.push(chunk)
156
- }
157
- return JSON.parse(Buffer.concat(chunks).toString('utf8'))
158
- }
159
-
160
- function sendSse(res, chunks) {
161
- res.writeHead(200, {
162
- 'content-type': 'text/event-stream; charset=utf-8',
163
- 'cache-control': 'no-cache, no-transform',
164
- connection: 'keep-alive',
165
- })
166
- for (const chunk of chunks) res.write(`data: ${JSON.stringify(chunk)}\n\n`)
167
- res.write('data: [DONE]\n\n')
168
- res.end()
169
- }
170
-
171
- function chatChunk(id, delta, finishReason = null, usage) {
172
- return {
173
- id,
174
- object: 'chat.completion.chunk',
175
- created: Math.floor(Date.now() / 1000),
176
- model: PI_MODEL,
177
- choices: [{ index: 0, delta, finish_reason: finishReason }],
178
- ...(usage ? { usage } : {}),
179
- }
180
- }
181
-
182
- async function startPiModelFixture() {
183
- piApiServer = createHttpServer(async (req, res) => {
184
- if (req.method !== 'POST' || req.url !== '/v1/chat/completions') {
185
- res.writeHead(404, { 'content-type': 'application/json' })
186
- res.end(JSON.stringify({ error: 'fixture route not found' }))
187
- return
188
- }
189
- try {
190
- const body = await readRequestJson(req)
191
- const target = piFixtureTarget
192
- const messages = Array.isArray(body.messages) ? body.messages : []
193
- const toolNames = (Array.isArray(body.tools) ? body.tools : [])
194
- .map(tool => String(tool?.function?.name ?? ''))
195
- .filter(Boolean)
196
- const roles = messages.map(message => String(message?.role ?? ''))
197
- const toolMessages = messages.filter(message => String(message?.role ?? '') === 'tool')
198
- const latestToolMessage = toolMessages.at(-1)
199
- const returnedToolContent = latestToolMessage?.content
200
- const returnedToolText = typeof returnedToolContent === 'string'
201
- ? returnedToolContent
202
- : JSON.stringify(returnedToolContent ?? '')
203
- const callIndex = target ? piApiTrace.filter(item => item.scene === target.scene).length : 0
204
- const requestId = `fixture-${target?.scene ?? 'unassigned'}-${callIndex + 1}`
205
- const requestEvidence = {
206
- requestId,
207
- scene: target?.scene ?? null,
208
- requestModel: safeText(body.model, 120),
209
- apiPath: req.url,
210
- loopbackPeer: req.socket.remoteAddress === '127.0.0.1' || req.socket.remoteAddress === '::ffff:127.0.0.1',
211
- apiKeyMatchesLocalFixture: req.headers.authorization === 'Bearer local-fixture-key-not-a-secret',
212
- streamRequested: body.stream === true,
213
- toolNames,
214
- messageRoles: roles,
215
- toolResultMessageCount: toolMessages.length,
216
- toolResultCallId: safeText(latestToolMessage?.tool_call_id ?? '', 120),
217
- toolResultText: toolMessages.length ? safeText(returnedToolText, 1200) : null,
218
- response: null,
219
- }
220
- if (!target || body.model !== PI_MODEL || !requestEvidence.loopbackPeer || !requestEvidence.apiKeyMatchesLocalFixture || body.stream !== true) {
221
- throw new Error('model fixture rejected a request outside the expected loopback Pi custom-provider configuration')
222
- }
223
- const id = `chatcmpl-${requestId}`
224
- if (callIndex === 0) {
225
- const promptText = JSON.stringify(messages)
226
- if (!toolNames.includes('recipe_trial')
227
- || roles.includes('tool')
228
- || !promptText.includes(target.recipeId)
229
- || !promptText.includes(target.nodeId)
230
- || !promptText.includes(String(target.value))) {
231
- throw new Error(`${target.scene} initial Pi request did not include the registered recipe_trial declaration and task identifiers`)
232
- }
233
- const args = JSON.stringify({
234
- recipe_id: target.recipeId,
235
- params: [{ node_id: target.nodeId, value: target.value }],
236
- hypothesis: 'Deterministic local fixture selection for a bounded simulator integration check.',
237
- })
238
- requestEvidence.response = { type: 'tool_call', toolName: 'recipe_trial', candidate: target.value }
239
- piApiTrace.push(requestEvidence)
240
- sendSse(res, [
241
- chatChunk(id, { role: 'assistant' }),
242
- chatChunk(id, { tool_calls: [{ index: 0, id: `call-${target.scene}`, type: 'function', function: { name: 'recipe_trial', arguments: args } }] }),
243
- chatChunk(id, {}, 'tool_calls', { prompt_tokens: 1, completion_tokens: 1, total_tokens: 2 }),
244
- ])
245
- return
246
- }
247
- if (callIndex === 1) {
248
- if (!roles.includes('tool') || !toolNames.includes('recipe_trial')) {
249
- throw new Error(`${target.scene} Pi follow-up request did not contain the platform tool result`)
250
- }
251
- if (toolMessages.length !== 1 || !requestEvidence.toolResultText || requestEvidence.toolResultCallId !== `call-${target.scene}`) {
252
- throw new Error(`${target.scene} Pi follow-up did not preserve exactly one non-empty platform tool result`)
253
- }
254
- requestEvidence.response = { type: 'tool_call', toolName: 'complete_task', taskId: target.taskId }
255
- piApiTrace.push(requestEvidence)
256
- sendSse(res, [
257
- chatChunk(id, { role: 'assistant' }),
258
- chatChunk(id, { tool_calls: [{ index: 0, id: `complete-${target.scene}`, type: 'function', function: { name: 'complete_task', arguments: JSON.stringify({
259
- task_id: target.taskId,
260
- summary: 'Completed the bounded local simulator integration check after the approved recipe trial returned its verified command result.',
261
- deliverable: `Task ${target.taskId}: the registered Pi host-tool bridge returned the recipe_trial result for candidate ${target.value}; this is integration evidence, not a process-improvement claim.`,
262
- }) } }] }),
263
- chatChunk(id, {}, 'tool_calls', { prompt_tokens: 1, completion_tokens: 1, total_tokens: 2 }),
264
- ])
265
- return
266
- }
267
- if (callIndex === 2) {
268
- if (!roles.includes('tool') || toolMessages.length !== 2 || !requestEvidence.toolResultText
269
- || requestEvidence.toolResultCallId !== `complete-${target.scene}`
270
- || !/COMPLETED/.test(requestEvidence.toolResultText)) {
271
- throw new Error(`${target.scene} Pi follow-up did not preserve the successful complete_task result`)
272
- }
273
- requestEvidence.response = { type: 'final_text_after_task_completion' }
274
- piApiTrace.push(requestEvidence)
275
- sendSse(res, [
276
- chatChunk(id, { role: 'assistant' }),
277
- chatChunk(id, { content: 'The bounded simulator integration task is complete. The approved recipe trial returned a verified command result; no process improvement is claimed.' }),
278
- chatChunk(id, {}, 'stop', { prompt_tokens: 1, completion_tokens: 1, total_tokens: 2 }),
279
- ])
280
- return
281
- }
282
- throw new Error(`${target.scene} made an unexpected extra local model request`)
283
- }
284
- catch (error) {
285
- const message = error instanceof Error ? error.message : String(error)
286
- res.writeHead(400, { 'content-type': 'application/json' })
287
- res.end(JSON.stringify({ error: { message: safeText(message, 300) } }))
288
- }
289
- })
290
- await new Promise((resolvePromise, reject) => {
291
- piApiServer.once('error', reject)
292
- piApiServer.listen(MODEL_API_PORT, '127.0.0.1', resolvePromise)
293
- })
294
- const address = piApiServer.address()
295
- if (!address || typeof address === 'string' || address.address !== '127.0.0.1' || address.port !== MODEL_API_PORT) {
296
- throw new Error('local Pi model fixture did not bind exactly to the approved IPv4 loopback endpoint')
297
- }
298
- noteIsolation('local-pi-model-api-bound-loopback', true, { host: address.address, port: address.port, route: '/v1/chat/completions' })
299
- }
300
-
301
- function assertLoopbackUrl(url, expectedPort) {
302
- const parsed = new URL(url)
303
- if (parsed.protocol !== 'http:' || parsed.hostname !== '127.0.0.1' || Number(parsed.port) !== expectedPort || Number(parsed.port) === FORBIDDEN_PORT) {
304
- throw new Error('network boundary rejected a non-approved loopback URL')
305
- }
306
- }
307
-
308
- function fixtureTracePath(sceneId) {
309
- if (!['cast-film', 'annealing'].includes(sceneId)) throw new Error('fixture trace scene is not approved')
310
- const root = resolve(ROOT)
311
- const tracePath = resolve(root, `fixture-${sceneId}.json`)
312
- const relativePath = relative(root, tracePath)
313
- if (isAbsolute(relativePath) || relativePath === '..' || relativePath.startsWith(`..${sep}`)) {
314
- throw new Error('fixture trace path escaped the experiment root')
315
- }
316
- return tracePath
317
- }
318
-
319
- async function assertFreeLoopback(port, label) {
320
- if (!Number.isInteger(port) || port < 1024 || port > 65535 || port === FORBIDDEN_PORT) {
321
- throw new Error(`port allocation rejected for ${label}`)
322
- }
323
- const server = createServer()
324
- await new Promise((resolvePromise, reject) => {
325
- server.once('error', reject)
326
- server.listen(port, '127.0.0.1', resolvePromise)
327
- })
328
- await new Promise(resolvePromise => server.close(resolvePromise))
329
- }
330
-
331
- async function preflight() {
332
- if (VERSION !== '0.8.0') throw new Error(`expected current package version 0.8.0; found ${safeText(VERSION, 80)}`)
333
- if (!existsSync(join(SIM_SOURCE, 'src', 'server', 'index.ts')) || !existsSync(join(SIM_SOURCE, 'node_modules')) || !existsSync(NUXT_CLI)
334
- || !existsSync(PI_COMMAND) || !existsSync(PI_CLI_PACKAGE_PATH)) {
335
- throw new Error('required registered Pi CLI, AgentWorkShop app, or simulator runtime is missing')
336
- }
337
- if (existsSync(HOME)) throw new Error('fresh AW_HOME path unexpectedly exists')
338
- const mode = resolveRunMode({ cwd: REPO, packageRoot: REPO, env: { AW_HOME: HOME, AW_MODE: 'home' } })
339
- if (mode.mode !== 'home' || resolve(mode.home) !== resolve(HOME) || resolve(mode.dataDir) !== resolve(join(HOME, 'data'))) {
340
- throw new Error('AW_HOME did not resolve to a new isolated home-mode data directory')
341
- }
342
- noteIsolation('fresh-home-mode-resolution', true, { mode: mode.mode, dataDir: mode.dataDir })
343
- for (const [label, port] of [['app', AW_PORT], ['simulator-http', SIM_PORT], ['local-model-api', MODEL_API_PORT], ['simulator-mqtt', MQTT_PORT], ['offline-app-mqtt-queue-probe', OFFLINE_APP_MQTT_QUEUE_PORT], ['offline-timescale-probe', OFFLINE_TSDB_PORT], ['offline-objectstore-probe', OFFLINE_OBJECTSTORE_PORT]]) {
344
- await assertFreeLoopback(port, label)
345
- noteIsolation(`${label}-free-loopback-port`, true, { port, host: '127.0.0.1' })
346
- }
347
- if ([AW_PORT, SIM_PORT, MODEL_API_PORT, MQTT_PORT].includes(FORBIDDEN_PORT)) {
348
- throw new Error('forbidden service port appeared in explicit service configuration')
349
- }
350
- noteIsolation('project-version-and-local-inputs', true, {
351
- version: VERSION,
352
- simulatorSourcePresent: true,
353
- piCommandPresent: true,
354
- piVersion: JSON.parse(readFileSync(PI_CLI_PACKAGE_PATH, 'utf8')).version,
355
- modelApiBoundToLoopback: true,
356
- noExternalModelCredentialsRequired: true,
357
- nuxtCliPresent: true,
358
- noUserOrBusinessArchiveInput: true,
359
- })
360
- noteIsolation('strict-child-environment-allowlist', true, {
361
- osKeys: CHILD_OS_ENV_KEYS,
362
- harnessMode: HARNESS_MODE,
363
- piAgentDirectoryIsolated: true,
364
- piOfflineMode: true,
365
- noStorageServiceEnvironment: true,
366
- })
367
- }
368
-
369
- function cleanChildEnv(extra = {}) {
370
- const env = {}
371
- for (const key of CHILD_OS_ENV_KEYS) {
372
- if (process.env[key] !== undefined) env[key] = process.env[key]
373
- }
374
- env.AW_HOME = HOME
375
- env.AW_MODE = 'home'
376
- env.AW_PROMPTS_DIR = ISOLATED_PROMPTS_DIR
377
- env.HOME = HOME
378
- env.PI_CODING_AGENT_DIR = PI_AGENT_DIR
379
- env.PI_CODING_AGENT_SESSION_DIR = join(PI_AGENT_DIR, 'sessions')
380
- env.PI_OFFLINE = '1'
381
- env.NUXT_SESSION_PASSWORD = generatedSessionPassword
382
- env.NO_PROXY = '127.0.0.1,localhost'
383
- env.no_proxy = '127.0.0.1,localhost'
384
- for (const [key, value] of Object.entries(extra)) {
385
- if (!CHILD_EXTRA_ENV_KEYS.has(key)) throw new Error(`child environment rejected unsupported override ${key}`)
386
- env[key] = String(value)
387
- }
388
- return env
389
- }
390
-
391
- function gitText(cwd, args) {
392
- const result = spawnSync('git', args, {
393
- cwd,
394
- windowsHide: true,
395
- encoding: 'utf8',
396
- stdio: ['ignore', 'pipe', 'pipe'],
397
- env: cleanChildEnv(),
398
- })
399
- if (result.error || result.status !== 0) {
400
- throw new Error(`could not capture source identity: ${safeText(result.stderr || result.error?.message || result.status)}`)
401
- }
402
- return String(result.stdout ?? '').trim()
403
- }
404
-
405
- function hashGitFiles(cwd, roots) {
406
- const names = gitText(cwd, ['ls-files', '-co', '--exclude-standard', '--', ...roots])
407
- .split(/\r?\n/).filter(Boolean).sort()
408
- if (names.length === 0) throw new Error(`source identity has no files under ${roots.join(', ')}`)
409
- return hashFileList(cwd, names)
410
- }
411
-
412
- function hashFileList(cwd, names) {
413
- const hash = createHash('sha256')
414
- for (const name of names) {
415
- hash.update(name.replaceAll('\\', '/') + '\0')
416
- hash.update(readFileSync(join(cwd, name)))
417
- hash.update('\0')
418
- }
419
- return { sha256: hash.digest('hex'), fileCount: names.length }
420
- }
421
-
422
- function hashDirectoryTree(root) {
423
- if (!existsSync(root)) return hashFileList(root, [])
424
- const names = []
425
- const visit = (directory) => {
426
- for (const entry of readdirSync(directory, { withFileTypes: true })) {
427
- const absolute = join(directory, entry.name)
428
- const name = relative(root, absolute).replaceAll('\\', '/')
429
- if (entry.isSymbolicLink()) throw new Error(`source identity rejected symlink in plugin tree: ${name}`)
430
- if (entry.isDirectory()) visit(absolute)
431
- else if (entry.isFile()) names.push(name)
432
- }
433
- }
434
- visit(root)
435
- names.sort()
436
- return hashFileList(root, names)
437
- }
438
-
439
- function pluginNamesUnder(root) {
440
- if (!existsSync(root)) return []
441
- return readdirSync(root, { withFileTypes: true })
442
- .filter(entry => entry.isDirectory() && existsSync(join(root, entry.name, 'index.mjs')))
443
- .map(entry => entry.name)
444
- .sort()
445
- }
446
-
447
- function captureSourceIdentity() {
448
- const appRoots = ['app', 'server', 'shared', 'mcp', 'cli', 'sdk', 'i18n', 'public', 'tsconfig.json', 'package.json', 'pnpm-lock.yaml', 'nuxt.config.ts', 'config.yml']
449
- const simulatorRoots = ['src', 'package.json', 'package-lock.json']
450
- const simulatorSourceFiles = gitText(SIM_SOURCE, ['ls-files', '-co', '--exclude-standard', '--', ...simulatorRoots])
451
- .split(/\r?\n/).filter(Boolean).sort()
452
- const executedSimulatorFiles = simulatorSourceFiles.filter(name => existsSync(join(SIM_ROOT, name)))
453
- if (!executedSimulatorFiles.includes('src/server/index.ts') || !executedSimulatorFiles.includes('package.json')) {
454
- throw new Error('executed simulator copy is missing required source files for provenance')
455
- }
456
- const projectPluginTree = hashDirectoryTree(join(REPO, '.AgentWorkShop', 'plugins'))
457
- if (projectPluginTree.sha256 !== projectPluginTreeAtPrepare?.sha256) {
458
- throw new Error('project plugin source changed after isolation was prepared')
459
- }
460
- const promptTree = hashDirectoryTree(ISOLATED_PROMPTS_DIR)
461
- if (promptTree.sha256 !== promptTreeAtPrepare?.sha256) {
462
- throw new Error('isolated prompt assets changed after isolation was prepared')
463
- }
464
- const piCliVersion = JSON.parse(readFileSync(PI_CLI_PACKAGE_PATH, 'utf8')).version
465
- return {
466
- recordedAt: new Date().toISOString(),
467
- nodeVersion: process.version,
468
- platform: process.platform,
469
- architecture: process.arch,
470
- app: {
471
- version: VERSION,
472
- gitHead: gitText(REPO, ['rev-parse', 'HEAD']),
473
- sourceTree: hashGitFiles(REPO, appRoots),
474
- workingTreeStatus: gitText(REPO, ['status', '--porcelain', '--', ...appRoots]),
475
- packageManifestSha256: createHash('sha256').update(readFileSync(join(REPO, 'package.json'))).digest('hex'),
476
- lockfileSha256: createHash('sha256').update(readFileSync(join(REPO, 'pnpm-lock.yaml'))).digest('hex'),
477
- projectPluginTree,
478
- projectPluginNames: pluginNamesUnder(join(REPO, '.AgentWorkShop', 'plugins')),
479
- },
480
- pluginIsolation: {
481
- disabledNames: isolatedPluginNames,
482
- enabledAllowlist: allowedEnabledPluginNames,
483
- setupExpectedForOtherPlugins: false,
484
- disabledStatePath: 'AW_HOME/plugins-state.json',
485
- projectPluginNames: pluginNamesUnder(join(REPO, '.AgentWorkShop', 'plugins')),
486
- projectPluginTree,
487
- },
488
- promptIsolation: {
489
- sourceDirectory: 'repository/.AgentWorkShop/prompts',
490
- isolatedDirectory: 'AW_HOME/prompts',
491
- sourceTree: projectPromptTreeAtPrepare,
492
- runtimeTree: promptTree,
493
- },
494
- experimentScriptSha256: createHash('sha256').update(readFileSync(fileURLToPath(import.meta.url))).digest('hex'),
495
- registeredHarness: {
496
- mode: HARNESS_MODE,
497
- harness: 'pi',
498
- command: PI_COMMAND,
499
- piCliVersion,
500
- provider: PI_PROVIDER,
501
- model: PI_MODEL,
502
- isolatedModelConfigSha256: createHash('sha256').update(readFileSync(PI_MODELS_PATH)).digest('hex'),
503
- localModelFixtureSha256: createHash('sha256').update(readFileSync(fileURLToPath(import.meta.url))).digest('hex'),
504
- externalCredentialsUsed: false,
505
- },
506
- simulator: {
507
- gitlinkHead: gitText(REPO, ['rev-parse', 'HEAD:plc-node-simulator']),
508
- gitHead: gitText(SIM_SOURCE, ['rev-parse', 'HEAD']),
509
- sourceTree: hashGitFiles(SIM_SOURCE, simulatorRoots),
510
- workingTreeStatus: gitText(SIM_SOURCE, ['status', '--porcelain', '--', ...simulatorRoots]),
511
- executedTree: hashFileList(SIM_ROOT, executedSimulatorFiles),
512
- lockfileSha256: createHash('sha256').update(readFileSync(join(SIM_SOURCE, 'package-lock.json'))).digest('hex'),
513
- copyPatch: 'bind copied simulator HTTP and MQTT listeners to 127.0.0.1 and remap only their ports; source script hash records the transformation',
514
- },
515
- }
516
- }
517
-
518
- function prepareIsolatedHome() {
519
- mkdirSync(join(HOME, 'data'), { recursive: true })
520
- mkdirSync(join(PI_AGENT_DIR, 'sessions'), { recursive: true })
521
- const piModels = {
522
- providers: {
523
- [PI_PROVIDER]: {
524
- name: 'AgentWorkShop loopback deterministic fixture',
525
- baseUrl: `http://127.0.0.1:${MODEL_API_PORT}/v1`,
526
- apiKey: 'local-fixture-key-not-a-secret',
527
- api: 'openai-completions',
528
- models: [{
529
- id: PI_MODEL,
530
- name: 'AgentWorkShop deterministic paper fixture',
531
- reasoning: false,
532
- input: ['text'],
533
- cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
534
- contextWindow: 64000,
535
- maxTokens: 2048,
536
- }],
537
- },
538
- },
539
- }
540
- writeFileSync(PI_MODELS_PATH, `${JSON.stringify(piModels, null, 2)}\n`, 'utf8')
541
- assertLoopbackUrl(piModels.providers[PI_PROVIDER].baseUrl, MODEL_API_PORT)
542
- noteIsolation('pi-custom-provider-isolated-to-local-fixture', true, {
543
- configPath: 'AW_HOME/pi-agent/models.json',
544
- provider: PI_PROVIDER,
545
- model: PI_MODEL,
546
- api: 'openai-completions',
547
- baseUrl: piModels.providers[PI_PROVIDER].baseUrl,
548
- apiKeyValueRecorded: false,
549
- externalCredentialsUsed: false,
550
- })
551
- copyFileSync(join(REPO, 'config.yml'), join(HOME, 'config.yml'))
552
- const overrides = {
553
- 'daq.startInfrastructure': 'never',
554
- 'daq.mqtt.host': '127.0.0.1',
555
- 'daq.mqtt.port': OFFLINE_APP_MQTT_QUEUE_PORT,
556
- 'daq.timescale.host': '127.0.0.1',
557
- 'daq.timescale.port': OFFLINE_TSDB_PORT,
558
- 'daq.objectstore.host': '127.0.0.1',
559
- 'daq.objectstore.port': OFFLINE_OBJECTSTORE_PORT,
560
- 'plugins.rag-bridge.base_url': RAG_BRIDGE_DISABLED_BASE_URL,
561
- }
562
- const runtimeSettingsPath = join(HOME, 'runtime-settings.json')
563
- writeFileSync(runtimeSettingsPath, `${JSON.stringify({ version: 1, updatedAt: new Date().toISOString(), overrides }, null, 2)}\n`, 'utf8')
564
- const savedOverrides = JSON.parse(readFileSync(runtimeSettingsPath, 'utf8')).overrides
565
- if (savedOverrides?.['plugins.rag-bridge.base_url'] !== overrides['plugins.rag-bridge.base_url']) {
566
- throw new Error('isolated runtime settings did not preserve the rag-bridge outbound-disable host guard setting')
567
- }
568
- const ragBridgeKvDir = join(HOME, 'data', 'plugins', 'rag-bridge')
569
- mkdirSync(ragBridgeKvDir, { recursive: true })
570
- const ragBridgeKvPath = join(ragBridgeKvDir, 'kv.json')
571
- writeFileSync(ragBridgeKvPath, `${JSON.stringify({ 'kb.base_url': RAG_BRIDGE_DISABLED_BASE_URL }, null, 2)}\n`, 'utf8')
572
- const savedRagBridgeKv = JSON.parse(readFileSync(ragBridgeKvPath, 'utf8'))
573
- if (savedRagBridgeKv?.['kb.base_url'] !== RAG_BRIDGE_DISABLED_BASE_URL) {
574
- throw new Error('isolated rag-bridge KV fallback did not preserve the outbound-disable host guard setting')
575
- }
576
- const projectPromptsRoot = join(REPO, '.AgentWorkShop', 'prompts')
577
- if (!existsSync(projectPromptsRoot)) throw new Error('project prompt source directory is missing')
578
- cpSync(projectPromptsRoot, ISOLATED_PROMPTS_DIR, { recursive: true })
579
- projectPromptTreeAtPrepare = hashDirectoryTree(projectPromptsRoot)
580
- promptTreeAtPrepare = hashDirectoryTree(ISOLATED_PROMPTS_DIR)
581
- if (projectPromptTreeAtPrepare.sha256 !== promptTreeAtPrepare.sha256) {
582
- throw new Error('isolated prompt copy differs from the repository prompt source')
583
- }
584
- writeFileSync(EMPTY_DOTENV, '', 'utf8')
585
- const builtinPlugins = pluginNamesUnder(join(REPO, 'server', 'plugins-builtin'))
586
- const projectPluginsRoot = join(REPO, '.AgentWorkShop', 'plugins')
587
- const projectPlugins = pluginNamesUnder(projectPluginsRoot)
588
- const userPlugins = pluginNamesUnder(join(HOME, 'plugins'))
589
- expectedPluginNames = [...new Set([...builtinPlugins, ...projectPlugins, ...userPlugins])].sort()
590
- isolatedPluginNames = expectedPluginNames.filter(name => !allowedEnabledPluginNames.includes(name))
591
- projectPluginTreeAtPrepare = hashDirectoryTree(projectPluginsRoot)
592
- const pluginStatePath = join(HOME, 'plugins-state.json')
593
- writeFileSync(pluginStatePath, `${JSON.stringify({ version: 1, updatedAt: new Date().toISOString(), disabled: isolatedPluginNames }, null, 2)}\n`, 'utf8')
594
- const savedPluginState = JSON.parse(readFileSync(pluginStatePath, 'utf8'))
595
- if (JSON.stringify([...savedPluginState.disabled].sort()) !== JSON.stringify(isolatedPluginNames)) {
596
- throw new Error('isolated plugin state did not disable every discovered plugin')
597
- }
598
- noteIsolation('isolated-runtime-config', true, {
599
- configRoot: 'fresh isolated AW_HOME',
600
- startInfrastructure: overrides['daq.startInfrastructure'],
601
- simulatorMqttBroker: `127.0.0.1:${MQTT_PORT}`,
602
- appMqttQueueProbe: `127.0.0.1:${OFFLINE_APP_MQTT_QUEUE_PORT}`,
603
- offlineTimescaleProbe: `127.0.0.1:${OFFLINE_TSDB_PORT}`,
604
- offlineObjectstoreProbe: `127.0.0.1:${OFFLINE_OBJECTSTORE_PORT}`,
605
- ragBridgeOutboundGuardSetting: 'plugins.rag-bridge.base_url',
606
- ragBridgeOutboundGuardConfigPresent: true,
607
- ragBridgeOutboundGuardKvFallbackPresent: true,
608
- emptyDotenv: true,
609
- repoDotenvBypassed: true,
610
- })
611
- noteIsolation('pre-existing-plugin-scopes-disabled', true, {
612
- builtinNames: builtinPlugins,
613
- projectNames: projectPlugins,
614
- userNames: userPlugins,
615
- disabledStatePath: 'AW_HOME/plugins-state.json',
616
- projectPluginTreeSha256: projectPluginTreeAtPrepare.sha256,
617
- enabledPluginAllowlist: allowedEnabledPluginNames,
618
- })
619
- noteIsolation('project-prompt-assets-isolated', true, {
620
- sourceDirectory: 'repository/.AgentWorkShop/prompts',
621
- isolatedDirectory: 'AW_HOME/prompts',
622
- sourceTreeSha256: projectPromptTreeAtPrepare.sha256,
623
- runtimeTreeSha256: promptTreeAtPrepare.sha256,
624
- awPromptsDir: 'AW_HOME/prompts',
625
- })
626
- }
627
-
628
- async function assertPluginIsolation() {
629
- const expectedNames = expectedPluginNames
630
- let plugins = []
631
- for (let attempt = 0; attempt < 40; attempt++) {
632
- const result = requireSuccess(await app('GET', '/api/workshop/plugins'), 'isolated plugin manifest')
633
- plugins = Array.isArray(result.plugins) ? result.plugins : []
634
- const actualNames = plugins.map(plugin => plugin.name).sort()
635
- if (JSON.stringify(actualNames) === JSON.stringify(expectedNames)) {
636
- const enabledNames = plugins.filter(plugin => plugin.enabled === true).map(plugin => plugin.name).sort()
637
- const enabledMatchesAllowlist = JSON.stringify(enabledNames) === JSON.stringify([...allowedEnabledPluginNames].sort())
638
- const statesMatchPolicy = plugins.every(plugin => allowedEnabledPluginNames.includes(plugin.name)
639
- ? plugin.enabled === true
640
- : plugin.enabled === false)
641
- check('only-outbound-disabled-rag-bridge-enabled', enabledMatchesAllowlist && statesMatchPolicy, {
642
- names: actualNames,
643
- enabledNames,
644
- disabledNames: plugins.filter(plugin => plugin.enabled === false).map(plugin => plugin.name).sort(),
645
- invalidStateNames: plugins.filter(plugin => typeof plugin.enabled !== 'boolean').map(plugin => plugin.name),
646
- })
647
- return
648
- }
649
- await delay(250)
650
- }
651
- throw new Error(`isolated plugin manifest differed from the expected built-in/user set: ${plugins.map(plugin => plugin.name).sort().join(', ')}`)
652
- }
653
-
654
- function spawnLogged(command, args, { cwd = REPO, env = cleanChildEnv(), logFd, label }) {
655
- const child = spawn(command, args, {
656
- cwd,
657
- env,
658
- stdio: ['ignore', logFd, logFd],
659
- windowsHide: true,
660
- detached: process.platform !== 'win32',
661
- })
662
- child.label = label
663
- children.add(child)
664
- child.once('exit', () => children.delete(child))
665
- child.once('error', () => children.delete(child))
666
- return child
667
- }
668
-
669
- async function waitForExit(child, timeoutMs = 8_000) {
670
- if (!child || child.exitCode !== null || child.signalCode !== null) return
671
- await Promise.race([
672
- new Promise(resolvePromise => child.once('exit', resolvePromise)),
673
- delay(timeoutMs),
674
- ])
675
- }
676
-
677
- function processGroupExists(pid) {
678
- try {
679
- process.kill(-pid, 0)
680
- return true
681
- }
682
- catch (error) {
683
- if (error?.code === 'ESRCH') return false
684
- if (error?.code === 'EPERM') return true
685
- throw error
686
- }
687
- }
688
-
689
- function windowsProcessExists(pid) {
690
- const result = spawnSync('tasklist.exe', ['/FI', `PID eq ${pid}`, '/FO', 'CSV', '/NH'], {
691
- windowsHide: true,
692
- encoding: 'utf8',
693
- stdio: ['ignore', 'pipe', 'ignore'],
694
- env: cleanChildEnv(),
695
- })
696
- if (result.error || result.status !== 0) return null
697
- return (result.stdout ?? '').split(/\r?\n/).some((line) => {
698
- const columns = line.match(/^"(?:[^"]|"")*","(\d+)"(?:,|$)/)
699
- return columns?.[1] === String(pid)
700
- })
701
- }
702
-
703
- async function stopProcessTree(child, label) {
704
- if (!child?.pid) return false
705
- const wasAlreadyExited = child.exitCode !== null || child.signalCode !== null
706
- let terminationStatus = null
707
- try {
708
- if (process.platform === 'win32' && child.pid) {
709
- const result = spawnSync('taskkill.exe', ['/PID', String(child.pid), '/T', '/F'], { windowsHide: true, stdio: 'ignore', env: cleanChildEnv() })
710
- terminationStatus = result.error ? 'spawn-error' : result.status
711
- }
712
- else if (process.platform !== 'win32' && child.pid) {
713
- process.kill(-child.pid, 'SIGTERM')
714
- }
715
- }
716
- catch { /* a process may have already exited */ }
717
- await waitForExit(child)
718
- if (process.platform !== 'win32' && processGroupExists(child.pid)) {
719
- try {
720
- process.kill(-child.pid, 'SIGKILL')
721
- terminationStatus = 'SIGKILL'
722
- }
723
- catch { /* already gone */ }
724
- }
725
- else if (process.platform === 'win32' && windowsProcessExists(child.pid) === true) {
726
- const result = spawnSync('taskkill.exe', ['/PID', String(child.pid), '/T', '/F'], { windowsHide: true, stdio: 'ignore', env: cleanChildEnv() })
727
- terminationStatus = result.error ? 'spawn-error' : result.status
728
- }
729
- await waitForExit(child, 2_000)
730
- let treePresent
731
- if (process.platform === 'win32') treePresent = windowsProcessExists(child.pid)
732
- else {
733
- const deadline = Date.now() + 3_000
734
- do {
735
- treePresent = processGroupExists(child.pid)
736
- if (!treePresent) break
737
- await delay(100)
738
- } while (Date.now() < deadline)
739
- }
740
- const pass = !wasAlreadyExited && treePresent === false && (process.platform !== 'win32' || terminationStatus === 0)
741
- evidence.checks.push({
742
- id: `${label}-process-stopped`,
743
- status: pass ? 'pass' : 'fail',
744
- detail: { pid: child.pid, terminationStatus, processTreePresentAfterCleanup: treePresent, rootWasAlreadyExited: wasAlreadyExited },
745
- })
746
- return pass
747
- }
748
-
749
- function buildHarnessShim() {
750
- if (process.platform === 'win32') {
751
- const compiler = [
752
- join(process.env.WINDIR || 'C:\\Windows', 'Microsoft.NET', 'Framework64', 'v4.0.30319', 'csc.exe'),
753
- join(process.env.WINDIR || 'C:\\Windows', 'Microsoft.NET', 'Framework', 'v4.0.30319', 'csc.exe'),
754
- ].find(existsSync)
755
- if (!compiler) throw new Error('Windows C# compiler unavailable; cannot safely launch a registered fixture executable')
756
- const source = join(ROOT, 'omp-fixture-shim.cs')
757
- wrapperPath = join(ROOT, 'omp-fixture-shim.exe')
758
- writeFileSync(source, String.raw`using System;
759
- using System.Diagnostics;
760
- using System.IO;
761
- using System.Linq;
762
- using System.Text;
763
- using System.Threading;
764
- class OmpFixtureShim {
765
- static string Quote(string value) {
766
- var result = new StringBuilder("\"");
767
- int backslashes = 0;
768
- foreach (char c in value) {
769
- if (c == '\\') { backslashes++; continue; }
770
- if (c == '"') {
771
- result.Append('\\', backslashes * 2 + 1);
772
- result.Append('"');
773
- }
774
- else {
775
- result.Append('\\', backslashes);
776
- result.Append(c);
777
- }
778
- backslashes = 0;
779
- }
780
- result.Append('\\', backslashes * 2);
781
- result.Append('"');
782
- return result.ToString();
783
- }
784
- static void Copy(Stream source, Stream destination) {
785
- byte[] buffer = new byte[4096];
786
- int count;
787
- while ((count = source.Read(buffer, 0, buffer.Length)) > 0) {
788
- destination.Write(buffer, 0, count);
789
- destination.Flush();
790
- }
791
- }
792
- static int Main(string[] args) {
793
- string node = Environment.GetEnvironmentVariable("AW_PAPER_FIXTURE_NODE");
794
- string script = Environment.GetEnvironmentVariable("AW_PAPER_FIXTURE_SCRIPT");
795
- if (String.IsNullOrWhiteSpace(node) || String.IsNullOrWhiteSpace(script)) return 125;
796
- var psi = new ProcessStartInfo(node);
797
- psi.UseShellExecute = false;
798
- psi.CreateNoWindow = true;
799
- psi.RedirectStandardInput = true;
800
- psi.RedirectStandardOutput = true;
801
- psi.RedirectStandardError = true;
802
- psi.Arguments = Quote(script) + " " + String.Join(" ", args.Skip(2).Select(Quote));
803
- using (var child = Process.Start(psi)) {
804
- if (child == null) return 126;
805
- var stdin = new Thread(() => {
806
- try {
807
- Copy(Console.OpenStandardInput(), child.StandardInput.BaseStream);
808
- }
809
- finally {
810
- child.StandardInput.Close();
811
- }
812
- });
813
- var stdout = new Thread(() => Copy(child.StandardOutput.BaseStream, Console.OpenStandardOutput()));
814
- var stderr = new Thread(() => Copy(child.StandardError.BaseStream, Console.OpenStandardError()));
815
- stdin.IsBackground = true;
816
- stdout.IsBackground = true;
817
- stderr.IsBackground = true;
818
- stdin.Start();
819
- stdout.Start();
820
- stderr.Start();
821
- child.WaitForExit();
822
- stdout.Join();
823
- stderr.Join();
824
- return child.ExitCode;
825
- }
826
- }
827
- }`.replace(/\n/g, '\n'), 'utf8')
828
- const result = spawnSync(compiler, ['/nologo', '/target:exe', `/out:${wrapperPath}`, source], { cwd: ROOT, windowsHide: true, encoding: 'utf8', timeout: 30_000, env: cleanChildEnv() })
829
- if (result.error || result.status !== 0 || !existsSync(wrapperPath)) {
830
- throw new Error(`could not compile isolated OMP fixture shim: ${safeText(result.stderr || result.stdout || result.error?.message || result.status)}`)
831
- }
832
- return wrapperPath
833
- }
834
- if (process.platform === 'linux' || process.platform === 'darwin') {
835
- wrapperPath = join(ROOT, 'omp-fixture-shim')
836
- writeFileSync(wrapperPath, '#!/bin/sh\nshift 2\nexec "$AW_PAPER_FIXTURE_NODE" "$AW_PAPER_FIXTURE_SCRIPT" "$@"\n', 'utf8')
837
- chmodSync(wrapperPath, 0o755)
838
- return wrapperPath
839
- }
840
- throw new Error(`unsupported fixture shim platform ${process.platform}`)
841
- }
842
-
843
- function extractPayload(body) {
844
- return body && typeof body === 'object' && Object.prototype.hasOwnProperty.call(body, 'data') ? body.data : body
845
- }
846
-
847
- async function request(base, expectedPort, method, path, body, { token, timeoutMs = 10_000 } = {}) {
848
- assertLoopbackUrl(base, expectedPort)
849
- if (!path.startsWith('/api/')) throw new Error('API path boundary rejected')
850
- const response = await fetch(`${base}${path}`, {
851
- method,
852
- headers: {
853
- ...(body === undefined ? {} : { 'content-type': 'application/json' }),
854
- ...(token ? { authorization: `Bearer ${token}` } : {}),
855
- },
856
- ...(body === undefined ? {} : { body: JSON.stringify(body) }),
857
- signal: AbortSignal.timeout(timeoutMs),
858
- })
859
- const parsed = await response.json().catch(() => null)
860
- return { status: response.status, body: parsed, data: extractPayload(parsed) }
861
- }
862
-
863
- const app = (method, path, body, opts = {}) => request(APP_BASE, AW_PORT, method, path, body, { token: opts.token ?? authToken, timeoutMs: opts.timeoutMs })
864
- const sim = (method, path, body) => request(SIM_BASE, SIM_PORT, method, path, body, { timeoutMs: 8_000 })
865
-
866
- function requireSuccess(result, label, status = 200) {
867
- if (result.status !== status) {
868
- const payload = result.body && typeof result.body === 'object' ? result.body : {}
869
- throw new Error(`${label} returned HTTP ${result.status}: ${safeText(payload.message || payload.statusMessage || payload.code || 'no response detail')}`)
870
- }
871
- return result.data
872
- }
873
-
874
- async function bootSimulator() {
875
- mkdirSync(SIM_ROOT, { recursive: true })
876
- cpSync(join(SIM_SOURCE, 'src'), join(SIM_ROOT, 'src'), { recursive: true })
877
- cpSync(join(SIM_SOURCE, 'package.json'), join(SIM_ROOT, 'package.json'))
878
- const simulatorEntry = join(SIM_ROOT, 'src', 'server', 'index.ts')
879
- const originalSource = readFileSync(simulatorEntry, 'utf8')
880
- const listenCall = 'server.listen(PORT, () => resolve())'
881
- const brokerCall = 'await startBroker(Number(process.env.MQTT_BROKER_PORT ?? 18830))'
882
- if (originalSource.split(listenCall).length !== 2) throw new Error('simulator copied source did not contain exactly one expected listener call')
883
- if (originalSource.split(brokerCall).length !== 2) throw new Error('simulator copied source did not contain exactly one expected broker startup call')
884
- const loopbackListenCall = `server.listen(PORT, '127.0.0.1', () => {
885
- const boundAddress = server.address()
886
- if (!boundAddress || typeof boundAddress === 'string' || boundAddress.address !== '127.0.0.1' || boundAddress.port !== PORT) {
887
- console.error('[paper-isolation] simulator listener address verification failed')
888
- server.close(() => process.exit(70))
889
- return
890
- }
891
- console.log('[paper-isolation] listener=' + boundAddress.address + ':' + boundAddress.port)
892
- resolve()
893
- })`
894
- const loopbackSource = originalSource
895
- .replace(listenCall, loopbackListenCall)
896
- .replace(brokerCall, `await startBroker(Number(process.env.MQTT_BROKER_PORT ?? 18830), '127.0.0.1')`)
897
- writeFileSync(simulatorEntry, loopbackSource, 'utf8')
898
- const modules = join(SIM_SOURCE, 'node_modules')
899
- symlinkSync(modules, join(SIM_ROOT, 'node_modules'), process.platform === 'win32' ? 'junction' : 'dir')
900
- simProcess = spawnLogged(process.execPath, [join(REPO, 'node_modules', 'tsx', 'dist', 'cli.mjs'), join(SIM_ROOT, 'src', 'server', 'index.ts')], {
901
- cwd: SIM_ROOT,
902
- logFd: SIM_LOG_FD,
903
- label: 'simulator',
904
- env: cleanChildEnv({ SIM_PORT: String(SIM_PORT), MQTT_BROKER_PORT: String(MQTT_PORT) }),
905
- })
906
- for (let i = 0; i < 50; i++) {
907
- if (simProcess.exitCode !== null) throw new Error(`simulator exited during startup (code ${simProcess.exitCode})`)
908
- try {
909
- const result = await sim('GET', '/api/nodes')
910
- if (result.status === 200) {
911
- const data = result.data
912
- const expectedListener = `[paper-isolation] listener=127.0.0.1:${SIM_PORT}`
913
- const simulatorLog = readFileSync(SIM_LOG, 'utf8')
914
- const expectedBroker = `[mqtt-broker] 内置 broker 就绪 mqtt://127.0.0.1:${MQTT_PORT}`
915
- if (!simulatorLog.includes(expectedListener)) throw new Error('simulator did not report the verified 127.0.0.1 HTTP listener address')
916
- if (!simulatorLog.includes(expectedBroker) || simulatorLog.includes('内置 broker 启动失败')) {
917
- throw new Error('simulator did not confirm its embedded loopback MQTT broker before application startup')
918
- }
919
- noteIsolation('simulator-listener-address-verified', true, { address: '127.0.0.1', port: SIM_PORT, copiedSourceOnly: true })
920
- noteIsolation('simulator-mqtt-broker-loopback-ready', true, { address: '127.0.0.1', port: MQTT_PORT, brokerStartupConfirmed: true })
921
- noteIsolation('simulator-local-http-ready', true, { version: 'local repository source', port: SIM_PORT, host: '127.0.0.1' })
922
- return data
923
- }
924
- }
925
- catch { /* the local simulator is still starting */ }
926
- await delay(400)
927
- }
928
- throw new Error('isolated simulator startup timed out')
929
- }
930
-
931
- function normalizeLocalNetworkConfig(value, portMap, key = '') {
932
- if (Array.isArray(value)) return value.map(item => normalizeLocalNetworkConfig(item, portMap, key))
933
- if (!value || typeof value !== 'object') {
934
- if (typeof value !== 'string') return value
935
- if (/^[a-z][a-z\d+.-]*:\/\//i.test(value)) {
936
- const parsed = new URL(value)
937
- if (!['127.0.0.1', 'localhost', '::1'].includes(parsed.hostname)) throw new Error('simulator preset contains a non-loopback endpoint')
938
- if (parsed.port && portMap.has(Number(parsed.port))) parsed.port = String(portMap.get(Number(parsed.port)))
939
- parsed.hostname = '127.0.0.1'
940
- return parsed.toString()
941
- }
942
- if (/(?:host|hostname|ip|address)$/i.test(key)) return '127.0.0.1'
943
- return value
944
- }
945
- const out = {}
946
- for (const [childKey, childValue] of Object.entries(value)) {
947
- if (/^port$/i.test(childKey) && typeof childValue === 'number' && portMap.has(childValue)) {
948
- out[childKey] = portMap.get(childValue)
949
- }
950
- else if (/(?:host|hostname|ip|address)$/i.test(childKey) && typeof childValue === 'string') {
951
- out[childKey] = '127.0.0.1'
952
- }
953
- else {
954
- out[childKey] = normalizeLocalNetworkConfig(childValue, portMap, childKey)
955
- }
956
- }
957
- return out
958
- }
959
-
960
- async function simulatorScene(scene) {
961
- const presetResponse = await sim('GET', `/api/presets/${encodeURIComponent(scene.preset)}`)
962
- const blueprint = requireSuccess(presetResponse, `${scene.id} simulator preset`)
963
- if (!blueprint?.plantModel || !Array.isArray(blueprint.nodes)) throw new Error(`${scene.id} simulator preset shape is invalid`)
964
-
965
- const portMapByDeviceId = new Map()
966
- const toCreate = []
967
- let nextPort = 44_000 + evidence.experiment.scenes.length * 100
968
- for (const raw of blueprint.nodes) {
969
- const node = structuredClone(raw)
970
- if ((node.protocol && /serial|rtu/i.test(String(node.protocol))) || /serialPort|comPort|devicePath/i.test(JSON.stringify(node.config ?? {}))) continue
971
- node.config ||= {}
972
- const oldPort = Number(node.config.port)
973
- const portMap = new Map()
974
- if (Number.isInteger(oldPort) && oldPort > 0) {
975
- while (allocatedDevicePorts.includes(nextPort) || nextPort === FORBIDDEN_PORT) nextPort += 1
976
- await assertFreeLoopback(nextPort, `${scene.id}-simulator-device`)
977
- portMap.set(oldPort, nextPort)
978
- allocatedDevicePorts.push(nextPort)
979
- noteIsolation(`${scene.id}-device-port-free-loopback`, true, { port: nextPort, host: '127.0.0.1', protocol: node.protocol ?? 'unspecified' })
980
- node.config.port = nextPort
981
- nextPort += 1
982
- }
983
- node.config = normalizeLocalNetworkConfig(node.config, portMap)
984
- if (node.protocol === 'mqtt' || /mqtt/i.test(String(node.protocol))) node.config.brokerUrl = `mqtt://127.0.0.1:${MQTT_PORT}`
985
- portMapByDeviceId.set(node.id, portMap)
986
- toCreate.push(node)
987
- }
988
- if (toCreate.length === 0) throw new Error(`${scene.id} simulator preset has no loopback-safe device nodes`)
989
-
990
- for (const node of toCreate) {
991
- const created = await sim('POST', '/api/nodes', node)
992
- requireSuccess(created, `${scene.id} simulator device ${safeText(node.id, 80)}`)
993
- }
994
- const plant = { ...blueprint.plantModel, id: `${TAG}-${scene.id}`, seed: 42, timeScale: 1, truthExport: false }
995
- const loaded = await sim('PUT', '/api/plant/config', { plantModel: plant, warm: true, upsert: true })
996
- requireSuccess(loaded, `${scene.id} simulator plant model`)
997
-
998
- const exports = []
999
- for (const node of toCreate) {
1000
- const result = await sim('GET', `/api/nodes/${encodeURIComponent(node.id)}/export`)
1001
- const data = requireSuccess(result, `${scene.id} simulator export ${safeText(node.id, 80)}`)
1002
- for (const item of data?.items ?? []) exports.push({ ...item, deviceId: node.id })
1003
- }
1004
- for (const item of exports) {
1005
- item.driverConfig = normalizeLocalNetworkConfig(item.driverConfig ?? {}, portMapByDeviceId.get(item.deviceId) ?? new Map())
1006
- for (const [key, value] of Object.entries(item.driverConfig)) {
1007
- if (/^(?:host|hostname|ip|address)$/i.test(key) && !['127.0.0.1', 'localhost', '::1'].includes(String(value))) {
1008
- throw new Error(`${scene.id} exported driver config escaped loopback boundary`)
1009
- }
1010
- }
1011
- }
1012
- const mv = exports.find(item => item.deviceId === scene.sourceDevice && item.signal === scene.mvSignal)
1013
- const cv = exports.find(item => item.signal === scene.cvSignal)
1014
- if (!mv || !cv) throw new Error(`${scene.id} simulator export lacks required MV/CV signals`)
1015
- if (!['opcua', 'modbus-tcp'].includes(String(mv.driver))) throw new Error(`${scene.id} MV driver is outside the approved simulator protocol set`)
1016
- const evidenceSignal = signal => Object.fromEntries(Object.entries(signal).filter(([key]) => key !== 'curl'))
1017
- return {
1018
- mv: evidenceSignal(mv),
1019
- cv: evidenceSignal(cv),
1020
- plant: { id: plant.id, kind: plant.kind ?? 'simulator', seed: 42, timeScale: 1 },
1021
- deviceCount: toCreate.length,
1022
- }
1023
- }
1024
-
1025
- async function registerAdmin() {
1026
- const response = await app('POST', '/api/users/register', {
1027
- name: `Paper Test ${TAG}`,
1028
- email: `${TAG}@example.invalid`,
1029
- password: `Paper-${Date.now()}-safe9`,
1030
- }, { token: undefined })
1031
- const data = requireSuccess(response, 'isolated synthetic administrator registration')
1032
- if (!data?.token || data?.user?.role !== 'admin') throw new Error('fresh-home registration did not return its first administrator token')
1033
- authToken = String(data.token)
1034
- syntheticAdminId = String(data.user.id)
1035
- return { id: syntheticAdminId, role: 'admin' }
1036
- }
1037
-
1038
- async function verifyRagBridgeOutboundDisabled() {
1039
- const ragBridgeHealth = requireSuccess(await app('GET', '/api/plugins/rag-bridge/health'), 'rag-bridge outbound guard health check')
1040
- const deadline = Date.now() + 3_000
1041
- let startupLogConfirmed = false
1042
- while (Date.now() < deadline) {
1043
- startupLogConfirmed = /\[rag-bridge\].*出站调用已禁用:/.test(readFileSync(APP_LOG, 'utf8'))
1044
- if (startupLogConfirmed) break
1045
- await delay(100)
1046
- }
1047
- noteIsolation('rag-bridge-outbound-disabled', ragBridgeHealth?.outbound === false && startupLogConfirmed, {
1048
- setting: 'plugins.rag-bridge.base_url',
1049
- pluginHealthOutbound: ragBridgeHealth?.outbound ?? null,
1050
- startupLogConfirmed,
1051
- })
1052
- }
1053
-
1054
- function piFixtureSystemPrompt(scene, recipe, control, decisionStimulus) {
1055
- const selected = Number(scene.fixtureCandidate)
1056
- return [
1057
- 'You are operating AgentWorkShop for a bounded integration test in a local process simulator.',
1058
- `Process scene: ${scene.processDescription}.`,
1059
- `Before task submission, the registered drivers measured the control at ${decisionStimulus.controlValue} ${control.unit} and the process variable at ${decisionStimulus.processValue} ${decisionStimulus.processUnit}.`,
1060
- `The task target band is ${decisionStimulus.targetMin} to ${decisionStimulus.targetMax} ${decisionStimulus.processUnit}.`,
1061
- `This local deterministic model fixture is configured to test one bounded candidate: ${selected} ${control.unit}. It is the only permitted value for this request.`,
1062
- `Call recipe_trial exactly once with recipe_id "${recipe.id}", one params entry for node_id "${control.id}" and value ${selected}. State only that this is a deterministic integration fixture in hypothesis.`,
1063
- 'After receiving the recipe_trial result, call complete_task exactly once on the active root task. Include the selected value and returned command-verification outcome in a concise summary and deliverable.',
1064
- 'Do not make any other tool calls. Do not retry. Do not create, update, apply, or roll back a recipe. Do not claim that the trial improves or settles the process.',
1065
- 'After the complete_task result, give a brief factual report and make no further tool calls.',
1066
- ].join('\n')
1067
- }
1068
-
1069
- async function setupScene(scene, simDetails) {
1070
- currentScene = scene.id
1071
- currentStage = `${scene.id}:application-setup`
1072
- const sceneEvidence = {
1073
- id: scene.id,
1074
- simulatorPreset: scene.preset,
1075
- simulator: simDetails,
1076
- status: 'running',
1077
- approvals: [],
1078
- runs: [],
1079
- }
1080
- evidence.experiment.scenes.push(sceneEvidence)
1081
-
1082
- const line = requireSuccess(await app('POST', '/api/workshop/dcw/lines', {
1083
- name: `${TAG}-${scene.id}`,
1084
- description: 'Synthetic isolated paper integration run',
1085
- simulated: true,
1086
- simSceneId: scene.preset,
1087
- controlMode: 'manual',
1088
- }), `${scene.id} line creation`).line
1089
- const product = requireSuccess(await app('POST', '/api/workshop/dcw/products', {
1090
- name: `${TAG}-${scene.id}-product`, lineId: line.id,
1091
- }), `${scene.id} product creation`).product
1092
- const template = requireSuccess(await app('POST', '/api/workshop/dcw/templates', {
1093
- name: `${TAG}-${scene.id}-control-template`,
1094
- unit: simDetails.mv.unit,
1095
- min: simDetails.mv.min,
1096
- max: simDetails.mv.max,
1097
- decimals: simDetails.mv.decimals ?? 0,
1098
- }), `${scene.id} control template creation`).template
1099
- const control = requireSuccess(await app('POST', '/api/workshop/dcw', {
1100
- templateRef: template.key,
1101
- name: `${TAG}-${scene.id}-control`,
1102
- driver: simDetails.mv.driver,
1103
- driverConfig: simDetails.mv.driverConfig,
1104
- lineId: line.id,
1105
- min: simDetails.mv.min,
1106
- max: simDetails.mv.max,
1107
- unit: simDetails.mv.unit,
1108
- decimals: simDetails.mv.decimals ?? 0,
1109
- stepLimit: 30,
1110
- writeLockSeconds: 0,
1111
- holdIntervalMs: 0,
1112
- readIntervalMs: 500,
1113
- semantics: `Bounded simulated ${scene.mvSignal} setpoint for integration evidence`,
1114
- }), `${scene.id} control node creation`).node
1115
- const daq = requireSuccess(await app('POST', '/api/workshop/daq', {
1116
- templateRef: 'daq-temp-tc',
1117
- name: `${TAG}-${scene.id}-daq-cv`,
1118
- driver: simDetails.cv.driver,
1119
- driverConfig: simDetails.cv.driverConfig,
1120
- lineId: line.id,
1121
- min: simDetails.cv.min,
1122
- max: simDetails.cv.max,
1123
- unit: simDetails.cv.unit,
1124
- intervalMs: 1000,
1125
- publishIntervalMs: 0,
1126
- semantics: `Bounded simulated ${scene.cvSignal} controlled variable for run-tagged sampling`,
1127
- }), `${scene.id} DAQ node creation`).node
1128
- const recipe = requireSuccess(await app('POST', '/api/workshop/dcw/recipes', {
1129
- name: `${TAG}-${scene.id}-recipe`,
1130
- productId: product.id,
1131
- params: [{ nodeId: control.id, templateRef: template.key, value: scene.baseline, min: simDetails.mv.min, max: simDetails.mv.max, stepLimit: 30 }],
1132
- daqWindows: [{ nodeId: daq.id, min: simDetails.cv.min, max: simDetails.cv.max }],
1133
- }), `${scene.id} recipe creation`).recipe
1134
-
1135
- const start = requireSuccess(await app('POST', `/api/workshop/dcw/lines/${encodeURIComponent(line.id)}/start`, { recipeId: recipe.id }), `${scene.id} line start`)
1136
- const runId = String(start.run?.id ?? '')
1137
- if (!runId) throw new Error(`${scene.id} line start returned no run identifier`)
1138
- sceneEvidence.activeRun = { id: runId, status: start.run?.status ?? null, startedAt: start.run?.startedAt ?? null, recipeId: start.run?.recipeId ?? recipe.id }
1139
-
1140
- let decisionStimulus
1141
- if (HARNESS_MODE === 'pi-local-fixture') {
1142
- let controlRead
1143
- let controlReadAttempts = 0
1144
- do {
1145
- controlRead = await app('POST', `/api/workshop/dcw/${encodeURIComponent(control.id)}/read`)
1146
- controlReadAttempts += 1
1147
- if (controlRead.status === 409 && controlReadAttempts < 3) await delay(500)
1148
- } while (controlRead.status === 409 && controlReadAttempts < 3)
1149
- const controlReadData = requireSuccess(controlRead, `${scene.id} pre-task control read`)
1150
- const controlData = controlReadData?.outcome ?? controlReadData?.read ?? controlReadData
1151
- const controlValue = Number(controlData?.value ?? controlData?.data?.value)
1152
- let processProbeResponse
1153
- let processProbeAttempts = 0
1154
- do {
1155
- processProbeResponse = await app('POST', `/api/workshop/daq/${encodeURIComponent(daq.id)}/test`)
1156
- processProbeAttempts += 1
1157
- if (processProbeResponse.status === 409 && processProbeAttempts < 3) await delay(500)
1158
- } while (processProbeResponse.status === 409 && processProbeAttempts < 3)
1159
- const processProbe = requireSuccess(processProbeResponse, `${scene.id} pre-task process probe`).test
1160
- const processValue = Number(processProbe?.sampleValue)
1161
- if (!Number.isFinite(controlValue) || processProbe?.ok !== true || !Number.isFinite(processValue)) {
1162
- throw new Error(`${scene.id} pre-task protocol reads did not provide finite control and process values`)
1163
- }
1164
- decisionStimulus = {
1165
- controlValue,
1166
- processValue,
1167
- processUnit: simDetails.cv.unit,
1168
- targetMin: scene.targetMin,
1169
- targetMax: scene.targetMax,
1170
- allowedValues: [...scene.candidates],
1171
- probeDriver: simDetails.cv.driver,
1172
- probeLatencyMs: Number.isFinite(Number(processProbe.latencyMs)) ? Number(processProbe.latencyMs) : null,
1173
- controlReadAttempts,
1174
- processProbeAttempts,
1175
- measuredAt: new Date().toISOString(),
1176
- }
1177
- sceneEvidence.decisionStimulus = decisionStimulus
1178
- sceneEvidence.simulator.candidateChoices = [...scene.candidates]
1179
- }
1180
-
1181
- const channel = requireSuccess(await app('POST', '/api/workshop/channels', {
1182
- name: `${TAG}-${scene.id}-harness-channel`,
1183
- description: 'Registered Pi CLI with a local deterministic model API fixture for simulator integration evidence',
1184
- }), `${scene.id} channel creation`)
1185
- const agentConfig = {
1186
- command: PI_COMMAND,
1187
- cwd: HOME,
1188
- baseUrl: APP_BASE,
1189
- provider: PI_PROVIDER,
1190
- model: PI_MODEL,
1191
- promptTimeoutMs: PI_PROMPT_TIMEOUT_MS,
1192
- systemPromptPrefix: piFixtureSystemPrompt(scene, recipe, control, decisionStimulus),
1193
- }
1194
- const agent = requireSuccess(await app('POST', `/api/workshop/channels/${encodeURIComponent(channel.channelId)}/agents`, {
1195
- name: `${TAG}-${scene.id}-pi-local-fixture`,
1196
- harness: 'pi',
1197
- role: 'lead',
1198
- config: agentConfig,
1199
- }), `${scene.id} registered OMP lead creation`)
1200
-
1201
- const recipeBinding = requireSuccess(await app('POST', '/api/workshop/agent-tools/bindings', {
1202
- agentId: agent.id, nodeId: recipe.id, kind: 'recipe',
1203
- }), `${scene.id} recipe binding`).binding
1204
- const daqBinding = requireSuccess(await app('POST', '/api/workshop/agent-tools/bindings', {
1205
- agentId: agent.id, nodeId: daq.id, kind: 'daq', mode: 'auto',
1206
- }), `${scene.id} DAQ binding`).binding
1207
- check(`${scene.id}-registered-pi`, agent.harness === 'pi' && Boolean(agent.id), { harness: agent.harness, agentId: agent.id, provider: PI_PROVIDER, model: PI_MODEL })
1208
- check(`${scene.id}-manual-recipe-binding`, recipeBinding.kind === 'recipe' && recipeBinding.mode === 'manual', { kind: recipeBinding.kind, mode: recipeBinding.mode })
1209
- check(`${scene.id}-daq-observation-binding`, daqBinding.kind === 'daq', { kind: daqBinding.kind })
1210
-
1211
- sceneEvidence.entities = { lineId: line.id, productId: product.id, recipeId: recipe.id, controlNodeId: control.id, daqNodeId: daq.id, channelId: channel.channelId, agentId: agent.id }
1212
- sceneEvidence.bindings = { recipe: { kind: recipeBinding.kind, mode: recipeBinding.mode }, daq: { kind: daqBinding.kind, mode: daqBinding.mode } }
1213
- sceneEvidence.routePolicy = { tool: 'recipe_trial', emergency: false, cadenceBypass: false, recipeBindingMode: recipeBinding.mode }
1214
- sceneEvidence.status = 'setup-complete'
1215
- return { line, product, template, control, daq, recipe, channel, agent, runId, evidence: sceneEvidence }
1216
- }
1217
-
1218
- async function submitFixtureTask(context) {
1219
- currentStage = `${context.evidence.id}:submit-lead-task`
1220
- const sent = requireSuccess(await app('POST', `/api/workshop/channels/${encodeURIComponent(context.channel.channelId)}/tasks`, {
1221
- title: `Isolated ${context.evidence.id} recipe_trial verification`,
1222
- description: [
1223
- `Execute the preconfigured isolated ${context.evidence.id} recipe_trial candidate exactly once and wait for synthetic human approval.`,
1224
- 'After the verified recipe_trial result returns, call complete_task exactly once with a concise factual deliverable. Do not claim process improvement.',
1225
- 'Do not make any other host-tool calls, retry, or create/update/apply/roll back a recipe.',
1226
- ].join(' '),
1227
- fromLabel: 'Synthetic isolated test driver',
1228
- }), `${context.evidence.id} lead task submission`)
1229
- context.evidence.taskId = sent.id ?? sent.task?.id ?? null
1230
- if (piFixtureTarget) piFixtureTarget.taskId = context.evidence.taskId
1231
- }
1232
-
1233
- async function submitRealOmpTask(context) {
1234
- currentStage = `${context.evidence.id}:submit-real-omp-task`
1235
- const sent = requireSuccess(await app('POST', `/api/workshop/channels/${encodeURIComponent(context.channel.channelId)}/tasks`, {
1236
- title: `R20 ${context.evidence.id} recipe_trial with explicit task closure`,
1237
- description: [
1238
- 'Use the measured process context in your registered system prompt to choose one candidate from its prevalidated set.',
1239
- `Call recipe_trial exactly once with recipe_id ${context.recipe.id} and one params entry for node_id ${context.control.id} using your selected value.`,
1240
- 'After receiving the recipe_trial result, call complete_task exactly once on the active root task shown in the supervision context. Include the selected value and returned command-verification outcome in a concise summary and deliverable.',
1241
- 'Do not make any other tool calls. Do not retry, save, update, apply, or roll back a recipe. If no candidate is justified, abstain and explicitly close the task with that limitation.',
1242
- ].join(' '),
1243
- fromLabel: 'Synthetic isolated R20 test driver',
1244
- }), `${context.evidence.id} real OMP lead task submission`)
1245
- context.evidence.taskId = sent.id ?? sent.task?.id ?? null
1246
- if (!context.evidence.taskId) throw new Error(`${context.evidence.id} real OMP task submission returned no task identifier`)
1247
- }
1248
-
1249
- function taskToolEvents(task) {
1250
- const events = []
1251
- for (const message of task?.history ?? []) {
1252
- for (const part of message?.parts ?? []) {
1253
- const text = typeof part?.text === 'string' ? part.text : ''
1254
- const match = text.match(/^🔧\s+([a-z][a-z\d_]*)/i)
1255
- if (!match) continue
1256
- events.push({
1257
- toolName: match[1],
1258
- phase: /(?:✅\s*完成|❌\s*失败)/.test(text) ? 'result' : 'call',
1259
- isError: /❌\s*失败/.test(text),
1260
- messageId: message.messageId ?? null,
1261
- text,
1262
- })
1263
- }
1264
- }
1265
- return events
1266
- }
1267
-
1268
- async function readRealOmpTask(context) {
1269
- const result = await app('GET', `/api/workshop/tasks/${encodeURIComponent(context.evidence.taskId)}?channelId=${encodeURIComponent(context.channel.channelId)}`)
1270
- if (result.status !== 200) throw new Error(`${context.evidence.id} task detail returned HTTP ${result.status}`)
1271
- return result.data
1272
- }
1273
-
1274
- async function waitForRealOmpTaskCompletion(context) {
1275
- const deadline = Date.now() + REAL_OMP_TASK_COMPLETION_TIMEOUT_MS
1276
- let latest
1277
- while (Date.now() < deadline) {
1278
- latest = await readRealOmpTask(context)
1279
- if (latest.state === 'COMPLETED') return latest
1280
- if (['FAILED', 'CANCELED'].includes(latest.state)) {
1281
- throw new Error(`${context.evidence.id} task reached ${latest.state} before completing the approved operation`)
1282
- }
1283
- await delay(500)
1284
- }
1285
- throw new Error(`${context.evidence.id} task did not reach COMPLETED within the bounded post-approval window (state=${latest?.state ?? 'unknown'})`)
1286
- }
1287
-
1288
- function assertSingleRealOmpCall(context, task) {
1289
- const events = taskToolEvents(task)
1290
- const calls = events.filter(event => event.phase === 'call')
1291
- const recipeCalls = calls.filter(event => event.toolName === 'recipe_trial')
1292
- const recipeResults = events.filter(event => event.toolName === 'recipe_trial' && event.phase === 'result')
1293
- const completionCalls = calls.filter(event => event.toolName === 'complete_task')
1294
- // The active lead turn is journaled through both the task-event mapper and
1295
- // the supervisor listener. A single host invocation can therefore appear
1296
- // twice in history; identical start text identifies that mirror. Route
1297
- // ledgers below remain authoritative for the number of executed trials.
1298
- const uniqueRecipeCalls = [...new Set(recipeCalls.map(event => event.text))]
1299
- if (events.some(event => !['recipe_trial', 'complete_task'].includes(event.toolName))
1300
- || recipeCalls.length < 1 || recipeCalls.length > 2 || uniqueRecipeCalls.length !== 1
1301
- || recipeResults.length < 1 || recipeResults.length > 2 || recipeResults.some(event => event.isError)
1302
- || completionCalls.length !== 1) {
1303
- throw new Error(`${context.evidence.id} OMP task history must show one recipe_trial invocation (allowing its mirrored journal entry), a successful result, and one explicit task-completion call`)
1304
- }
1305
- return { events, calls: [recipeCalls[0]], results: [recipeResults[0]], completionCalls }
1306
- }
1307
-
1308
- async function approveRealOmpTrial(context) {
1309
- currentStage = `${context.evidence.id}:await-real-omp-hitl-approval`
1310
- const deadline = Date.now() + REAL_OMP_APPROVAL_TIMEOUT_MS
1311
- let pending
1312
- let latestTask
1313
- while (Date.now() < deadline) {
1314
- latestTask = await readRealOmpTask(context)
1315
- if (['FAILED', 'CANCELED', 'COMPLETED'].includes(latestTask.state)) {
1316
- throw new Error(`${context.evidence.id} task reached ${latestTask.state} before synthetic approval`)
1317
- }
1318
- const result = await app('GET', `/api/workshop/agent-tools/approvals?agentId=${encodeURIComponent(context.agent.id)}&scope=pending`)
1319
- if (result.status === 200) {
1320
- const matches = (result.data?.approvals ?? []).filter(item => item.agentId === context.agent.id && item.nodeId === `recipe:${context.recipe.id}` && item.status === 'pending')
1321
- if (matches.length > 1) throw new Error(`${context.evidence.id} has multiple pending real OMP trial approvals`)
1322
- if (matches.length === 1) {
1323
- const payload = matches[0].payload
1324
- const params = Array.isArray(payload?.params) ? payload.params : []
1325
- const proposedValue = Number(params[0]?.to)
1326
- const decisionStimulus = context.evidence.decisionStimulus
1327
- const allowedValues = decisionStimulus?.allowedValues ?? []
1328
- const isExpectedTrial = payload?.kind === 'recipe-gate'
1329
- && payload?.op === 'trial'
1330
- && payload?.recipeId === context.recipe.id
1331
- && payload?.emergency !== true
1332
- && payload?.emergency !== 'true'
1333
- && params.length === 1
1334
- && params[0]?.nodeId === context.control.id
1335
- && Number.isFinite(proposedValue)
1336
- && allowedValues.includes(proposedValue)
1337
- && proposedValue >= Number(context.evidence.simulator.mv.min)
1338
- && proposedValue <= Number(context.evidence.simulator.mv.max)
1339
- && Math.abs(proposedValue - Number(decisionStimulus.controlValue)) <= 30
1340
- if (!isExpectedTrial) throw new Error(`${context.evidence.id} refused a pending approval outside the registered recipe_trial candidate set`)
1341
- context.evidence.simulator.candidate = proposedValue
1342
- context.evidence.modelDecision = {
1343
- source: 'registered OMP host-tool proposal, checked against current protocol reads and prevalidated set',
1344
- controlValue: decisionStimulus.controlValue,
1345
- processValue: decisionStimulus.processValue,
1346
- targetBand: [decisionStimulus.targetMin, decisionStimulus.targetMax],
1347
- allowedValues,
1348
- selectedValue: proposedValue,
1349
- selectionRationale: safeText(payload?.hypothesis ?? payload?.rationale ?? '', 400),
1350
- selectedValueWithinRangeAndStep: true,
1351
- }
1352
- pending = matches[0]
1353
- break
1354
- }
1355
- }
1356
- await delay(500)
1357
- }
1358
- if (!pending) throw new Error(`${context.evidence.id} real OMP recipe_trial approval did not appear within the bounded window`)
1359
- context.evidence.approvals.push({ id: pending.id, statusBeforeDecision: pending.status, nodeId: pending.nodeId, title: pending.title ?? null, candidateValue: context.evidence.simulator.candidate, decision: 'approve' })
1360
- requireSuccess(await app('POST', `/api/workshop/agent-tools/approvals/${encodeURIComponent(pending.id)}/decide`, {
1361
- approved: true,
1362
- comment: 'Approved for the bounded R20 local simulator integration check.',
1363
- }), `${context.evidence.id} synthetic real OMP HITL approval`)
1364
- const history = await app('GET', `/api/workshop/agent-tools/approvals?agentId=${encodeURIComponent(context.agent.id)}&scope=history`)
1365
- const finalApproval = (history.data?.approvals ?? []).find(item => item.id === pending.id)
1366
- if (history.status !== 200 || finalApproval?.status !== 'approved' || finalApproval?.decidedBy !== syntheticAdminId) {
1367
- throw new Error(`${context.evidence.id} real OMP HITL history did not confirm the synthetic administrator decision`)
1368
- }
1369
- context.evidence.approvals[0] = {
1370
- ...context.evidence.approvals[0],
1371
- statusAfterDecision: finalApproval.status,
1372
- decisionActor: 'synthetic isolated administrator via protected approval API',
1373
- commentRecorded: finalApproval.comment === 'Approved for the bounded R20 local simulator integration check.',
1374
- }
1375
- }
1376
-
1377
- async function captureRealOmpUsage(context) {
1378
- const unavailable = {
1379
- source: 'not exposed by the channel queue endpoint',
1380
- context: null,
1381
- requestInputTokens: null,
1382
- requestOutputTokens: null,
1383
- costUsd: null,
1384
- costAvailable: false,
1385
- }
1386
- if (!context?.channel?.channelId || !context?.agent?.id) return unavailable
1387
- try {
1388
- const queueResult = await app('GET', `/api/workshop/channels/${encodeURIComponent(context.channel.channelId)}/queue`)
1389
- if (queueResult.status !== 200) return unavailable
1390
- const queue = extractPayload(queueResult.body)
1391
- const agentStatus = (Array.isArray(queue) ? queue : []).find(item => item.agentId === context.agent.id)
1392
- const raw = agentStatus?.context
1393
- if (!raw) return unavailable
1394
- return {
1395
- source: 'channel queue OMP context snapshot (not request-level billing)',
1396
- context: {
1397
- usedTokens: Number.isFinite(Number(raw.usedTokens)) ? Number(raw.usedTokens) : null,
1398
- contextWindow: Number.isFinite(Number(raw.contextWindow)) ? Number(raw.contextWindow) : null,
1399
- percent: Number.isFinite(Number(raw.percent)) ? Number(raw.percent) : null,
1400
- compacting: raw.compacting === true,
1401
- },
1402
- requestInputTokens: null,
1403
- requestOutputTokens: null,
1404
- costUsd: null,
1405
- costAvailable: false,
1406
- }
1407
- }
1408
- catch { return unavailable }
1409
- }
1410
-
1411
- async function approvePendingTrial(context) {
1412
- currentStage = `${context.evidence.id}:manual-hitl-approval`
1413
- const deadline = Date.now() + 20_000
1414
- let pending
1415
- while (Date.now() < deadline) {
1416
- const result = await app('GET', `/api/workshop/agent-tools/approvals?agentId=${encodeURIComponent(context.agent.id)}&scope=pending`)
1417
- if (result.status === 200) {
1418
- const matches = (result.data?.approvals ?? []).filter(item => item.agentId === context.agent.id && item.nodeId === `recipe:${context.recipe.id}` && item.status === 'pending')
1419
- if (matches.length > 1) throw new Error(`${context.evidence.id} has multiple pending trial approvals`)
1420
- if (matches.length === 1) {
1421
- pending = matches[0]
1422
- break
1423
- }
1424
- }
1425
- await delay(400)
1426
- }
1427
- if (!pending) throw new Error(`${context.evidence.id} manual recipe_trial HITL approval did not appear within the bounded window`)
1428
- const payload = pending.payload ?? {}
1429
- const params = Array.isArray(payload.params) ? payload.params : []
1430
- const proposedValue = Number(params[0]?.to)
1431
- if (payload.kind !== 'recipe-gate'
1432
- || payload.op !== 'trial'
1433
- || payload.recipeId !== context.recipe.id
1434
- || params.length !== 1
1435
- || params[0]?.nodeId !== context.control.id
1436
- || proposedValue !== Number(piFixtureTarget?.value)
1437
- || payload.emergency === true
1438
- || payload.emergency === 'true') {
1439
- throw new Error(`${context.evidence.id} refused a Pi approval outside the scripted bounded recipe_trial request`)
1440
- }
1441
- context.evidence.simulator.candidate = proposedValue
1442
- context.evidence.modelDecision = {
1443
- source: 'registered Pi host-tool request generated by a deterministic loopback model fixture',
1444
- controlValue: context.evidence.decisionStimulus?.controlValue ?? null,
1445
- processValue: context.evidence.decisionStimulus?.processValue ?? null,
1446
- targetBand: [context.evidence.decisionStimulus?.targetMin, context.evidence.decisionStimulus?.targetMax],
1447
- allowedValues: context.evidence.decisionStimulus?.allowedValues ?? [],
1448
- selectedValue: proposedValue,
1449
- selectionRationale: safeText(payload.hypothesis ?? payload.rationale ?? '', 400),
1450
- selectedValueWithinRangeAndStep: true,
1451
- }
1452
- context.evidence.approvals.push({ id: pending.id, taskId: context.evidence.taskId, statusBeforeDecision: pending.status, nodeId: pending.nodeId, candidateValue: proposedValue, title: pending.title ?? null, decision: 'approve' })
1453
- const decided = await app('POST', `/api/workshop/agent-tools/approvals/${encodeURIComponent(pending.id)}/decide`, {
1454
- approved: true,
1455
- comment: 'Approved for the isolated deterministic simulator integration check.',
1456
- })
1457
- requireSuccess(decided, `${context.evidence.id} explicit HITL approval`)
1458
- const history = await app('GET', `/api/workshop/agent-tools/approvals?agentId=${encodeURIComponent(context.agent.id)}&scope=history`)
1459
- const finalApproval = (history.data?.approvals ?? []).find(item => item.id === pending.id)
1460
- if (history.status !== 200 || finalApproval?.status !== 'approved' || finalApproval?.decidedBy !== syntheticAdminId) {
1461
- throw new Error(`${context.evidence.id} HITL approval history failed to confirm the explicit administrator decision`)
1462
- }
1463
- context.evidence.approvals[0] = {
1464
- ...context.evidence.approvals[0],
1465
- statusAfterDecision: finalApproval.status,
1466
- decisionActor: 'synthetic isolated administrator via protected approval API',
1467
- commentRecorded: finalApproval.comment === 'Approved for the isolated deterministic simulator integration check.',
1468
- }
1469
- }
1470
-
1471
- async function waitForPiTaskCompletion(context) {
1472
- const deadline = Date.now() + PI_TASK_COMPLETION_TIMEOUT_MS
1473
- let latest
1474
- while (Date.now() < deadline) {
1475
- latest = await readRealOmpTask(context)
1476
- if (latest.assigneeId !== context.agent.id) {
1477
- throw new Error(`${context.evidence.id} Pi task was not executed by its registered agent`)
1478
- }
1479
- if (latest.state === 'COMPLETED') return latest
1480
- if (['FAILED', 'CANCELED'].includes(latest.state)) {
1481
- throw new Error(`${context.evidence.id} Pi task reached ${latest.state} before returning the tool result`)
1482
- }
1483
- await delay(300)
1484
- }
1485
- throw new Error(`${context.evidence.id} Pi task did not complete within the bounded window (state=${latest?.state ?? 'unknown'})`)
1486
- }
1487
-
1488
- async function collectSceneEvidence(context) {
1489
- currentStage = `${context.evidence.id}:collect-result-and-observations`
1490
- let trace
1491
- let toolName
1492
- let toolText
1493
- let toolIsError
1494
- let realTask
1495
- let realToolEvents
1496
- if (HARNESS_MODE === 'pi-local-fixture') {
1497
- const finalTask = await waitForPiTaskCompletion(context)
1498
- const traceDeadline = Date.now() + 10_000
1499
- let sceneRequests = piApiTrace.filter(item => item.scene === context.evidence.id)
1500
- while (sceneRequests.length < 3 && Date.now() < traceDeadline) {
1501
- await delay(100)
1502
- sceneRequests = piApiTrace.filter(item => item.scene === context.evidence.id)
1503
- }
1504
- const proposal = sceneRequests[0]
1505
- const recipeResult = sceneRequests[1]
1506
- const completionResult = sceneRequests[2]
1507
- const traceChecks = {
1508
- exactlyThreeModelRequests: sceneRequests.length === 3,
1509
- recipeTrialCall: proposal?.response?.type === 'tool_call' && proposal?.response?.toolName === 'recipe_trial',
1510
- approvedCandidateMatches: Number(proposal?.response?.candidate) === Number(context.evidence.simulator.candidate),
1511
- completionToolAvailable: proposal?.toolNames?.includes('complete_task') === true,
1512
- recipeResultFollowedByTaskClosure: recipeResult?.response?.type === 'tool_call' && recipeResult?.response?.toolName === 'complete_task',
1513
- recipeResultReturnedToPi: recipeResult?.toolResultCallId === `call-${context.evidence.id}` && recipeResult?.toolResultMessageCount === 1 && Boolean(recipeResult?.toolResultText),
1514
- recipeResultWasSuccessful: !/(?:isError\s*[:=]\s*true|❌\s*失败|tool error)/i.test(recipeResult?.toolResultText ?? ''),
1515
- completeTaskResultReturnedToPi: completionResult?.response?.type === 'final_text_after_task_completion'
1516
- && completionResult?.toolResultCallId === `complete-${context.evidence.id}`
1517
- && completionResult?.toolResultMessageCount === 2
1518
- && /COMPLETED/.test(completionResult?.toolResultText ?? ''),
1519
- }
1520
- if (Object.values(traceChecks).some(passed => !passed)) {
1521
- throw new Error(`${context.evidence.id} Pi model trace check failed: ${JSON.stringify(Object.fromEntries(Object.entries(traceChecks).filter(([, passed]) => !passed)))}`)
1522
- }
1523
- toolName = 'recipe_trial'
1524
- toolText = recipeResult.toolResultText
1525
- toolIsError = /(?:isError\s*[:=]\s*true|❌\s*失败|tool error)/i.test(toolText)
1526
- context.evidence.modelExecution = {
1527
- harness: 'registered Pi CLI adapter',
1528
- provider: PI_PROVIDER,
1529
- model: PI_MODEL,
1530
- modelMode: 'deterministic local OpenAI-compatible fixture; no LLM or external provider',
1531
- taskId: context.evidence.taskId,
1532
- taskState: finalTask.state,
1533
- taskCompleted: finalTask.state === 'COMPLETED',
1534
- taskAssigneeMatchesRegisteredPi: finalTask.assigneeId === context.agent.id,
1535
- modelApiRequests: sceneRequests.map(item => ({
1536
- requestId: item.requestId,
1537
- requestModel: item.requestModel,
1538
- loopbackPeer: item.loopbackPeer,
1539
- apiKeyMatchesLocalFixture: item.apiKeyMatchesLocalFixture,
1540
- streamRequested: item.streamRequested,
1541
- toolNames: item.toolNames,
1542
- messageRoles: item.messageRoles,
1543
- toolResultMessageCount: item.toolResultMessageCount,
1544
- response: item.response,
1545
- })),
1546
- recipeTrialResultReturnedToPi: recipeResult.toolResultMessageCount === 1,
1547
- completeTaskCallIssued: recipeResult.response.toolName === 'complete_task',
1548
- completeTaskResultReturnedToPi: completionResult.toolResultMessageCount === 2,
1549
- completeTaskResultConfirmed: /COMPLETED/.test(completionResult.toolResultText),
1550
- }
1551
- }
1552
- else if (HARNESS_MODE === 'real-omp') {
1553
- // The supervisor journals compact host-tool start/result events on the
1554
- // active root task. Approval and operation ledgers remain authoritative
1555
- // for the proposal and its execution.
1556
- realTask = await waitForRealOmpTaskCompletion(context)
1557
- if (realTask.assigneeId !== context.agent.id) throw new Error(`${context.evidence.id} real OMP task was not executed by its registered lead agent`)
1558
- realToolEvents = assertSingleRealOmpCall(context, realTask)
1559
- const channelMessages = requireSuccess(await app('GET', `/api/workshop/channels/${encodeURIComponent(context.channel.channelId)}/messages?limit=500`), `${context.evidence.id} channel task evidence`)
1560
- const taskMessages = (Array.isArray(channelMessages) ? channelMessages : []).filter(message => message.taskId === context.evidence.taskId)
1561
- const usage = await captureRealOmpUsage(context)
1562
- context.evidence.modelExecution = {
1563
- provider: REAL_OMP_PROVIDER,
1564
- model: REAL_OMP_MODEL,
1565
- taskId: context.evidence.taskId,
1566
- taskState: realTask.state,
1567
- taskArtifactCount: Array.isArray(realTask.artifacts) ? realTask.artifacts.length : 0,
1568
- evidenceSource: 'registered OMP task history, approval payload, task state, and route-specific recipe/ACK records',
1569
- hostToolCallEvents: realToolEvents.calls.length + realToolEvents.completionCalls.length,
1570
- hostToolResultEvents: realToolEvents.results.length,
1571
- taskCompletionToolCallEvents: realToolEvents.completionCalls.length,
1572
- taskToolEvents: realToolEvents.events.map(event => ({ toolName: event.toolName, phase: event.phase, isError: event.isError })),
1573
- hostToolEventHistoryAvailable: realToolEvents.events.length > 0,
1574
- approvedProposalValue: context.evidence.modelDecision?.selectedValue ?? null,
1575
- approvedProposalCount: context.evidence.approvals.length,
1576
- channelEvidence: {
1577
- source: 'GET /api/workshop/channels/:id/messages',
1578
- taskMessageCount: taskMessages.length,
1579
- agentMessageCount: taskMessages.filter(message => message.fromAgentId === context.agent.id).length,
1580
- roles: [...new Set(taskMessages.map(message => safeText(message.role, 40)))],
1581
- },
1582
- usage,
1583
- }
1584
- }
1585
- else if (HARNESS_MODE === 'fixture') {
1586
- const tracePath = fixtureTracePath(context.evidence.id)
1587
- const deadline = Date.now() + 20_000
1588
- while (Date.now() < deadline) {
1589
- if (existsSync(tracePath)) {
1590
- try {
1591
- trace = JSON.parse(readFileSync(tracePath, 'utf8'))
1592
- }
1593
- catch { /* fixture is rewriting a small JSON trace */ }
1594
- }
1595
- if (trace?.hostToolResults?.length) break
1596
- await delay(300)
1597
- }
1598
- if (!trace) throw new Error(`${context.evidence.id} deterministic fixture did not create its trace`)
1599
- if (trace.hostToolCalls?.length !== 1 || trace.hostToolCalls[0]?.toolName !== 'recipe_trial' || trace.hostToolResults?.length !== 1) {
1600
- throw new Error(`${context.evidence.id} fixture trace did not show exactly one recipe_trial host_tool_call/result`)
1601
- }
1602
- const toolResult = trace.hostToolResults[0].result
1603
- toolText = String(toolResult?.content?.[0]?.text ?? '')
1604
- toolName = trace.hostToolCalls[0].toolName
1605
- toolIsError = Boolean(toolResult?.isError)
1606
- if (toolIsError || !/全部设备证实|下发并全部设备证实/.test(toolText)) {
1607
- throw new Error(`${context.evidence.id} recipe_trial did not return a fully verified device ACK`)
1608
- }
1609
- }
1610
-
1611
- const readback = await app('POST', `/api/workshop/dcw/${encodeURIComponent(context.control.id)}/read`)
1612
- requireSuccess(readback, `${context.evidence.id} DCW readback`)
1613
-
1614
- const runData = await app('GET', `/api/workshop/dcw/runs/${encodeURIComponent(context.runId)}/data`)
1615
- requireSuccess(runData, `${context.evidence.id} active run data`)
1616
- const logs = await app('GET', `/api/workshop/ops-logs?scope=line&lineId=${encodeURIComponent(context.line.id)}&recipeId=${encodeURIComponent(context.recipe.id)}&limit=100`)
1617
- requireSuccess(logs, `${context.evidence.id} recipe operation log`)
1618
- const recipeRows = (logs.data?.logs ?? [])
1619
- .filter(row => String(row.action).startsWith('recipe.'))
1620
- .map((row) => {
1621
- let detail = row.detail
1622
- if (!detail || typeof detail !== 'object' || Array.isArray(detail)) {
1623
- try {
1624
- const parsed = JSON.parse(String(row.detailJson ?? '{}'))
1625
- detail = parsed && typeof parsed === 'object' && !Array.isArray(parsed) ? parsed : {}
1626
- }
1627
- catch { detail = {} }
1628
- }
1629
- return { ...row, detail }
1630
- })
1631
- const trialRows = recipeRows.filter(row => row.action === 'recipe.trial')
1632
- const trialAckRows = recipeRows.filter(row => row.action === 'recipe.dispatch.ack' && row.detail?.trial === true)
1633
- const trialRow = trialRows[0]
1634
- const ackRow = trialAckRows[0]
1635
- const trialRunId = String(ackRow?.detail?.runId ?? '')
1636
- if (trialRows.length !== 1 || trialAckRows.length !== 1 || !trialRunId || String(trialRow?.detail?.runId ?? '') !== trialRunId) {
1637
- throw new Error(`${context.evidence.id} recipe log did not contain exactly one matching recipe.trial and trial ACK pair`)
1638
- }
1639
- if (HARNESS_MODE === 'real-omp' && context.evidence.approvals.length !== 1) {
1640
- throw new Error(`${context.evidence.id} expected exactly one approved real OMP proposal`)
1641
- }
1642
- const trialRunData = await app('GET', `/api/workshop/dcw/runs/${encodeURIComponent(trialRunId)}/data`)
1643
- requireSuccess(trialRunData, `${context.evidence.id} trial run data`)
1644
- const ack = ackRow.detail?.ackSummary ?? null
1645
- if (!ack || ack.total !== 1 || ack.verified !== 1 || ack.failed !== 0 || ack.unverified !== 0) {
1646
- throw new Error(`${context.evidence.id} logged trial ACK is not one-of-one verified`)
1647
- }
1648
- const returnedTrialRun = trialRunData.data?.run
1649
- const trialResults = returnedTrialRun?.results
1650
- if (returnedTrialRun?.id !== trialRunId || !Array.isArray(trialResults) || trialResults.length !== 1 || trialResults[0]?.verify?.verdict !== 'verified' || trialResults[0]?.ok !== true) {
1651
- throw new Error(`${context.evidence.id} trial run data lacks an independently verified write result`)
1652
- }
1653
-
1654
- const snapshotDelayStartedAt = new Date().toISOString()
1655
- await delay(20_000)
1656
- const probeStartedAt = new Date().toISOString()
1657
- const probeResponse = await app('POST', `/api/workshop/daq/${encodeURIComponent(context.daq.id)}/test`)
1658
- const probe = requireSuccess(probeResponse, `${context.evidence.id} DAQ driver probe`).test
1659
- const sampleValue = Number(probe?.sampleValue)
1660
- if (probe?.ok !== true || !Number.isFinite(sampleValue)) {
1661
- throw new Error(`${context.evidence.id} DAQ driver probe did not return a finite simulator value`)
1662
- }
1663
- const probeCompletedAt = new Date().toISOString()
1664
- const ingestAt = probeCompletedAt
1665
- const ingest = requireSuccess(await app('POST', `/api/workshop/daq/${encodeURIComponent(context.daq.id)}/ingest`, {
1666
- at: ingestAt,
1667
- value: sampleValue,
1668
- state: 'ok',
1669
- }), `${context.evidence.id} DAQ snapshot ingest`)
1670
- if (ingest?.accepted !== true || ingest.nodeId !== context.daq.id || ingest.lineId !== context.line.id) {
1671
- throw new Error(`${context.evidence.id} DAQ snapshot ingest was not accepted for the expected node and line`)
1672
- }
1673
-
1674
- const persistedAt = String(ingest.at ?? ingestAt)
1675
- const persistedAtMs = Date.parse(persistedAt)
1676
- if (!Number.isFinite(persistedAtMs)) throw new Error(`${context.evidence.id} DAQ snapshot ingest returned an invalid sample timestamp`)
1677
- const fromMs = persistedAtMs
1678
- const toMs = persistedAtMs + 1
1679
- // Let the in-process queue and SQLite batch flush settle before a fixed-window query;
1680
- // retries outlast the short query-cache TTL if the first lookup is still empty.
1681
- await delay(800)
1682
- const queryDeadline = Date.now() + 12_000
1683
- let taggedQuery
1684
- let taggedSeries
1685
- let snapshotBucketAt
1686
- while (Date.now() < queryDeadline) {
1687
- const candidate = await app('GET', `/api/workshop/daq/query?line_id=${encodeURIComponent(context.line.id)}&node_ids=${encodeURIComponent(context.daq.id)}&run_id=${encodeURIComponent(context.runId)}&from=${fromMs}&to=${toMs}&bucket_ms=1000`)
1688
- if (candidate.status === 200) {
1689
- taggedQuery = candidate
1690
- taggedSeries = candidate.data?.series?.find(series => series.nodeId === context.daq.id)
1691
- const bucketMs = Number(candidate.data?.window?.bucketMs) || 1_000
1692
- snapshotBucketAt = Math.floor(persistedAtMs / bucketMs) * bucketMs
1693
- const matchingPoint = taggedSeries?.points?.find(point => Number(point.at) === snapshotBucketAt && Math.abs(Number(point.v) - sampleValue) <= 0.01)
1694
- if (matchingPoint && candidate.data?.activeRun?.runId === context.runId) break
1695
- }
1696
- await delay(300)
1697
- }
1698
- if (!taggedQuery || !taggedSeries?.points?.length || taggedQuery.data?.activeRun?.runId !== context.runId) {
1699
- throw new Error(`${context.evidence.id} platform DAQ query returned no snapshot tagged to the active run`)
1700
- }
1701
- const matchingProbePoint = taggedSeries.points.find(point => Number(point.at) === snapshotBucketAt && Math.abs(Number(point.v) - sampleValue) <= 0.01)
1702
- if (!matchingProbePoint) {
1703
- throw new Error(`${context.evidence.id} run-tagged DAQ data did not contain the driver-probe snapshot value`)
1704
- }
1705
-
1706
- if (HARNESS_MODE === 'real-omp') {
1707
- const finalTask = await readRealOmpTask(context)
1708
- context.evidence.hostToolExecution = {
1709
- provenance: 'registered OMP model proposal → protected synthetic approval → one recipe.trial and one verified DCW receipt',
1710
- hostToolEventHistoryAvailable: realToolEvents.events.length > 0,
1711
- taskStateAfterObservation: finalTask.state,
1712
- taskCompleted: finalTask.state === 'COMPLETED',
1713
- approvedProposalCount: context.evidence.approvals.length,
1714
- recipeTrialCount: trialRows.length,
1715
- recipeTrialAckCount: trialAckRows.length,
1716
- toolName: 'recipe_trial',
1717
- resultReceived: ack?.verified === 1 && ack?.failed === 0,
1718
- }
1719
- context.evidence.modelExecution.taskStateAfterObservation = finalTask.state
1720
- context.evidence.modelExecution.taskCompleted = finalTask.state === 'COMPLETED'
1721
- }
1722
- else {
1723
- context.evidence.fixtureTrace = {
1724
- fixture: HARNESS_MODE === 'pi-local-fixture' ? 'registered Pi CLI with deterministic loopback model fixture' : trace.fixture,
1725
- decisionSource: HARNESS_MODE === 'pi-local-fixture' ? 'Pi CLI tool call through the AgentWorkShop host-tool bridge' : trace.decisionSource,
1726
- hostToolCallCount: HARNESS_MODE === 'pi-local-fixture' ? 1 : trace.hostToolCalls.length,
1727
- toolName,
1728
- resultReceived: HARNESS_MODE === 'pi-local-fixture' ? Boolean(context.evidence.modelExecution?.recipeTrialResultReturnedToPi) : trace.hostToolResults.length === 1,
1729
- toolResultText: safeText(toolText, 1200),
1730
- toolIsError,
1731
- }
1732
- }
1733
- context.evidence.trial = {
1734
- taskId: context.evidence.taskId,
1735
- runId: trialRunId,
1736
- toolName,
1737
- approvalId: context.evidence.approvals[0].id,
1738
- ackSummary: ack,
1739
- resultCount: trialResults.length,
1740
- resultRows: trialResults,
1741
- }
1742
- context.evidence.readback = {
1743
- expectedCandidate: context.evidence.simulator.candidate,
1744
- response: readback.data?.outcome ?? readback.data?.read ?? readback.data,
1745
- resultMatchesCandidate: (() => {
1746
- const details = readback.data?.outcome ?? readback.data?.read ?? readback.data ?? {}
1747
- const observed = Number(details.value ?? details.data?.value ?? details.result?.value)
1748
- return Number.isFinite(observed) && Math.abs(observed - context.evidence.simulator.candidate) <= 0.01
1749
- })(),
1750
- }
1751
- context.evidence.daq = {
1752
- taskId: context.evidence.taskId,
1753
- nodeId: context.daq.id,
1754
- method: 'single driver-probe/ingest snapshot',
1755
- storageBackend: 'isolated AW_HOME SQLite time-series fallback',
1756
- postTrialDelaySeconds: 20,
1757
- snapshotDelayStartedAt,
1758
- sampleCount: taggedSeries.points.length,
1759
- runTags: [context.runId],
1760
- expectedActiveRunId: context.runId,
1761
- probe: {
1762
- driver: context.daq.driver,
1763
- startedAt: probeStartedAt,
1764
- completedAt: probeCompletedAt,
1765
- sampleValue,
1766
- latencyMs: Number.isFinite(Number(probe.latencyMs)) ? Number(probe.latencyMs) : null,
1767
- },
1768
- ingest: {
1769
- accepted: ingest.accepted,
1770
- at: persistedAt,
1771
- value: sampleValue,
1772
- state: 'ok',
1773
- },
1774
- taggedQuery: {
1775
- requestedRunId: context.runId,
1776
- returnedRunId: taggedQuery.data?.activeRun?.runId ?? null,
1777
- seriesPointCount: taggedSeries.points.length,
1778
- probeValueMatched: true,
1779
- snapshotBucketAt: new Date(snapshotBucketAt).toISOString(),
1780
- matchingProbePoint,
1781
- series: taggedSeries.points.slice(-5),
1782
- },
1783
- activeRunDataKeys: Object.keys(runData.data ?? {}),
1784
- }
1785
- context.evidence.recipeLog = {
1786
- taskId: context.evidence.taskId,
1787
- query: 'ops-logs filtered by lineId and recipeId (recipe_log-equivalent audit view)',
1788
- rowCount: recipeRows.length,
1789
- trialAction: trialRow.action,
1790
- trialSummary: safeText(trialRow.summary, 600),
1791
- ackAction: ackRow.action,
1792
- ackSummary: safeText(ackRow.summary, 600),
1793
- trialRunDataKeys: Object.keys(trialRunData.data ?? {}),
1794
- }
1795
- context.evidence.status = 'verified'
1796
- context.evidence.traceability = {
1797
- taskId: context.evidence.taskId,
1798
- approvalId: context.evidence.approvals[0].id,
1799
- recipeId: context.recipe.id,
1800
- trialRunId,
1801
- activeRunId: context.runId,
1802
- daqNodeId: context.daq.id,
1803
- sampleAt: persistedAt,
1804
- taskState: context.evidence.modelExecution?.taskState ?? null,
1805
- taskCompleted: context.evidence.modelExecution?.taskCompleted === true,
1806
- }
1807
- }
1808
-
1809
- async function runScene(scene) {
1810
- const simDetails = await simulatorScene(scene)
1811
- const context = await setupScene(scene, { ...simDetails, candidate: scene.candidate })
1812
- context.evidence.simulator.candidate = scene.candidate
1813
- context.evidence.simulator.baseline = scene.baseline
1814
- piFixtureTarget = {
1815
- scene: context.evidence.id,
1816
- recipeId: context.recipe.id,
1817
- nodeId: context.control.id,
1818
- value: scene.candidate,
1819
- }
1820
- await submitFixtureTask(context)
1821
- await approvePendingTrial(context)
1822
- await collectSceneEvidence(context)
1823
- check(`${scene.id}-pi-task-completed`, context.evidence.modelExecution?.taskCompleted === true && context.evidence.modelExecution?.taskAssigneeMatchesRegisteredPi === true, {
1824
- taskId: context.evidence.taskId,
1825
- state: context.evidence.modelExecution?.taskState ?? null,
1826
- assigneeMatchesRegisteredPi: context.evidence.modelExecution?.taskAssigneeMatchesRegisteredPi === true,
1827
- })
1828
- const linked = context.evidence.traceability?.taskId === context.evidence.taskId
1829
- && context.evidence.approvals[0]?.taskId === context.evidence.taskId
1830
- && context.evidence.trial?.taskId === context.evidence.taskId
1831
- && context.evidence.daq?.taskId === context.evidence.taskId
1832
- && context.evidence.traceability?.approvalId === context.evidence.approvals[0]?.id
1833
- && context.evidence.traceability?.trialRunId === context.evidence.trial?.runId
1834
- && context.evidence.traceability?.activeRunId === context.evidence.daq?.expectedActiveRunId
1835
- && context.evidence.daq?.taggedQuery?.returnedRunId === context.evidence.daq?.expectedActiveRunId
1836
- && Boolean(context.evidence.traceability?.sampleAt)
1837
- check(`${scene.id}-task-approval-receipt-sample-linked`, linked, context.evidence.traceability)
1838
- piFixtureTarget = null
1839
- const stopped = await app('POST', `/api/workshop/dcw/lines/${encodeURIComponent(context.line.id)}/stop`)
1840
- requireSuccess(stopped, `${scene.id} line stop`)
1841
- context.evidence.activeRun.endedAt = stopped.data?.run?.endedAt ?? null
1842
- check(`${scene.id}-host-dispatch-one-call`, context.evidence.fixtureTrace.hostToolCallCount === 1, { tool: context.evidence.fixtureTrace.toolName })
1843
- check(`${scene.id}-ack-verified`, context.evidence.trial.ackSummary.verified === 1 && context.evidence.trial.ackSummary.failed === 0, context.evidence.trial.ackSummary)
1844
- check(`${scene.id}-readback-matches`, context.evidence.readback.resultMatchesCandidate, context.evidence.readback)
1845
- check(`${scene.id}-run-tagged-daq-probe-ingest-snapshot`, context.evidence.daq.taggedQuery.seriesPointCount >= 1 && context.evidence.daq.taggedQuery.probeValueMatched, {
1846
- method: context.evidence.daq.method,
1847
- value: context.evidence.daq.probe.sampleValue,
1848
- runId: context.evidence.daq.expectedActiveRunId,
1849
- matchingPoint: context.evidence.daq.taggedQuery.matchingProbePoint,
1850
- })
1851
- check(`${scene.id}-recipe-log`, context.evidence.recipeLog.rowCount >= 2, { trialAction: context.evidence.recipeLog.trialAction, ackAction: context.evidence.recipeLog.ackAction })
1852
- }
1853
-
1854
- async function recoverFailedRealOmpTrial(context, outcome) {
1855
- const recovery = []
1856
- if (context?.evidence?.taskId) {
1857
- try {
1858
- const task = await readRealOmpTask(context)
1859
- if (!['COMPLETED', 'FAILED', 'CANCELED'].includes(task.state)) {
1860
- const canceled = await app('POST', `/api/workshop/tasks/${encodeURIComponent(context.evidence.taskId)}/cancel`)
1861
- recovery.push({ action: 'cancel-nonterminal-task', status: canceled.status === 200 ? 'completed' : `http-${canceled.status}` })
1862
- }
1863
- else recovery.push({ action: 'cancel-nonterminal-task', status: 'not-needed', taskState: task.state })
1864
- }
1865
- catch (error) { recovery.push({ action: 'cancel-nonterminal-task', status: 'failed', error: compactError(error) }) }
1866
- }
1867
- if (context?.channel?.channelId && context?.agent?.id) {
1868
- try {
1869
- const stopped = await app('POST', `/api/workshop/channels/${encodeURIComponent(context.channel.channelId)}/agents/${encodeURIComponent(context.agent.id)}/stop`)
1870
- recovery.push({ action: 'stop-agent-runtime', status: stopped.status === 200 ? 'completed' : `http-${stopped.status}` })
1871
- }
1872
- catch (error) { recovery.push({ action: 'stop-agent-runtime', status: 'failed', error: compactError(error) }) }
1873
- try {
1874
- const pendingResult = await app('GET', `/api/workshop/agent-tools/approvals?agentId=${encodeURIComponent(context.agent.id)}&scope=pending`)
1875
- const pending = pendingResult.status === 200
1876
- ? (pendingResult.data?.approvals ?? []).filter(item => item.agentId === context.agent.id && item.status === 'pending')
1877
- : []
1878
- for (const approval of pending) {
1879
- const denied = await app('POST', `/api/workshop/agent-tools/approvals/${encodeURIComponent(approval.id)}/decide`, {
1880
- approved: false,
1881
- comment: 'Denied during bounded R20 failure cleanup.',
1882
- })
1883
- recovery.push({ action: 'deny-pending-agent-approval', approvalId: approval.id, status: denied.status === 200 ? 'completed' : `http-${denied.status}` })
1884
- }
1885
- if (pendingResult.status !== 200) recovery.push({ action: 'deny-pending-agent-approval', status: `list-http-${pendingResult.status}` })
1886
- else if (pending.length === 0) recovery.push({ action: 'deny-pending-agent-approval', status: 'not-needed' })
1887
- }
1888
- catch (error) { recovery.push({ action: 'deny-pending-agent-approval', status: 'failed', error: compactError(error) }) }
1889
- }
1890
- if (context?.line?.id) {
1891
- try {
1892
- const stopped = await app('POST', `/api/workshop/dcw/lines/${encodeURIComponent(context.line.id)}/stop`)
1893
- recovery.push({ action: 'stop-line', status: stopped.status === 200 ? 'completed' : `http-${stopped.status}` })
1894
- }
1895
- catch (error) { recovery.push({ action: 'stop-line', status: 'failed', error: compactError(error) }) }
1896
- }
1897
- outcome.recovery = recovery
1898
- }
1899
-
1900
- async function runRealOmpScene(baseScene) {
1901
- currentScene = baseScene.id
1902
- let simDetails
1903
- try {
1904
- currentStage = `${baseScene.id}:simulator-setup-once`
1905
- simDetails = await simulatorScene(baseScene)
1906
- if (!Array.isArray(baseScene.candidates) || baseScene.candidates.length !== REAL_OMP_TRIALS_PER_SCENE
1907
- || baseScene.candidates.some(candidate => !Number.isFinite(candidate)
1908
- || candidate < Number(simDetails.mv.min)
1909
- || candidate > Number(simDetails.mv.max)
1910
- || Math.abs(candidate - baseScene.baseline) > 30)) {
1911
- throw new Error(`${baseScene.id} real OMP candidates violate the configured count, process range, or 30-unit recipe step limit`)
1912
- }
1913
- }
1914
- catch (error) {
1915
- for (let repetition = 1; repetition <= REAL_OMP_TRIALS_PER_SCENE; repetition++) {
1916
- const outcome = {
1917
- id: `${baseScene.id}-r${repetition}`,
1918
- scene: baseScene.id,
1919
- repetition,
1920
- provider: REAL_OMP_PROVIDER,
1921
- model: REAL_OMP_MODEL,
1922
- candidate: baseScene.candidates[repetition - 1],
1923
- usage: { source: 'not available because simulator setup failed', context: null, requestInputTokens: null, requestOutputTokens: null, costUsd: null, costAvailable: false },
1924
- costUsd: null,
1925
- status: 'failed',
1926
- failure: compactError(error),
1927
- }
1928
- evidence.experiment.runOutcomes.push(outcome)
1929
- }
1930
- return
1931
- }
1932
-
1933
- for (let repetition = 1; repetition <= REAL_OMP_TRIALS_PER_SCENE; repetition++) {
1934
- const scene = { ...baseScene, id: `${baseScene.id}-r${repetition}` }
1935
- const outcome = {
1936
- id: scene.id,
1937
- scene: baseScene.id,
1938
- repetition,
1939
- provider: REAL_OMP_PROVIDER,
1940
- model: REAL_OMP_MODEL,
1941
- candidate: null,
1942
- candidateChoices: [...baseScene.candidates],
1943
- usage: { source: 'not yet available', context: null, requestInputTokens: null, requestOutputTokens: null, costUsd: null, costAvailable: false },
1944
- costUsd: null,
1945
- status: 'running',
1946
- startedAt: new Date().toISOString(),
1947
- }
1948
- evidence.experiment.runOutcomes.push(outcome)
1949
- let context
1950
- try {
1951
- currentScene = scene.id
1952
- const runSimDetails = { ...simDetails, candidateChoices: [...baseScene.candidates] }
1953
- context = await setupScene(scene, runSimDetails)
1954
- context.evidence.simulator.baseline = scene.baseline
1955
- outcome.entities = context.evidence.entities
1956
- outcome.runId = context.runId
1957
- await submitRealOmpTask(context)
1958
- outcome.taskId = context.evidence.taskId
1959
- await approveRealOmpTrial(context)
1960
- outcome.candidate = context.evidence.simulator.candidate
1961
- outcome.modelDecision = context.evidence.modelDecision
1962
- await collectSceneEvidence(context)
1963
- const stopped = await app('POST', `/api/workshop/dcw/lines/${encodeURIComponent(context.line.id)}/stop`)
1964
- requireSuccess(stopped, `${scene.id} line stop`)
1965
- context.evidence.activeRun.endedAt = stopped.data?.run?.endedAt ?? null
1966
- const finalTask = await readRealOmpTask(context)
1967
- context.evidence.hostToolExecution.taskStateAfterObservation = finalTask.state
1968
- context.evidence.hostToolExecution.taskCompleted = finalTask.state === 'COMPLETED'
1969
- context.evidence.modelExecution.taskStateAfterObservation = finalTask.state
1970
- context.evidence.modelExecution.taskCompleted = finalTask.state === 'COMPLETED'
1971
- check(`${scene.id}-real-omp-approved-model-proposal`, context.evidence.modelExecution.approvedProposalCount === 1 && context.evidence.modelExecution.approvedProposalValue === context.evidence.simulator.candidate, {
1972
- provider: REAL_OMP_PROVIDER,
1973
- model: REAL_OMP_MODEL,
1974
- selectedValue: context.evidence.modelExecution.approvedProposalValue,
1975
- toolEventHistoryAvailable: context.evidence.modelExecution.hostToolEventHistoryAvailable,
1976
- })
1977
- check(`${scene.id}-real-omp-one-recipe-trial-ledger`, context.evidence.hostToolExecution.recipeTrialCount === 1 && context.evidence.hostToolExecution.recipeTrialAckCount === 1, {
1978
- recipeTrialCount: context.evidence.hostToolExecution.recipeTrialCount,
1979
- recipeTrialAckCount: context.evidence.hostToolExecution.recipeTrialAckCount,
1980
- })
1981
- check(`${scene.id}-ack-verified`, context.evidence.trial.ackSummary.verified === 1 && context.evidence.trial.ackSummary.failed === 0, context.evidence.trial.ackSummary)
1982
- check(`${scene.id}-readback-matches`, context.evidence.readback.resultMatchesCandidate, context.evidence.readback)
1983
- check(`${scene.id}-run-tagged-daq-probe-ingest-snapshot`, context.evidence.daq.taggedQuery.seriesPointCount >= 1 && context.evidence.daq.taggedQuery.probeValueMatched, {
1984
- method: context.evidence.daq.method,
1985
- value: context.evidence.daq.probe.sampleValue,
1986
- runId: context.evidence.daq.expectedActiveRunId,
1987
- matchingPoint: context.evidence.daq.taggedQuery.matchingProbePoint,
1988
- })
1989
- check(`${scene.id}-recipe-log`, context.evidence.recipeLog.rowCount >= 2, { trialAction: context.evidence.recipeLog.trialAction, ackAction: context.evidence.recipeLog.ackAction })
1990
- check(`${scene.id}-real-omp-task-completed`, context.evidence.hostToolExecution.taskCompleted, {
1991
- taskState: context.evidence.hostToolExecution.taskStateAfterObservation,
1992
- })
1993
- context.evidence.status = 'verified'
1994
- outcome.status = context.evidence.hostToolExecution.taskCompleted ? 'verified' : 'verified-operation-task-incomplete'
1995
- outcome.finishedAt = new Date().toISOString()
1996
- outcome.trialRunId = context.evidence.trial.runId
1997
- outcome.taskState = context.evidence.hostToolExecution.taskStateAfterObservation
1998
- outcome.usage = context.evidence.modelExecution.usage
1999
- outcome.costUsd = null
2000
- outcome.evidenceSceneId = context.evidence.id
2001
- }
2002
- catch (error) {
2003
- context && (context.evidence.status = 'failed')
2004
- if (context) context.evidence.failure = compactError(error)
2005
- outcome.status = 'failed'
2006
- outcome.failure = compactError(error)
2007
- outcome.finishedAt = new Date().toISOString()
2008
- if (context) {
2009
- outcome.usage = await captureRealOmpUsage(context)
2010
- await recoverFailedRealOmpTrial(context, outcome)
2011
- }
2012
- }
2013
- }
2014
- }
2015
-
2016
- async function startApplication() {
2017
- currentStage = 'application-startup'
2018
- await assertFreeLoopback(OFFLINE_APP_MQTT_QUEUE_PORT, 'offline-app-mqtt-queue-probe-before-startup')
2019
- noteIsolation('offline-app-mqtt-queue-port-free-immediately-before-startup', true, {
2020
- port: OFFLINE_APP_MQTT_QUEUE_PORT,
2021
- host: '127.0.0.1',
2022
- })
2023
- appProcess = spawnLogged(process.execPath, [NUXT_CLI, 'dev', '--host', '127.0.0.1', '--port', String(AW_PORT), '--dotenv', EMPTY_DOTENV], {
2024
- cwd: REPO,
2025
- env: cleanChildEnv(),
2026
- logFd: APP_LOG_FD,
2027
- label: 'agentworkshop',
2028
- })
2029
- for (let i = 0; i < 90; i++) {
2030
- if (appProcess.exitCode !== null) throw new Error(`AgentWorkShop startup exited (code ${appProcess.exitCode})`)
2031
- try {
2032
- const response = await app('GET', '/api/health', undefined, { token: undefined, timeoutMs: 2_000 })
2033
- if (response.status === 200 && response.data?.status === 'ok' && response.data?.workshop === 'ready') {
2034
- if (response.data?.version !== '0.8.0') throw new Error(`server reported unexpected version ${safeText(response.data?.version, 80)}`)
2035
- noteIsolation('application-loopback-ready', true, { version: response.data.version, workshop: response.data.workshop, port: AW_PORT, host: '127.0.0.1' })
2036
- return response.data
2037
- }
2038
- }
2039
- catch (error) {
2040
- if (error?.message?.startsWith('server reported unexpected version')) throw error
2041
- }
2042
- await delay(500)
2043
- }
2044
- throw new Error('isolated AgentWorkShop startup timed out or workshop manager did not become ready')
2045
- }
2046
-
2047
- async function main() {
2048
- mkdirSync(join(REPO, '.omc'), { recursive: true })
2049
- if (VERSION !== '0.8.0') throw new Error(`expected current package version 0.8.0; found ${VERSION}`)
2050
- await preflight()
2051
- prepareIsolatedHome()
2052
- if (HARNESS_MODE === 'pi-local-fixture') {
2053
- await startPiModelFixture()
2054
- noteIsolation('registered-pi-fixture-configured', true, {
2055
- command: PI_COMMAND,
2056
- provider: PI_PROVIDER,
2057
- model: PI_MODEL,
2058
- localModelApi: `127.0.0.1:${MODEL_API_PORT}`,
2059
- noExternalProvider: true,
2060
- })
2061
- }
2062
- else if (HARNESS_MODE === 'fixture') {
2063
- currentStage = 'compile-local-omp-fixture-shim'
2064
- wrapperPath = buildHarnessShim()
2065
- noteIsolation('registered-omp-fixture-launcher-ready', true, { platform: process.platform, wrapper: 'local process shim; fixture is deterministic' })
2066
- }
2067
- else {
2068
- noteIsolation('registered-omp-real-provider-model-declared', true, {
2069
- command: 'omp from allowlisted PATH',
2070
- provider: REAL_OMP_PROVIDER,
2071
- model: REAL_OMP_MODEL,
2072
- cwd: 'fresh isolated AW_HOME',
2073
- authSource: 'local OMP auth store; value is not inspected or added to evidence',
2074
- discoveryDisabled: ['extensions', 'skills', 'rules'],
2075
- credentialValuesExposedToRunnerOrEvidence: false,
2076
- })
2077
- }
2078
- currentStage = 'simulator-startup'
2079
- await bootSimulator()
2080
- const health = await startApplication()
2081
- evidence.experiment.server = { version: health.version, mode: health.mode, workshop: health.workshop, uptimeMsAtReady: health.uptimeMs }
2082
- evidence.experiment.sourceIdentity = captureSourceIdentity()
2083
- const admin = await registerAdmin()
2084
- evidence.experiment.syntheticAdmin = admin
2085
- await assertPluginIsolation()
2086
- await verifyRagBridgeOutboundDisabled()
2087
- const daqStatus = requireSuccess(await app('GET', '/api/workshop/daq', undefined, { timeoutMs: 45_000 }), 'isolated DAQ backend status')
2088
- const settings = requireSuccess(await app('GET', '/api/system/settings'), 'effective runtime settings snapshot')
2089
- const effectiveMqttHost = settings.effective?.['daq.mqtt.host']
2090
- const effectiveMqttPort = Number(settings.effective?.['daq.mqtt.port'])
2091
- const effectiveMqttPortSource = settings.sources?.['daq.mqtt.port']
2092
- const effectiveInfrastructurePolicy = settings.effective?.['daq.startInfrastructure']
2093
- const effectiveInfrastructurePolicySource = settings.sources?.['daq.startInfrastructure']
2094
- const runtimeTargetMatches = effectiveMqttHost === '127.0.0.1'
2095
- && effectiveMqttPort === OFFLINE_APP_MQTT_QUEUE_PORT
2096
- && effectiveMqttPortSource === 'runtime'
2097
- && effectiveInfrastructurePolicy === 'never'
2098
- && effectiveInfrastructurePolicySource === 'runtime'
2099
- check('runtime-settings-target-offline-loopback-queue', runtimeTargetMatches, {
2100
- mqttHost: effectiveMqttHost ?? null,
2101
- mqttPort: effectiveMqttPort,
2102
- mqttPortSource: effectiveMqttPortSource ?? null,
2103
- infrastructurePolicy: effectiveInfrastructurePolicy ?? null,
2104
- infrastructurePolicySource: effectiveInfrastructurePolicySource ?? null,
2105
- })
2106
- check('isolated-inproc-queue-and-sqlite-tsdb', runtimeTargetMatches && daqStatus.meta?.queue === 'inproc' && daqStatus.meta?.tsdb === 'sqlite-emulated', {
2107
- queue: daqStatus.meta?.queue ?? null,
2108
- tsdb: daqStatus.meta?.tsdb ?? null,
2109
- effectiveMqttHost,
2110
- effectiveMqttPort,
2111
- effectiveMqttPortSource,
2112
- })
2113
- noteIsolation('application-message-path-is-inproc', runtimeTargetMatches && daqStatus.meta?.queue === 'inproc', {
2114
- queue: daqStatus.meta?.queue ?? null,
2115
- effectiveMqttHost,
2116
- effectiveMqttPort,
2117
- effectiveMqttPortSource: effectiveMqttPortSource ?? null,
2118
- simulatorMqttBrokerRemainsLoopback: `127.0.0.1:${MQTT_PORT}`,
2119
- })
2120
- evidence.isolation.result = 'passed'
2121
- noteIsolation('application-env-and-dotenv-isolation', true, {
2122
- launch: 'direct Nuxt CLI; dev-guard .env preload bypassed',
2123
- dotenvFile: EMPTY_DOTENV,
2124
- childEnvironmentAllowlisted: true,
2125
- storageEndpointsRestrictedToFreeLoopbackPorts: true,
2126
- })
2127
-
2128
- const scenes = [
2129
- {
2130
- id: 'cast-film', preset: 'cast-film-physics', sourceDevice: 'dev-extruder-opcua',
2131
- mvSignal: 'ScrewSpeedSP', cvSignal: 'thick', baseline: 120, fixtureCandidate: 125,
2132
- processDescription: 'cast-film extrusion; screw speed affects measured film thickness',
2133
- targetMin: 48, targetMax: 52,
2134
- candidates: [125, 130, 135],
2135
- },
2136
- {
2137
- id: 'annealing', preset: 'anneal-line', sourceDevice: 'anneal-heating-mbtcp',
2138
- mvSignal: '均热区3炉温SP', cvSignal: 'StripTemp', baseline: 730, fixtureCandidate: 735,
2139
- processDescription: 'continuous annealing; zone-3 furnace setpoint affects measured strip temperature',
2140
- targetMin: 700, targetMax: 760,
2141
- candidates: [735, 740, 745],
2142
- },
2143
- ]
2144
- if (HARNESS_MODE === 'real-omp') {
2145
- check('real-omp-six-unique-trials-planned', scenes.length * REAL_OMP_TRIALS_PER_SCENE === 6 && new Set(scenes.flatMap(scene => Array.from({ length: REAL_OMP_TRIALS_PER_SCENE }, (_, index) => `${scene.id}-r${index + 1}`))).size === 6, {
2146
- scenes: scenes.map(scene => scene.id),
2147
- repetitionsPerScene: REAL_OMP_TRIALS_PER_SCENE,
2148
- })
2149
- for (const scene of scenes) await runRealOmpScene(scene)
2150
- const failedRuns = evidence.experiment.runOutcomes.filter(outcome => outcome.status !== 'verified')
2151
- evidence.status = failedRuns.length === 0 ? 'passed' : 'failed'
2152
- if (failedRuns.length) {
2153
- evidence.failure = {
2154
- stage: 'real-omp-trial-set',
2155
- name: 'RealOmpTrialSetError',
2156
- message: `${failedRuns.length} of ${evidence.experiment.runOutcomes.length} bounded real OMP trials failed`,
2157
- failedRunIds: failedRuns.map(outcome => outcome.id),
2158
- }
2159
- evidence.isolation.result = 'incomplete'
2160
- }
2161
- }
2162
- else {
2163
- for (const scene of scenes) await runScene({ ...scene, candidate: scene.fixtureCandidate })
2164
- evidence.status = 'passed'
2165
- }
2166
- }
2167
-
2168
- async function cleanup() {
2169
- currentStage = 'cleanup'
2170
- const processResults = []
2171
- const processByChild = new Map()
2172
- if (appProcess) processByChild.set(appProcess, 'agentworkshop')
2173
- if (simProcess) processByChild.set(simProcess, 'simulator')
2174
- for (const child of children) if (!processByChild.has(child)) processByChild.set(child, child.label ?? 'child')
2175
- for (const [child, label] of [...processByChild.entries()].reverse()) {
2176
- try {
2177
- const stopped = await stopProcessTree(child, label)
2178
- processResults.push(stopped)
2179
- if (!evidence.checks.some(item => item.id === `${label}-process-stopped`)) {
2180
- evidence.checks.push({ id: `${label}-process-stopped`, status: 'fail', detail: { pid: child.pid ?? null, reason: 'process pid unavailable for termination verification' } })
2181
- }
2182
- }
2183
- catch (error) {
2184
- evidence.checks.push({ id: `${label}-process-stopped`, status: 'fail', detail: { pid: child.pid ?? null, error: compactError(error) } })
2185
- processResults.push(false)
2186
- }
2187
- }
2188
- if (piApiServer) {
2189
- try {
2190
- await new Promise((resolvePromise, reject) => {
2191
- piApiServer.close(error => error ? reject(error) : resolvePromise())
2192
- })
2193
- piApiServer = null
2194
- evidence.checks.push({ id: 'local-model-api-process-stopped', status: 'pass', detail: { host: '127.0.0.1', port: MODEL_API_PORT } })
2195
- }
2196
- catch (error) {
2197
- evidence.checks.push({ id: 'local-model-api-process-stopped', status: 'fail', detail: { error: compactError(error) } })
2198
- processResults.push(false)
2199
- }
2200
- }
2201
- const portResults = []
2202
- for (const [label, port] of [
2203
- ['app', AW_PORT],
2204
- ['simulator-http', SIM_PORT],
2205
- ['local-model-api', MODEL_API_PORT],
2206
- ['simulator-mqtt', MQTT_PORT],
2207
- ['offline-app-mqtt-queue-probe', OFFLINE_APP_MQTT_QUEUE_PORT],
2208
- ['offline-timescale-probe', OFFLINE_TSDB_PORT],
2209
- ['offline-objectstore-probe', OFFLINE_OBJECTSTORE_PORT],
2210
- ...allocatedDevicePorts.map((port, index) => [`simulator-device-${index}`, port]),
2211
- ]) {
2212
- try {
2213
- await assertFreeLoopback(port, label)
2214
- evidence.checks.push({ id: `${label}-port-released`, status: 'pass', detail: { port, host: '127.0.0.1' } })
2215
- portResults.push(true)
2216
- }
2217
- catch (error) {
2218
- evidence.checks.push({ id: `${label}-port-released`, status: 'fail', detail: { port, host: '127.0.0.1', error: compactError(error) } })
2219
- portResults.push(false)
2220
- }
2221
- }
2222
- try {
2223
- closeSync(SIM_LOG_FD)
2224
- }
2225
- catch { /* already closed */ }
2226
- try {
2227
- closeSync(APP_LOG_FD)
2228
- }
2229
- catch { /* already closed */ }
2230
- const requiredProcessLabels = evidence.status === 'passed' ? ['agentworkshop', 'simulator'] : [...processByChild.values()]
2231
- const verifiedProcessLabels = new Set(evidence.checks.filter(item => item.id.endsWith('-process-stopped') && item.status === 'pass').map(item => item.id.replace(/-process-stopped$/, '')))
2232
- const allRequiredProcessesVerified = requiredProcessLabels.every(label => verifiedProcessLabels.has(label))
2233
- return processResults.every(Boolean) && portResults.every(Boolean) && allRequiredProcessesVerified
2234
- }
2235
-
2236
- try {
2237
- await main()
2238
- }
2239
- catch (error) {
2240
- const preflightFailed = currentStage === 'preflight' || currentStage === 'compile-local-omp-fixture-shim' || currentStage === 'simulator-startup'
2241
- evidence.status = preflightFailed ? 'blocked' : 'failed'
2242
- evidence.failure = { stage: currentStage, scene: currentScene ?? null, ...compactError(error) }
2243
- if (evidence.isolation.result === 'pending') evidence.isolation.result = preflightFailed ? 'failed' : 'incomplete'
2244
- }
2245
- finally {
2246
- const cleanupPassed = await cleanup()
2247
- if (!cleanupPassed) {
2248
- evidence.status = 'failed'
2249
- evidence.isolation.result = 'failed'
2250
- evidence.failure ??= { stage: 'cleanup', name: 'CleanupVerificationError', message: 'process stop or loopback port release verification failed' }
2251
- evidence.failure.cleanupVerificationFailed = true
2252
- }
2253
- if (evidence.status === 'passed') {
2254
- const failedChecks = [...evidence.checks, ...evidence.isolation.checks].filter(item => item.status !== 'pass')
2255
- const cleanupChecks = evidence.checks.filter(item => RELEASE_CHECK_SUFFIXES.some(suffix => item.id.endsWith(suffix)))
2256
- if (failedChecks.length || !cleanupChecks.length || cleanupChecks.some(item => item.status !== 'pass')) {
2257
- evidence.status = 'failed'
2258
- evidence.isolation.result = 'failed'
2259
- evidence.failure ??= { stage: 'final-verification', name: 'FinalVerificationError', message: 'not all experiment and cleanup checks passed' }
2260
- }
2261
- }
2262
- evidence.cleanup = { status: cleanupPassed ? 'passed' : 'failed', requiredProcessAndPortChecks: true }
2263
- evidence.experiment.finishedAt = new Date().toISOString()
2264
- evidence.experiment.evidencePath = 'evidence.json'
2265
- evidence.experiment.runtimeLogPaths = { app: 'agentworkshop.log', simulator: 'simulator.log' }
2266
- evidence.experiment.modelApiTrace = piApiTrace
2267
- const sanitizeArchiveText = content => content
2268
- .replaceAll(ROOT, '<isolated-run>')
2269
- .replaceAll(HOME, '<isolated-home>')
2270
- .replaceAll(REPO, '<workspace>')
2271
- .replaceAll(PI_COMMAND, 'pi.cmd')
2272
- .replace(/[A-Za-z0-9._%+-]+@example\.invalid/gi, '<synthetic-admin>')
2273
- .replace(/[A-Z]:\\Users\\[^\\\s]+/gi, '<user-home>')
2274
- try {
2275
- mkdirSync(OUTPUT_DIR, { recursive: false })
2276
- writeFileSync(PI_API_TRACE_PATH, `${JSON.stringify(piApiTrace, null, 2)}\n`, 'utf8')
2277
- const archiveName = OUTPUT_DIR.slice(OUTPUT_DIR.lastIndexOf(sep) + 1)
2278
- evidence.experiment.archiveDirectory = archiveName
2279
- const archiveFiles = ['evidence.json', 'agentworkshop.log', 'simulator.log', 'pi-model-api-trace.json', 'e2e-pi-simulator-paper.mjs', 'README.md']
2280
- evidence.experiment.archiveFiles = archiveFiles
2281
- writeFileSync(EVIDENCE_PATH, `${JSON.stringify(evidence, null, 2)}\n`, 'utf8')
2282
- const archivedEvidence = `${sanitizeArchiveText(JSON.stringify(evidence, null, 2))}\n`
2283
- writeFileSync(join(OUTPUT_DIR, 'evidence.json'), archivedEvidence, 'utf8')
2284
- writeFileSync(join(OUTPUT_DIR, 'agentworkshop.log'), sanitizeArchiveText(readFileSync(APP_LOG, 'utf8')), 'utf8')
2285
- writeFileSync(join(OUTPUT_DIR, 'simulator.log'), sanitizeArchiveText(readFileSync(SIM_LOG, 'utf8')), 'utf8')
2286
- copyFileSync(PI_API_TRACE_PATH, join(OUTPUT_DIR, 'pi-model-api-trace.json'))
2287
- copyFileSync(fileURLToPath(import.meta.url), join(OUTPUT_DIR, 'e2e-pi-simulator-paper.mjs'))
2288
- const readme = [
2289
- '# R23 registered Pi CLI simulator evidence',
2290
- '',
2291
- `Run status: **${evidence.status}**.`,
2292
- '',
2293
- 'This archive was produced by a bounded local integration run of the registered Pi CLI adapter, its AgentWorkShop host-tool extension, the protected synthetic approval endpoint, and the loopback process simulator. The model endpoint is a deterministic OpenAI-compatible fixture bound to IPv4 loopback; no external model, provider, or service was called.',
2294
- '',
2295
- 'The fixture is scripted to issue one bounded `recipe_trial`, pass its returned host-tool result back into Pi, issue one explicit `complete_task`, and pass that result back into Pi. Device acknowledgement, direct readback, run-tagged DAQ sample persistence, task/approval/receipt/sample linkage, and process/port cleanup are recorded in `evidence.json` when observed.',
2296
- '',
2297
- 'The archived application and simulator logs contain runtime diagnostics with workspace and temporary-home paths and the synthetic admin email scrubbed. The Pi API trace contains request metadata and bounded tool-result text only; it omits prompts, credentials, session files, and the temporary isolated home.',
2298
- '',
2299
- evidence.failure ? `Recorded blocker/failure: ${safeText(evidence.failure.message, 500)} (stage: ${safeText(evidence.failure.stage, 120)}).` : 'No run blocker was recorded.',
2300
- '',
2301
- ].join('\n')
2302
- writeFileSync(join(OUTPUT_DIR, 'README.md'), readme, 'utf8')
2303
- writeFileSync(EVIDENCE_PATH, `${JSON.stringify(evidence, null, 2)}\n`, 'utf8')
2304
- writeFileSync(join(OUTPUT_DIR, 'evidence.json'), `${sanitizeArchiveText(JSON.stringify(evidence, null, 2))}\n`, 'utf8')
2305
- }
2306
- catch (error) {
2307
- evidence.status = 'failed'
2308
- evidence.failure ??= { stage: 'evidence-archive', ...compactError(error) }
2309
- writeFileSync(EVIDENCE_PATH, `${JSON.stringify(evidence, null, 2)}\n`, 'utf8')
2310
- }
2311
- console.log(`REGISTERED_HARNESS_E2E=${evidence.status}`)
2312
- console.log(`EVIDENCE=${join(OUTPUT_DIR, 'evidence.json')}`)
2313
- console.log(`STAGE=${evidence.failure?.stage ?? 'complete'}`)
2314
- }
2315
-
2316
- if (evidence.status !== 'passed') process.exitCode = evidence.status === 'blocked' ? 2 : 1