agentworkshop 0.8.2 → 0.8.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1646) 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/B4iJT5PX2.js +2 -0
  8. package/.output/public/_nuxt/{DuUc4bbY2.js → B9qIhT7k2.js} +1 -1
  9. package/.output/public/_nuxt/{BkEokGX5.js → BE9oKpOt.js} +1 -1
  10. package/.output/public/_nuxt/BNUaS1jv.js +20 -0
  11. package/.output/public/_nuxt/BhJA-E372.js +1 -0
  12. package/.output/public/_nuxt/Bq8YzXzs2.js +1 -0
  13. package/.output/public/_nuxt/{dHwWyr6b.js → CT4bi_Y4.js} +1 -1
  14. package/.output/public/_nuxt/{26OL4Ao82.js → CeCSjB9O2.js} +1 -1
  15. package/.output/public/_nuxt/Cf7ER7e2.js +1 -0
  16. package/.output/public/_nuxt/{Dyxf2xZw.js → Cot5VNae.js} +1 -1
  17. package/.output/public/_nuxt/{BVg2R2VB2.js → Crf8_Ad02.js} +1 -1
  18. package/.output/public/_nuxt/{rDvMijKA.js → D9tNM-1a.js} +2 -2
  19. package/.output/public/_nuxt/{YAA98rWJ.js → DAug2CPf.js} +7 -7
  20. package/.output/public/_nuxt/{DrlnrdvY2.js → DPnjnDtg.js} +1 -1
  21. package/.output/public/_nuxt/{CQSxS_Ek.js → DbhTN7-T.js} +1 -1
  22. package/.output/public/_nuxt/DgGzwjAr2.js +2 -0
  23. package/.output/public/_nuxt/DgTqKyYF2.js +1 -0
  24. package/.output/public/_nuxt/DkRozlDP2.js +1 -0
  25. package/.output/public/_nuxt/{Byiiiwc72.js → DxH5focQ.js} +1 -1
  26. package/.output/public/_nuxt/Dyr3LPGL.js +1 -0
  27. package/.output/public/_nuxt/{CC2Pv8VL2.js → MC_i34H42.js} +1 -1
  28. package/.output/public/_nuxt/MmlCf-EZ.js +1 -0
  29. package/.output/public/_nuxt/OmpTerminalPanel.DMWgGwDs.css +1 -0
  30. package/.output/public/_nuxt/PluginSlot.BqBzLD4T.css +1 -0
  31. package/.output/public/_nuxt/TownView.Cn8SPG7S.css +1 -0
  32. package/.output/public/_nuxt/{CmuGMxDP.js → TugRY_4O.js} +1 -1
  33. package/.output/public/_nuxt/{BPUQZ9Lq2.js → WybiLTow2.js} +1 -1
  34. package/.output/public/_nuxt/{BaYDgyaR.js → Zn0BZpf0.js} +3 -3
  35. package/.output/public/_nuxt/{_id_.BQRWK7J2.css → _id_.Be5JaH-P.css} +1 -1
  36. package/.output/public/_nuxt/{_wsId_.DCnKQQdY.css → _wsId_.p_vAYtTp.css} +1 -1
  37. package/.output/public/_nuxt/{agents.D-JPovTZ.css → agents.CRomddYR.css} +1 -1
  38. package/.output/public/_nuxt/aml.DgOMpDpv.css +1 -0
  39. package/.output/public/_nuxt/builds/latest.json +1 -1
  40. package/.output/public/_nuxt/builds/meta/8a151630-3285-41b8-a1e5-063fee2002ac.json +1 -0
  41. package/.output/public/_nuxt/{default.BEXGWZFQ.css → default.CpAx70gC.css} +1 -1
  42. package/.output/public/_nuxt/{entry.C7koBPom.css → entry.D6nBdXet.css} +1 -1
  43. package/.output/public/_nuxt/{logs.BkJPbR_K.css → logs.DcSvz6vi.css} +1 -1
  44. package/.output/public/_nuxt/{monitor.D3yEqqrv.css → monitor.OoNTwfMJ.css} +1 -1
  45. package/.output/public/_nuxt/ontology.D4P756Tc.css +1 -0
  46. package/.output/public/_nuxt/{operations.-l6u44Ar.css → operations.C48ggFa5.css} +1 -1
  47. package/.output/public/_nuxt/{pages.Cdpm_B-G.css → pages.Dpa28tJW.css} +1 -1
  48. package/.output/public/_nuxt/permissions.CrV-4t-6.css +1 -0
  49. package/.output/public/_nuxt/pipeline.NFs5z5V-.css +1 -0
  50. package/.output/public/_nuxt/{BfeXib9G.js → rcdmiszh2.js} +1 -1
  51. package/.output/public/_nuxt/schedules.DYWOjGHm.css +1 -0
  52. package/.output/public/_nuxt/{teams.CLQaXno5.css → teams.DEJoJ4QV.css} +1 -1
  53. package/.output/public/_nuxt/{tokens.BDSUWF-L.css → tokens.DKZWCP5v.css} +1 -1
  54. package/.output/public/_nuxt/tools.DP-nsTli.css +1 -0
  55. package/.output/public/_nuxt/wK6Pp4Zc2.js +2 -0
  56. package/.output/public/_nuxt/{workshop.BBiFhXuM.css → workshop.PT1xhP8C.css} +1 -1
  57. package/.output/public/favicon.svg +14 -14
  58. package/.output/public/robots.txt +3 -3
  59. package/.output/server/chunks/_/LeftOutlined.mjs.map +1 -1
  60. package/.output/server/chunks/_/RightOutlined.mjs.map +1 -1
  61. package/.output/server/chunks/_/SearchOutlined.mjs +1230 -1261
  62. package/.output/server/chunks/_/SearchOutlined.mjs.map +1 -1
  63. package/.output/server/chunks/_/character-asset.repo.mjs +1 -1
  64. package/.output/server/chunks/_/chart-repo.mjs +1 -1
  65. package/.output/server/chunks/_/chart-repo.mjs.map +1 -1
  66. package/.output/server/chunks/_/eda-db.mjs +12 -0
  67. package/.output/server/chunks/_/eda-db.mjs.map +1 -1
  68. package/.output/server/chunks/_/error-500.mjs.map +1 -1
  69. package/.output/server/chunks/_/host-bindings.mjs +1 -1
  70. package/.output/server/chunks/_/nitro.mjs +3258 -3313
  71. package/.output/server/chunks/_/nitro.mjs.map +1 -1
  72. package/.output/server/chunks/_/scene-layout.repo.mjs +1 -1
  73. package/.output/server/chunks/_/template-repo.mjs +97 -0
  74. package/.output/server/chunks/_/template-repo.mjs.map +1 -0
  75. package/.output/server/chunks/build/AuthGate-G74Wr5IV.mjs +704 -0
  76. package/.output/server/chunks/build/AuthGate-G74Wr5IV.mjs.map +1 -0
  77. package/.output/server/chunks/build/FormItemContext-DmuQqaeJ.mjs +77 -0
  78. package/.output/server/chunks/build/FormItemContext-DmuQqaeJ.mjs.map +1 -0
  79. package/.output/server/chunks/build/OmpTerminalPanel-5cB-78zp.mjs +889 -0
  80. package/.output/server/chunks/build/OmpTerminalPanel-5cB-78zp.mjs.map +1 -0
  81. package/.output/server/chunks/build/PluginSlot-CZlGlRoR.mjs +131 -0
  82. package/.output/server/chunks/build/PluginSlot-CZlGlRoR.mjs.map +1 -0
  83. package/.output/server/chunks/build/TownView-CcUPLqF1.mjs +5960 -0
  84. package/.output/server/chunks/build/TownView-CcUPLqF1.mjs.map +1 -0
  85. package/.output/server/chunks/build/_id_-AgACEyL6.mjs +1922 -0
  86. package/.output/server/chunks/build/_id_-AgACEyL6.mjs.map +1 -0
  87. package/.output/server/chunks/build/_id_-B3yCK2lD.mjs +373 -0
  88. package/.output/server/chunks/build/_id_-B3yCK2lD.mjs.map +1 -0
  89. package/.output/server/chunks/build/_wsId_-kcDriA4i.mjs +13707 -0
  90. package/.output/server/chunks/build/_wsId_-kcDriA4i.mjs.map +1 -0
  91. package/.output/server/chunks/build/agents-DRod4lTC.mjs +1047 -0
  92. package/.output/server/chunks/build/agents-DRod4lTC.mjs.map +1 -0
  93. package/.output/server/chunks/build/alert-CNGhs--Y.mjs +260 -0
  94. package/.output/server/chunks/build/alert-CNGhs--Y.mjs.map +1 -0
  95. package/.output/server/chunks/build/aml-B3Umz4DR.mjs +729 -0
  96. package/.output/server/chunks/build/aml-B3Umz4DR.mjs.map +1 -0
  97. package/.output/server/chunks/build/analysis-CMsMTMCg.mjs +502 -0
  98. package/.output/server/chunks/build/analysis-CMsMTMCg.mjs.map +1 -0
  99. package/.output/server/chunks/build/{api-B4Om0mEc.mjs → api-D-zkgkj-.mjs} +8 -10
  100. package/.output/server/chunks/build/api-D-zkgkj-.mjs.map +1 -0
  101. package/.output/server/chunks/build/{api-BsAgXWxi.mjs → api-D3gy2e2q.mjs} +22 -24
  102. package/.output/server/chunks/build/api-D3gy2e2q.mjs.map +1 -0
  103. package/.output/server/chunks/build/{api-BEW_ebY_.mjs → api-bn4OKkl_.mjs} +17 -19
  104. package/.output/server/chunks/build/api-bn4OKkl_.mjs.map +1 -0
  105. package/.output/server/chunks/build/api-error-CnW_xiNI.mjs +46 -0
  106. package/.output/server/chunks/build/api-error-CnW_xiNI.mjs.map +1 -0
  107. package/.output/server/chunks/build/apiClient-DIXx9sfD.mjs +70 -0
  108. package/.output/server/chunks/build/apiClient-DIXx9sfD.mjs.map +1 -0
  109. package/.output/server/chunks/build/board-B2oYXGBy.mjs +172 -0
  110. package/.output/server/chunks/build/board-B2oYXGBy.mjs.map +1 -0
  111. package/.output/server/chunks/build/builtin-catalog-edpDcgfL.mjs +81 -94
  112. package/.output/server/chunks/build/builtin-catalog-edpDcgfL.mjs.map +1 -1
  113. package/.output/server/chunks/build/card-BECE6y_G.mjs +922 -0
  114. package/.output/server/chunks/build/card-BECE6y_G.mjs.map +1 -0
  115. package/.output/server/chunks/build/channel-templates-R2TInv8B.mjs +950 -0
  116. package/.output/server/chunks/build/channel-templates-R2TInv8B.mjs.map +1 -0
  117. package/.output/server/chunks/build/chart-trend-BWeZh5Lv.mjs +113 -112
  118. package/.output/server/chunks/build/chart-trend-BWeZh5Lv.mjs.map +1 -1
  119. package/.output/server/chunks/build/checkbox-C6xY5uc6.mjs +429 -0
  120. package/.output/server/chunks/build/checkbox-C6xY5uc6.mjs.map +1 -0
  121. package/.output/server/chunks/build/client-only-S7k53PIm.mjs +42 -0
  122. package/.output/server/chunks/build/client-only-S7k53PIm.mjs.map +1 -0
  123. package/.output/server/chunks/build/constants-HPHJvjne.mjs +65 -75
  124. package/.output/server/chunks/build/constants-HPHJvjne.mjs.map +1 -1
  125. package/.output/server/chunks/build/core-CRlsQhzd.mjs +292 -0
  126. package/.output/server/chunks/build/core-CRlsQhzd.mjs.map +1 -0
  127. package/.output/server/chunks/build/daq-DFQQOtcZ.mjs +1210 -0
  128. package/.output/server/chunks/build/daq-DFQQOtcZ.mjs.map +1 -0
  129. package/.output/server/chunks/build/data-Cl4wRZO6.mjs +459 -0
  130. package/.output/server/chunks/build/data-Cl4wRZO6.mjs.map +1 -0
  131. package/.output/server/chunks/build/dcw-8415S3Km.mjs +467 -0
  132. package/.output/server/chunks/build/dcw-8415S3Km.mjs.map +1 -0
  133. package/.output/server/chunks/build/dcw-driver-badge-Df5wL_ZA.mjs +3 -15
  134. package/.output/server/chunks/build/dcw-driver-badge-Df5wL_ZA.mjs.map +1 -1
  135. package/.output/server/chunks/build/default-DDRKP2Mb.mjs +2246 -0
  136. package/.output/server/chunks/build/default-DDRKP2Mb.mjs.map +1 -0
  137. package/.output/server/chunks/build/descriptions-B3uhDesi.mjs +401 -0
  138. package/.output/server/chunks/build/descriptions-B3uhDesi.mjs.map +1 -0
  139. package/.output/server/chunks/build/drawer-DwXxapMg.mjs +822 -0
  140. package/.output/server/chunks/build/drawer-DwXxapMg.mjs.map +1 -0
  141. package/.output/server/chunks/build/dropdown-DLrGy-Fs.mjs +12 -0
  142. package/.output/server/chunks/build/dropdown-DLrGy-Fs.mjs.map +1 -0
  143. package/.output/server/chunks/build/dropdown-nsGv8Gqx.mjs +530 -0
  144. package/.output/server/chunks/build/dropdown-nsGv8Gqx.mjs.map +1 -0
  145. package/.output/server/chunks/build/{es-Bxu10NJ2.mjs → es-DXSEkmAm.mjs} +1 -2
  146. package/.output/server/chunks/build/es-DXSEkmAm.mjs.map +1 -0
  147. package/.output/server/chunks/build/firstNotUndefined-laiThpLD.mjs +2082 -0
  148. package/.output/server/chunks/build/firstNotUndefined-laiThpLD.mjs.map +1 -0
  149. package/.output/server/chunks/build/form-Cw2Ex9w5.mjs +3543 -0
  150. package/.output/server/chunks/build/form-Cw2Ex9w5.mjs.map +1 -0
  151. package/.output/server/chunks/build/hasIn-RYRGomyg.mjs +192 -0
  152. package/.output/server/chunks/build/hasIn-RYRGomyg.mjs.map +1 -0
  153. package/.output/server/chunks/build/hitl-B4cHRlkC.mjs +120 -0
  154. package/.output/server/chunks/build/hitl-B4cHRlkC.mjs.map +1 -0
  155. package/.output/server/chunks/build/input-CJgB-RL6.mjs +1705 -0
  156. package/.output/server/chunks/build/input-CJgB-RL6.mjs.map +1 -0
  157. package/.output/server/chunks/build/input-number-CQKL42p_.mjs +1027 -0
  158. package/.output/server/chunks/build/input-number-CQKL42p_.mjs.map +1 -0
  159. package/.output/server/chunks/build/interval-DiAUqODq.mjs +8 -0
  160. package/.output/server/chunks/build/interval-DiAUqODq.mjs.map +1 -0
  161. package/.output/server/chunks/build/isNumeric-DQiJ-b15.mjs +6 -0
  162. package/.output/server/chunks/build/isNumeric-DQiJ-b15.mjs.map +1 -0
  163. package/.output/server/chunks/build/logs-C-dWpJ80.mjs +381 -0
  164. package/.output/server/chunks/build/logs-C-dWpJ80.mjs.map +1 -0
  165. package/.output/server/chunks/build/menu-xO8ocVtL.mjs +1833 -0
  166. package/.output/server/chunks/build/menu-xO8ocVtL.mjs.map +1 -0
  167. package/.output/server/chunks/build/monitor-BNrG6v3b.mjs +2216 -0
  168. package/.output/server/chunks/build/monitor-BNrG6v3b.mjs.map +1 -0
  169. package/.output/server/chunks/build/narrow-fetch-CcG-BPxc.mjs +0 -2
  170. package/.output/server/chunks/build/narrow-fetch-CcG-BPxc.mjs.map +1 -1
  171. package/.output/server/chunks/build/ontology-DoXAsa2y.mjs +1416 -0
  172. package/.output/server/chunks/build/ontology-DoXAsa2y.mjs.map +1 -0
  173. package/.output/server/chunks/build/operations-Ch6tZIKo.mjs +278 -0
  174. package/.output/server/chunks/build/operations-Ch6tZIKo.mjs.map +1 -0
  175. package/.output/server/chunks/build/optimizer-DaTyaY3c.mjs +202 -0
  176. package/.output/server/chunks/build/optimizer-DaTyaY3c.mjs.map +1 -0
  177. package/.output/server/chunks/build/pages-CQOfwKB4.mjs +439 -0
  178. package/.output/server/chunks/build/pages-CQOfwKB4.mjs.map +1 -0
  179. package/.output/server/chunks/build/pagination-BTzq7dD5.mjs +1330 -0
  180. package/.output/server/chunks/build/pagination-BTzq7dD5.mjs.map +1 -0
  181. package/.output/server/chunks/build/permissions-qmimwB0M.mjs +649 -0
  182. package/.output/server/chunks/build/permissions-qmimwB0M.mjs.map +1 -0
  183. package/.output/server/chunks/build/pipeline-eo2RWN3f.mjs +226 -0
  184. package/.output/server/chunks/build/pipeline-eo2RWN3f.mjs.map +1 -0
  185. package/.output/server/chunks/build/plugins-Dh_goy-k.mjs +269 -0
  186. package/.output/server/chunks/build/plugins-Dh_goy-k.mjs.map +1 -0
  187. package/.output/server/chunks/build/popconfirm-DuGF7ty-.mjs +333 -0
  188. package/.output/server/chunks/build/popconfirm-DuGF7ty-.mjs.map +1 -0
  189. package/.output/server/chunks/build/responsiveObserve-CzRpNXkr.mjs +77 -0
  190. package/.output/server/chunks/build/responsiveObserve-CzRpNXkr.mjs.map +1 -0
  191. package/.output/server/chunks/build/schedules-C2_x38gj.mjs +7039 -0
  192. package/.output/server/chunks/build/schedules-C2_x38gj.mjs.map +1 -0
  193. package/.output/server/chunks/build/segmented-29uEKZ3D.mjs +332 -0
  194. package/.output/server/chunks/build/segmented-29uEKZ3D.mjs.map +1 -0
  195. package/.output/server/chunks/build/select-CJb2XrQf.mjs +3734 -0
  196. package/.output/server/chunks/build/select-CJb2XrQf.mjs.map +1 -0
  197. package/.output/server/chunks/build/settings-Cz2Plds0.mjs +944 -0
  198. package/.output/server/chunks/build/settings-Cz2Plds0.mjs.map +1 -0
  199. package/.output/server/chunks/build/space-BByD-mFE.mjs +107 -0
  200. package/.output/server/chunks/build/space-BByD-mFE.mjs.map +1 -0
  201. package/.output/server/chunks/build/spin-XhbgGeLP.mjs +313 -0
  202. package/.output/server/chunks/build/spin-XhbgGeLP.mjs.map +1 -0
  203. package/.output/server/chunks/build/studio-CwYXl00G.mjs +329 -0
  204. package/.output/server/chunks/build/studio-CwYXl00G.mjs.map +1 -0
  205. package/.output/server/chunks/build/switch-DWcwVFxW.mjs +374 -0
  206. package/.output/server/chunks/build/switch-DWcwVFxW.mjs.map +1 -0
  207. package/.output/server/chunks/build/table-Zhuo7Fq-.mjs +7249 -0
  208. package/.output/server/chunks/build/table-Zhuo7Fq-.mjs.map +1 -0
  209. package/.output/server/chunks/build/tabs-BCwBXjNt.mjs +1838 -0
  210. package/.output/server/chunks/build/tabs-BCwBXjNt.mjs.map +1 -0
  211. package/.output/server/chunks/build/tag-CRW-anwy.mjs +1010 -0
  212. package/.output/server/chunks/build/tag-CRW-anwy.mjs.map +1 -0
  213. package/.output/server/chunks/build/teams-CwhFdcYn.mjs +1160 -0
  214. package/.output/server/chunks/build/teams-CwhFdcYn.mjs.map +1 -0
  215. package/.output/server/chunks/build/tokens-C5ODO1HA.mjs +992 -0
  216. package/.output/server/chunks/build/tokens-C5ODO1HA.mjs.map +1 -0
  217. package/.output/server/chunks/build/tools-C0YKragH.mjs +487 -0
  218. package/.output/server/chunks/build/tools-C0YKragH.mjs.map +1 -0
  219. package/.output/server/chunks/build/tooltip-GlMrUZzx.mjs +888 -0
  220. package/.output/server/chunks/build/tooltip-GlMrUZzx.mjs.map +1 -0
  221. package/.output/server/chunks/build/town-BV-hbwb5.mjs +16 -29
  222. package/.output/server/chunks/build/town-BV-hbwb5.mjs.map +1 -1
  223. package/.output/server/chunks/build/town-DLFB4SZl.mjs +117 -0
  224. package/.output/server/chunks/build/town-DLFB4SZl.mjs.map +1 -0
  225. package/.output/server/chunks/build/types-D6J7slEa.mjs.map +1 -1
  226. package/.output/server/chunks/build/types-DWqIeMRP.mjs +28 -29
  227. package/.output/server/chunks/build/types-DWqIeMRP.mjs.map +1 -1
  228. package/.output/server/chunks/build/useAgentHarnessOptions-CYKuLtZ2.mjs +120 -0
  229. package/.output/server/chunks/build/useAgentHarnessOptions-CYKuLtZ2.mjs.map +1 -0
  230. package/.output/server/chunks/build/useAgentTemplateActions-Da_V1LSD.mjs +71 -0
  231. package/.output/server/chunks/build/useAgentTemplateActions-Da_V1LSD.mjs.map +1 -0
  232. package/.output/server/chunks/build/useAgentTemplateDialogState-CZzpu5og.mjs +16 -23
  233. package/.output/server/chunks/build/useAgentTemplateDialogState-CZzpu5og.mjs.map +1 -1
  234. package/.output/server/chunks/build/useAgentTemplateForm-BWvax5_E.mjs +112 -0
  235. package/.output/server/chunks/build/useAgentTemplateForm-BWvax5_E.mjs.map +1 -0
  236. package/.output/server/chunks/build/useAgentTemplatesCatalog-BnYjZy59.mjs +140 -0
  237. package/.output/server/chunks/build/useAgentTemplatesCatalog-BnYjZy59.mjs.map +1 -0
  238. package/.output/server/chunks/build/useAmlDatasets-nGi10DAl.mjs +88 -0
  239. package/.output/server/chunks/build/useAmlDatasets-nGi10DAl.mjs.map +1 -0
  240. package/.output/server/chunks/build/useAmlEntities-CTgNAgcZ.mjs +79 -0
  241. package/.output/server/chunks/build/useAmlEntities-CTgNAgcZ.mjs.map +1 -0
  242. package/.output/server/chunks/build/useAmlEnv-Da2TVfyK.mjs +188 -0
  243. package/.output/server/chunks/build/useAmlEnv-Da2TVfyK.mjs.map +1 -0
  244. package/.output/server/chunks/build/useAmlExperiments-U9AQ52RI.mjs +86 -0
  245. package/.output/server/chunks/build/useAmlExperiments-U9AQ52RI.mjs.map +1 -0
  246. package/.output/server/chunks/build/useAmlFormat-C2sl3MGB.mjs +32 -37
  247. package/.output/server/chunks/build/useAmlFormat-C2sl3MGB.mjs.map +1 -1
  248. package/.output/server/chunks/build/useAmlJobs-BM1mu5iH.mjs +251 -0
  249. package/.output/server/chunks/build/useAmlJobs-BM1mu5iH.mjs.map +1 -0
  250. package/.output/server/chunks/build/useAmlModels-C1DwIOMi.mjs +90 -0
  251. package/.output/server/chunks/build/useAmlModels-C1DwIOMi.mjs.map +1 -0
  252. package/.output/server/chunks/build/useAmlNotes-CNm47QdS.mjs +80 -0
  253. package/.output/server/chunks/build/useAmlNotes-CNm47QdS.mjs.map +1 -0
  254. package/.output/server/chunks/build/useAmlPredict-m8I1AdRn.mjs +126 -0
  255. package/.output/server/chunks/build/useAmlPredict-m8I1AdRn.mjs.map +1 -0
  256. package/.output/server/chunks/build/useAnalysisFeed-CpbOaiBD.mjs +120 -0
  257. package/.output/server/chunks/build/useAnalysisFeed-CpbOaiBD.mjs.map +1 -0
  258. package/.output/server/chunks/build/useDaqAddNode-D_1EBuR3.mjs +141 -0
  259. package/.output/server/chunks/build/useDaqAddNode-D_1EBuR3.mjs.map +1 -0
  260. package/.output/server/chunks/build/useDaqDetailBinding-j05iSApd.mjs +72 -0
  261. package/.output/server/chunks/build/useDaqDetailBinding-j05iSApd.mjs.map +1 -0
  262. package/.output/server/chunks/build/useDaqDetailFrames-BKciVJ78.mjs +78 -0
  263. package/.output/server/chunks/build/useDaqDetailFrames-BKciVJ78.mjs.map +1 -0
  264. package/.output/server/chunks/build/useDaqDetailHistory-DgemICkr.mjs +166 -0
  265. package/.output/server/chunks/build/useDaqDetailHistory-DgemICkr.mjs.map +1 -0
  266. package/.output/server/chunks/build/useDaqDetailNode-Cn7_og6t.mjs +103 -0
  267. package/.output/server/chunks/build/useDaqDetailNode-Cn7_og6t.mjs.map +1 -0
  268. package/.output/server/chunks/build/useDaqDetailParams-DX_vjFyK.mjs +157 -0
  269. package/.output/server/chunks/build/useDaqDetailParams-DX_vjFyK.mjs.map +1 -0
  270. package/.output/server/chunks/build/useDaqFilters-DMS4GN20.mjs +224 -0
  271. package/.output/server/chunks/build/useDaqFilters-DMS4GN20.mjs.map +1 -0
  272. package/.output/server/chunks/build/useDaqNodeWindow-1DWj2H5G.mjs +43 -44
  273. package/.output/server/chunks/build/useDaqNodeWindow-1DWj2H5G.mjs.map +1 -1
  274. package/.output/server/chunks/build/useDaqOptimizations-OPbdy5YB.mjs +132 -0
  275. package/.output/server/chunks/build/useDaqOptimizations-OPbdy5YB.mjs.map +1 -0
  276. package/.output/server/chunks/build/useDaqStream-CS1G6iro.mjs +385 -0
  277. package/.output/server/chunks/build/useDaqStream-CS1G6iro.mjs.map +1 -0
  278. package/.output/server/chunks/build/useDaqTemplates-DqhRYo88.mjs +181 -0
  279. package/.output/server/chunks/build/useDaqTemplates-DqhRYo88.mjs.map +1 -0
  280. package/.output/server/chunks/build/useDashboardCharts-D45083s_.mjs +312 -310
  281. package/.output/server/chunks/build/useDashboardCharts-D45083s_.mjs.map +1 -1
  282. package/.output/server/chunks/build/useDashboardData-CeaMjEA9.mjs +139 -0
  283. package/.output/server/chunks/build/useDashboardData-CeaMjEA9.mjs.map +1 -0
  284. package/.output/server/chunks/build/useDcwAddNode-Cytz_odQ.mjs +217 -0
  285. package/.output/server/chunks/build/useDcwAddNode-Cytz_odQ.mjs.map +1 -0
  286. package/.output/server/chunks/build/{useDcwCards-SaiImIYQ.mjs → useDcwCards-BKCFqkRd.mjs} +20 -23
  287. package/.output/server/chunks/build/useDcwCards-BKCFqkRd.mjs.map +1 -0
  288. package/.output/server/chunks/build/useDcwDetailScope-CvdvcKAv.mjs +184 -0
  289. package/.output/server/chunks/build/useDcwDetailScope-CvdvcKAv.mjs.map +1 -0
  290. package/.output/server/chunks/build/useDcwDetailTemplates-CC2FcEge.mjs +143 -0
  291. package/.output/server/chunks/build/useDcwDetailTemplates-CC2FcEge.mjs.map +1 -0
  292. package/.output/server/chunks/build/useDcwFilter-CVoiXbZh.mjs +65 -0
  293. package/.output/server/chunks/build/useDcwFilter-CVoiXbZh.mjs.map +1 -0
  294. package/.output/server/chunks/build/{useDcwLedger-0ie-0WTc.mjs → useDcwLedger-Cd-ckHoJ.mjs} +29 -35
  295. package/.output/server/chunks/build/useDcwLedger-Cd-ckHoJ.mjs.map +1 -0
  296. package/.output/server/chunks/build/useDcwLineMutations-BOQs-fw3.mjs +133 -0
  297. package/.output/server/chunks/build/useDcwLineMutations-BOQs-fw3.mjs.map +1 -0
  298. package/.output/server/chunks/build/useDcwLineRun-D9qvcyTM.mjs +100 -0
  299. package/.output/server/chunks/build/useDcwLineRun-D9qvcyTM.mjs.map +1 -0
  300. package/.output/server/chunks/build/useDcwParamApprovals-D36q4can.mjs +119 -0
  301. package/.output/server/chunks/build/useDcwParamApprovals-D36q4can.mjs.map +1 -0
  302. package/.output/server/chunks/build/useDcwProducts-BozctrwT.mjs +88 -0
  303. package/.output/server/chunks/build/useDcwProducts-BozctrwT.mjs.map +1 -0
  304. package/.output/server/chunks/build/useDcwQuery-C8FikKgu.mjs +93 -0
  305. package/.output/server/chunks/build/useDcwQuery-C8FikKgu.mjs.map +1 -0
  306. package/.output/server/chunks/build/useDcwQuickActions-IyQ8Rkpe.mjs +84 -0
  307. package/.output/server/chunks/build/useDcwQuickActions-IyQ8Rkpe.mjs.map +1 -0
  308. package/.output/server/chunks/build/useDcwRecipes-k9HGhMwF.mjs +263 -0
  309. package/.output/server/chunks/build/useDcwRecipes-k9HGhMwF.mjs.map +1 -0
  310. package/.output/server/chunks/build/useDcwStream-BnBOiawo.mjs +455 -0
  311. package/.output/server/chunks/build/useDcwStream-BnBOiawo.mjs.map +1 -0
  312. package/.output/server/chunks/build/useDcwTemplates-CnyYOOy0.mjs +87 -0
  313. package/.output/server/chunks/build/useDcwTemplates-CnyYOOy0.mjs.map +1 -0
  314. package/.output/server/chunks/build/useDcwWrites-Cco590iv.mjs +136 -0
  315. package/.output/server/chunks/build/useDcwWrites-Cco590iv.mjs.map +1 -0
  316. package/.output/server/chunks/build/useDeviceTwins-DL-VLFeX.mjs +118 -0
  317. package/.output/server/chunks/build/useDeviceTwins-DL-VLFeX.mjs.map +1 -0
  318. package/.output/server/chunks/build/useExpConfirmations-DgwqTb9O.mjs +104 -0
  319. package/.output/server/chunks/build/useExpConfirmations-DgwqTb9O.mjs.map +1 -0
  320. package/.output/server/chunks/build/useLocalTime-C__kwn8h.mjs +52 -0
  321. package/.output/server/chunks/build/useLocalTime-C__kwn8h.mjs.map +1 -0
  322. package/.output/server/chunks/build/useLogsFormat-B-o4MHy7.mjs +30 -33
  323. package/.output/server/chunks/build/useLogsFormat-B-o4MHy7.mjs.map +1 -1
  324. package/.output/server/chunks/build/useLogsManual-BcfanT0s.mjs +80 -0
  325. package/.output/server/chunks/build/useLogsManual-BcfanT0s.mjs.map +1 -0
  326. package/.output/server/chunks/build/useLogsQuery-BGlKVKpV.mjs +136 -0
  327. package/.output/server/chunks/build/useLogsQuery-BGlKVKpV.mjs.map +1 -0
  328. package/.output/server/chunks/build/useLogsScope-C-yrta-v.mjs +75 -0
  329. package/.output/server/chunks/build/useLogsScope-C-yrta-v.mjs.map +1 -0
  330. package/.output/server/chunks/build/useMonitorColumns-vVnt3r5Q.mjs +155 -166
  331. package/.output/server/chunks/build/useMonitorColumns-vVnt3r5Q.mjs.map +1 -1
  332. package/.output/server/chunks/build/useMonitorData-BUey2Xly.mjs +128 -0
  333. package/.output/server/chunks/build/useMonitorData-BUey2Xly.mjs.map +1 -0
  334. package/.output/server/chunks/build/useMonitorFormat-rhs7FlNo.mjs +77 -0
  335. package/.output/server/chunks/build/useMonitorFormat-rhs7FlNo.mjs.map +1 -0
  336. package/.output/server/chunks/build/useMonitorTerminal-Dj4QwRNW.mjs +20 -27
  337. package/.output/server/chunks/build/useMonitorTerminal-Dj4QwRNW.mjs.map +1 -1
  338. package/.output/server/chunks/build/useOperationsFeed-DWfCjP4l.mjs +182 -0
  339. package/.output/server/chunks/build/useOperationsFeed-DWfCjP4l.mjs.map +1 -0
  340. package/.output/server/chunks/build/useOpsLog--yf8erUi.mjs +139 -0
  341. package/.output/server/chunks/build/useOpsLog--yf8erUi.mjs.map +1 -0
  342. package/.output/server/chunks/build/useRecipeDispatchApprovals-CKF2sB9P.mjs +146 -0
  343. package/.output/server/chunks/build/useRecipeDispatchApprovals-CKF2sB9P.mjs.map +1 -0
  344. package/.output/server/chunks/build/useResponsive-BKDMGTHs.mjs +23 -39
  345. package/.output/server/chunks/build/useResponsive-BKDMGTHs.mjs.map +1 -1
  346. package/.output/server/chunks/build/useTeamActions-C08sAVqY.mjs +71 -0
  347. package/.output/server/chunks/build/useTeamActions-C08sAVqY.mjs.map +1 -0
  348. package/.output/server/chunks/build/useTeamAddMemberDialog-fzTmflr8.mjs +78 -0
  349. package/.output/server/chunks/build/useTeamAddMemberDialog-fzTmflr8.mjs.map +1 -0
  350. package/.output/server/chunks/build/useTeamCreateDialog-De63ep-X.mjs +91 -0
  351. package/.output/server/chunks/build/useTeamCreateDialog-De63ep-X.mjs.map +1 -0
  352. package/.output/server/chunks/build/useTeamDeployDialog-CpAtG5Jy.mjs +76 -0
  353. package/.output/server/chunks/build/useTeamDeployDialog-CpAtG5Jy.mjs.map +1 -0
  354. package/.output/server/chunks/build/useTeamDialogState-CFRUQxAf.mjs +31 -38
  355. package/.output/server/chunks/build/useTeamDialogState-CFRUQxAf.mjs.map +1 -1
  356. package/.output/server/chunks/build/useTeamPluginDialog-C1OOe1sL.mjs +99 -0
  357. package/.output/server/chunks/build/useTeamPluginDialog-C1OOe1sL.mjs.map +1 -0
  358. package/.output/server/chunks/build/useTeamsCatalog-DA41SMDu.mjs +124 -0
  359. package/.output/server/chunks/build/useTeamsCatalog-DA41SMDu.mjs.map +1 -0
  360. package/.output/server/chunks/build/useTokenClipboard-CwQpoFeP.mjs +21 -28
  361. package/.output/server/chunks/build/useTokenClipboard-CwQpoFeP.mjs.map +1 -1
  362. package/.output/server/chunks/build/useTokenCreate-XHTQExra.mjs +106 -0
  363. package/.output/server/chunks/build/useTokenCreate-XHTQExra.mjs.map +1 -0
  364. package/.output/server/chunks/build/useTokenRename-Cf1B0cRy.mjs +81 -0
  365. package/.output/server/chunks/build/useTokenRename-Cf1B0cRy.mjs.map +1 -0
  366. package/.output/server/chunks/build/useTokenReveal-C8n1Vt9t.mjs +108 -0
  367. package/.output/server/chunks/build/useTokenReveal-C8n1Vt9t.mjs.map +1 -0
  368. package/.output/server/chunks/build/useTokensList-MMIq24E-.mjs +86 -0
  369. package/.output/server/chunks/build/useTokensList-MMIq24E-.mjs.map +1 -0
  370. package/.output/server/chunks/build/useTownBus-D9SoIsAN.mjs +16 -17
  371. package/.output/server/chunks/build/useTownBus-D9SoIsAN.mjs.map +1 -1
  372. package/.output/server/chunks/build/useWorkbenchAuth-Dyc_czui.mjs +131 -0
  373. package/.output/server/chunks/build/useWorkbenchAuth-Dyc_czui.mjs.map +1 -0
  374. package/.output/server/chunks/build/useWorkbenchWorkspaces-DT33HbBD.mjs +128 -0
  375. package/.output/server/chunks/build/useWorkbenchWorkspaces-DT33HbBD.mjs.map +1 -0
  376. package/.output/server/chunks/build/useWorkshopApi-BkEgGBIM.mjs +118 -0
  377. package/.output/server/chunks/build/useWorkshopApi-BkEgGBIM.mjs.map +1 -0
  378. package/.output/server/chunks/build/useWorkshopWs-BWrVj4jL.mjs +1577 -0
  379. package/.output/server/chunks/build/useWorkshopWs-BWrVj4jL.mjs.map +1 -0
  380. package/.output/server/chunks/build/{useWorkspaceAuth-Dlvj9csD.mjs → useWorkspaceAuth-TahC9EC7.mjs} +4 -16
  381. package/.output/server/chunks/build/useWorkspaceAuth-TahC9EC7.mjs.map +1 -0
  382. package/.output/server/chunks/build/useWorkspaceChannels-BVAHmhN3.mjs +94 -0
  383. package/.output/server/chunks/build/useWorkspaceChannels-BVAHmhN3.mjs.map +1 -0
  384. package/.output/server/chunks/build/useWorkspacePanels-CTwREmq0.mjs +30 -33
  385. package/.output/server/chunks/build/useWorkspacePanels-CTwREmq0.mjs.map +1 -1
  386. package/.output/server/chunks/build/useWorkspaceShell-rQHWNNWJ.mjs +150 -0
  387. package/.output/server/chunks/build/useWorkspaceShell-rQHWNNWJ.mjs.map +1 -0
  388. package/.output/server/chunks/build/users-pVCK50z-.mjs +566 -0
  389. package/.output/server/chunks/build/users-pVCK50z-.mjs.map +1 -0
  390. package/.output/server/chunks/build/workshop-DAgsBgG4.mjs +499 -0
  391. package/.output/server/chunks/build/workshop-DAgsBgG4.mjs.map +1 -0
  392. package/.output/server/chunks/build/workspaces-CmW0cpOt.mjs +111 -121
  393. package/.output/server/chunks/build/workspaces-CmW0cpOt.mjs.map +1 -1
  394. package/.output/server/chunks/routes/api/workshop/assets/index.post.mjs +1 -1
  395. package/.output/server/chunks/routes/api/workshop/assets/index2.post.mjs +1 -1
  396. package/.output/server/chunks/routes/api/workshop/channel-templates/_id/instantiate.post.mjs +1 -1
  397. package/.output/server/chunks/routes/api/workshop/channels/_id/activate.post.mjs +1 -1
  398. package/.output/server/chunks/routes/api/workshop/channels/_id/chat/index.post.mjs +1 -1
  399. package/.output/server/chunks/routes/api/workshop/channels/_id/index.post.mjs +1 -1
  400. package/.output/server/chunks/routes/api/workshop/channels/_id/index3.post.mjs +1 -1
  401. package/.output/server/chunks/routes/api/workshop/channels/_id/index4.post.mjs +1 -1
  402. package/.output/server/chunks/routes/api/workshop/channels/_id/line.put.mjs +1 -1
  403. package/.output/server/chunks/routes/api/workshop/channels/index.get.mjs +1 -1
  404. package/.output/server/chunks/routes/api/workshop/channels.post.mjs +1 -1
  405. package/.output/server/chunks/routes/api/workshop/dcw/lines/_id_.delete.mjs +1 -1
  406. package/.output/server/chunks/routes/api/workshop/eda/index8.get.mjs +33 -0
  407. package/.output/server/chunks/routes/api/workshop/eda/index8.get.mjs.map +1 -0
  408. package/.output/server/chunks/routes/api/workshop/eda/index8.post.mjs +41 -0
  409. package/.output/server/chunks/routes/api/workshop/eda/index8.post.mjs.map +1 -0
  410. package/.output/server/chunks/routes/api/workshop/eda/templates/_id_.delete.mjs +36 -0
  411. package/.output/server/chunks/routes/api/workshop/eda/templates/_id_.delete.mjs.map +1 -0
  412. package/.output/server/chunks/routes/api/workshop/eda/templates/_id_.get.mjs +37 -0
  413. package/.output/server/chunks/routes/api/workshop/eda/templates/_id_.get.mjs.map +1 -0
  414. package/.output/server/chunks/routes/api/workshop/eda/templates/_id_.patch.mjs +42 -0
  415. package/.output/server/chunks/routes/api/workshop/eda/templates/_id_.patch.mjs.map +1 -0
  416. package/.output/server/chunks/routes/api/workshop/index10.post.mjs +33 -0
  417. package/.output/server/chunks/routes/api/workshop/index10.post.mjs.map +1 -0
  418. package/.output/server/chunks/routes/api/workshop/index2.post.mjs +45 -46
  419. package/.output/server/chunks/routes/api/workshop/index2.post.mjs.map +1 -1
  420. package/.output/server/chunks/routes/api/workshop/index3.post.mjs +46 -23
  421. package/.output/server/chunks/routes/api/workshop/index3.post.mjs.map +1 -1
  422. package/.output/server/chunks/routes/api/workshop/index4.post.mjs +10 -9
  423. package/.output/server/chunks/routes/api/workshop/index4.post.mjs.map +1 -1
  424. package/.output/server/chunks/routes/api/workshop/index5.post.mjs +22 -19
  425. package/.output/server/chunks/routes/api/workshop/index5.post.mjs.map +1 -1
  426. package/.output/server/chunks/routes/api/workshop/index6.post.mjs +18 -42
  427. package/.output/server/chunks/routes/api/workshop/index6.post.mjs.map +1 -1
  428. package/.output/server/chunks/routes/api/workshop/index7.post.mjs +43 -17
  429. package/.output/server/chunks/routes/api/workshop/index7.post.mjs.map +1 -1
  430. package/.output/server/chunks/routes/api/workshop/index8.post.mjs +13 -15
  431. package/.output/server/chunks/routes/api/workshop/index8.post.mjs.map +1 -1
  432. package/.output/server/chunks/routes/api/workshop/index9.post.mjs +18 -4
  433. package/.output/server/chunks/routes/api/workshop/index9.post.mjs.map +1 -1
  434. package/.output/server/chunks/routes/api/workshop/process-model/datasets.post.mjs +1 -1
  435. package/.output/server/chunks/routes/api/workshop/process-model/eligibility.mjs +1 -1
  436. package/.output/server/chunks/routes/api/workshop/process-model/experiments.mjs +1 -1
  437. package/.output/server/chunks/routes/api/workshop/teams/_id/deploy.post.mjs +1 -1
  438. package/.output/server/chunks/routes/api/workshop/workspaces/_id/channel-templates/_tplId_.post.mjs +1 -1
  439. package/.output/server/chunks/routes/renderer.mjs +1 -1
  440. package/.output/server/chunks/routes/renderer.mjs.map +1 -1
  441. package/.output/server/chunks/virtual/entry.mjs +9581 -10848
  442. package/.output/server/chunks/virtual/entry.mjs.map +1 -1
  443. package/.output/server/chunks/virtual/precomputed.mjs +1 -1
  444. package/.output/server/chunks/virtual/precomputed.mjs.map +1 -1
  445. package/.output/server/package.json +1 -1
  446. package/README-zh.md +8 -5
  447. package/README.md +9 -6
  448. package/app/components/AwChart.vue +14 -0
  449. package/app/components/AwLogo.vue +75 -75
  450. package/app/components/aml/AmlDatasetFormModal.vue +279 -279
  451. package/app/components/aml/AmlDatasetTable.vue +319 -319
  452. package/app/components/aml/AmlExperimentsTable.vue +142 -142
  453. package/app/components/aml/AmlInfraBanner.vue +23 -23
  454. package/app/components/aml/AmlJobsTable.vue +248 -248
  455. package/app/components/aml/AmlOverviewBar.vue +62 -62
  456. package/app/components/aml/AmlPageHeader.vue +47 -47
  457. package/app/components/aml/AmlPredictConsole.vue +201 -201
  458. package/app/components/app-header/HitlBell.vue +423 -423
  459. package/app/components/daq/DaqAddNodeModal.vue +209 -209
  460. package/app/components/daq/DaqAlarmBar.vue +46 -46
  461. package/app/components/daq/DaqControlCard.vue +159 -159
  462. package/app/components/daq/DaqInfraBanner.vue +31 -31
  463. package/app/components/daq/DaqLineBanner.vue +47 -47
  464. package/app/components/daq/DaqNodePanel.vue +396 -396
  465. package/app/components/daq/DaqOptPanel.vue +197 -197
  466. package/app/components/daq/DaqTemplateModal.vue +246 -246
  467. package/app/components/dashboard/DashboardGaugeBand.vue +78 -78
  468. package/app/components/dashboard/DashboardHero.vue +209 -209
  469. package/app/components/dashboard/DashboardLineStatePanel.vue +78 -78
  470. package/app/components/dashboard/DashboardNodeStatePanel.vue +46 -46
  471. package/app/components/dashboard/DashboardPipelinePanel.vue +46 -46
  472. package/app/components/dashboard/DashboardTrendPanel.vue +83 -83
  473. package/app/components/dashboard/DashboardWritePanel.vue +52 -52
  474. package/app/components/dcw/DcwCreateLineModal.vue +105 -105
  475. package/app/components/dcw/DcwDeleteLineModal.vue +73 -73
  476. package/app/components/dcw/DcwDetailTemplateModal.vue +238 -238
  477. package/app/components/dcw/DcwLedgerCard.vue +160 -160
  478. package/app/components/dcw/DcwMesArtifacts.vue +140 -140
  479. package/app/components/dcw/DcwProductCreateModal.vue +113 -113
  480. package/app/components/dcw/DcwRecipeDispatchHistoryModal.vue +244 -244
  481. package/app/components/dcw/DcwRecipeEditModal.vue +399 -399
  482. package/app/components/dcw/DcwRecipeHistoryModal.vue +165 -165
  483. package/app/components/dcw/DcwRunDataModal.vue +191 -191
  484. package/app/components/dcw/DcwTemplateModal.vue +227 -227
  485. package/app/components/dcw/DcwWriteHistoryCard.vue +96 -96
  486. package/app/components/dcw/ExpConfirmCard.vue +103 -103
  487. package/app/components/dcw/RecipeDispatchApprovalCard.vue +330 -330
  488. package/app/components/logs/LogsPageHead.vue +71 -71
  489. package/app/components/monitor/MonitorAgentTable.vue +143 -143
  490. package/app/components/monitor/MonitorChannelTable.vue +80 -80
  491. package/app/components/monitor/MonitorLoginGate.vue +24 -24
  492. package/app/components/monitor/MonitorPageHead.vue +92 -92
  493. package/app/components/monitor/MonitorProcessTable.vue +159 -159
  494. package/app/components/ontology/OntologyGraph.vue +356 -356
  495. package/app/components/operations/OperationsFilterCard.vue +164 -164
  496. package/app/components/operations/OperationsPageHead.vue +47 -47
  497. package/app/components/tokens/TokenCreateModal.vue +42 -42
  498. package/app/components/tokens/TokenOnceModal.vue +164 -164
  499. package/app/components/tokens/TokenRenameModal.vue +40 -40
  500. package/app/components/tokens/TokensPageHead.vue +76 -76
  501. package/app/components/workshop/A2aRpcDebugger.vue +237 -237
  502. package/app/components/workshop/AgentInspectorDrawer.vue +424 -424
  503. package/app/components/workshop/AgentLanesView.vue +278 -278
  504. package/app/components/workshop/ArtifactCard.vue +120 -120
  505. package/app/components/workshop/AssetLibrary.vue +452 -452
  506. package/app/components/workshop/ChatMemberPanel.vue +556 -556
  507. package/app/components/workshop/CommandPalette.vue +270 -270
  508. package/app/components/workshop/Composer.vue +540 -540
  509. package/app/components/workshop/DaqTemplateIcon.vue +33 -33
  510. package/app/components/workshop/DeviceTwinPanel.vue +167 -167
  511. package/app/components/workshop/FileSelectorModal.vue +188 -188
  512. package/app/components/workshop/InspectorPanel.vue +301 -301
  513. package/app/components/workshop/PluginSlot.vue +120 -120
  514. package/app/components/workshop/TranscriptTimeline.vue +223 -223
  515. package/app/components/workshop/agents/AgentTemplateEditModal.vue +139 -139
  516. package/app/components/workshop/blocks/ClusterArtifact.vue +61 -61
  517. package/app/components/workshop/blocks/ClusterError.vue +85 -85
  518. package/app/components/workshop/blocks/ClusterLife.vue +87 -87
  519. package/app/components/workshop/blocks/ClusterMember.vue +95 -95
  520. package/app/components/workshop/blocks/ClusterMemory.vue +84 -84
  521. package/app/components/workshop/blocks/ClusterOther.vue +67 -67
  522. package/app/components/workshop/blocks/ClusterStatus.vue +149 -149
  523. package/app/components/workshop/blocks/ClusterTool.vue +176 -176
  524. package/app/components/workshop/blocks/EventBlockAvatar.vue +114 -114
  525. package/app/components/workshop/blocks/EventBlockHead.vue +232 -232
  526. package/app/components/workshop/composer/ComposerToolbar.vue +278 -278
  527. package/app/components/workshop/composer/MentionMenu.vue +135 -135
  528. package/app/components/workshop/composer/ReplyChip.vue +65 -65
  529. package/app/components/workshop/composer/StatusChip.vue +171 -171
  530. package/app/components/workshop/console/Dock.vue +71 -71
  531. package/app/components/workshop/console/LeftPane.vue +84 -84
  532. package/app/components/workshop/device-twin/DeviceTwinCard.vue +265 -265
  533. package/app/components/workshop/device-twin/DeviceTwinDcwSection.vue +203 -203
  534. package/app/components/workshop/lanes/AddMemberModal.vue +270 -270
  535. package/app/components/workshop/lanes/EditMemberModal.vue +106 -106
  536. package/app/components/workshop/lanes/LanesToolbar.vue +97 -97
  537. package/app/components/workshop/session-list/ChannelSettingsModal.vue +3 -3
  538. package/app/components/workshop/session-list/MountChannelModal.vue +124 -124
  539. package/app/components/workshop/session-list/SaveTemplateModal.vue +93 -93
  540. package/app/components/workshop/task-board/Card.vue +172 -172
  541. package/app/components/workshop/task-board/Column.vue +151 -151
  542. package/app/components/workshop/task-board/List.vue +157 -157
  543. package/app/components/workshop/task-board/StatusMenu.vue +88 -88
  544. package/app/components/workshop/teams/TeamAddMemberModal.vue +53 -53
  545. package/app/components/workshop/teams/TeamCreateModal.vue +94 -94
  546. package/app/components/workshop/teams/TeamDeployModal.vue +40 -40
  547. package/app/components/workshop/teams/TeamPluginModal.vue +119 -119
  548. package/app/components/workshop/terminal/OmpTerminalPanel.vue +270 -270
  549. package/app/components/workshop/terminal/TerminalHitlCard.vue +170 -170
  550. package/app/components/workshop/town/TownScene.ts +466 -466
  551. package/app/components/workshop/town/TownView.vue +561 -561
  552. package/app/components/workshop/town/components/AutoModeConfirmModal.vue +94 -94
  553. package/app/components/workshop/town/components/TownAgentBindings.vue +405 -405
  554. package/app/components/workshop/town/components/TownAgentInspector.vue +554 -554
  555. package/app/components/workshop/town/components/TownAlarmList.vue +147 -147
  556. package/app/components/workshop/town/components/TownBoundaryPanel.vue +350 -350
  557. package/app/components/workshop/town/components/TownCalloutLayer.vue +147 -147
  558. package/app/components/workshop/town/components/TownChannelDock.vue +116 -116
  559. package/app/components/workshop/town/components/TownControlDock.vue +405 -405
  560. package/app/components/workshop/town/components/TownDaqNodeInspector.vue +345 -345
  561. package/app/components/workshop/town/components/TownDaqTree.vue +366 -366
  562. package/app/components/workshop/town/components/TownDcwBindSection.vue +473 -473
  563. package/app/components/workshop/town/components/TownDcwNodeInspector.vue +185 -185
  564. package/app/components/workshop/town/components/TownDcwTree.vue +280 -280
  565. package/app/components/workshop/town/components/TownDeviceBindings.vue +394 -394
  566. package/app/components/workshop/town/components/TownDeviceTransform.vue +248 -248
  567. package/app/components/workshop/town/components/TownEventList.vue +120 -120
  568. package/app/components/workshop/town/components/TownHealthBody.vue +100 -100
  569. package/app/components/workshop/town/components/TownKpiStrip.vue +207 -207
  570. package/app/components/workshop/town/components/TownLeftRail.vue +308 -308
  571. package/app/components/workshop/town/components/TownLoadingMask.vue +61 -61
  572. package/app/components/workshop/town/components/TownNavMap.vue +154 -154
  573. package/app/components/workshop/town/components/TownRightRail.vue +543 -543
  574. package/app/components/workshop/town/components/TownStage.vue +281 -281
  575. package/app/components/workshop/town/components/TownStageTop.vue +238 -238
  576. package/app/components/workshop/town/components/TownStatusBar.vue +108 -108
  577. package/app/components/workshop/town/components/TownTopNav.vue +367 -367
  578. package/app/components/workshop/town/components/TownTrendDock.vue +178 -178
  579. package/app/components/workshop/town/scene/town-scene-agents.ts +254 -254
  580. package/app/components/workshop/town/scene/town-scene-behavior.ts +194 -194
  581. package/app/components/workshop/town/scene/town-scene-bubbles.ts +96 -96
  582. package/app/components/workshop/town/scene/town-scene-core.ts +158 -158
  583. package/app/components/workshop/town/scene/town-scene-models.ts +109 -109
  584. package/app/components/workshop/town/scene/town-scene-visuals.ts +279 -279
  585. package/app/components/workshop/town/scene/town-scene3d-agents.ts +308 -308
  586. package/app/components/workshop/town/scene/town-scene3d-blocks.ts +297 -297
  587. package/app/components/workshop/town/scene/town-scene3d-bubbles.ts +281 -281
  588. package/app/components/workshop/town/scene/town-scene3d-camera.ts +282 -282
  589. package/app/components/workshop/town/scene/town-scene3d-devices.ts +433 -433
  590. package/app/components/workshop/town/scene/town-scene3d-editing.ts +490 -490
  591. package/app/components/workshop/town/scene/town-scene3d-events.ts +173 -173
  592. package/app/components/workshop/town/scene/town-scene3d-factory.ts +412 -412
  593. package/app/components/workshop/town/scene/town-scene3d-hud.ts +110 -110
  594. package/app/components/workshop/town/scene/town-scene3d-lifecycle.ts +144 -144
  595. package/app/components/workshop/town/scene/town-scene3d-links.ts +141 -141
  596. package/app/components/workshop/town/scene/town-scene3d-loop.ts +286 -286
  597. package/app/components/workshop/town/scene/town-scene3d-models.ts +154 -154
  598. package/app/components/workshop/town/scene/town-scene3d-nodes.ts +562 -562
  599. package/app/components/workshop/town/scene/town-scene3d-ranges.ts +273 -273
  600. package/app/components/workshop/town/scene/town-scene3d-renderer.ts +320 -320
  601. package/app/components/workshop/town/scene/town-scene3d-selection.ts +257 -257
  602. package/app/components/workshop/town/scene/town-scene3d-types.ts +264 -264
  603. package/app/components/workshop/transcript/TranscriptBlockList.vue +68 -68
  604. package/app/components/workshop/transcript/TranscriptEarlierPager.vue +81 -81
  605. package/app/components/workshop/transcript/TranscriptFilterBar.vue +126 -126
  606. package/app/components/workshop/workbench/CreateWorkspaceModal.vue +36 -36
  607. package/app/components/workshop/workbench/WorkspaceEmpty.vue +56 -56
  608. package/app/composables/useResponsive.ts +88 -88
  609. package/app/composables/workshop/device-twin-types.ts +29 -29
  610. package/app/composables/workshop/event-blocks/attention.ts +58 -58
  611. package/app/composables/workshop/event-blocks/classify.ts +44 -44
  612. package/app/composables/workshop/event-blocks/clusterer.ts +231 -231
  613. package/app/composables/workshop/event-blocks/fold-stream.ts +45 -45
  614. package/app/composables/workshop/event-blocks/markdown.ts +81 -81
  615. package/app/composables/workshop/event-blocks/mentions.ts +49 -49
  616. package/app/composables/workshop/event-blocks/text-utils.ts +100 -100
  617. package/app/composables/workshop/event-blocks/types.ts +40 -40
  618. package/app/composables/workshop/town/town-relay-props.ts +231 -231
  619. package/app/composables/workshop/town/town-view-types.ts +145 -145
  620. package/app/composables/workshop/town/useTownAgentBindings.ts +182 -182
  621. package/app/composables/workshop/town/useTownAgentChat.ts +203 -203
  622. package/app/composables/workshop/town/useTownAlarms.ts +36 -36
  623. package/app/composables/workshop/town/useTownCallouts.ts +174 -174
  624. package/app/composables/workshop/town/useTownChannels.ts +220 -220
  625. package/app/composables/workshop/town/useTownHealth.ts +66 -66
  626. package/app/composables/workshop/town/useTownHudTickers.ts +77 -77
  627. package/app/composables/workshop/town/useTownLayout.ts +277 -277
  628. package/app/composables/workshop/town/useTownNavMap.ts +301 -301
  629. package/app/composables/workshop/town/useTownNodeBindings.ts +345 -345
  630. package/app/composables/workshop/town/useTownPanelDrag.ts +91 -91
  631. package/app/composables/workshop/town/useTownRailData.ts +421 -421
  632. package/app/composables/workshop/town/useTownSceneControl.ts +92 -92
  633. package/app/composables/workshop/town/useTownSceneInput.ts +275 -275
  634. package/app/composables/workshop/town/useTownSceneRuntime.ts +390 -390
  635. package/app/composables/workshop/town/useTownSheets.ts +41 -41
  636. package/app/composables/workshop/town/useTownTrends.ts +93 -93
  637. package/app/composables/workshop/useChannelList.ts +88 -88
  638. package/app/composables/workshop/useChannelTerminals.ts +65 -65
  639. package/app/composables/workshop/useComposerMentions.ts +130 -130
  640. package/app/composables/workshop/useDcwStream.ts +374 -374
  641. package/app/composables/workshop/useDeviceTwinDcwWrite.ts +77 -77
  642. package/app/composables/workshop/useDeviceTwinPanel.ts +56 -56
  643. package/app/composables/workshop/useEscClose.ts +44 -44
  644. package/app/composables/workshop/useEventBlockView.ts +159 -159
  645. package/app/composables/workshop/useEventBlocks.ts +33 -33
  646. package/app/composables/workshop/useHitlAnswer.ts +184 -184
  647. package/app/composables/workshop/useLaneWidths.ts +27 -27
  648. package/app/composables/workshop/useOmpTerminalSession.ts +424 -424
  649. package/app/composables/workshop/usePluginAdmin.ts +152 -152
  650. package/app/composables/workshop/usePluginPanels.ts +72 -72
  651. package/app/composables/workshop/useRuntimeConfigDraft.ts +118 -118
  652. package/app/composables/workshop/useSettingsGroups.ts +243 -243
  653. package/app/composables/workshop/useTaskBoardColumns.ts +47 -47
  654. package/app/composables/workshop/useTerminalRenderer.ts +308 -308
  655. package/app/composables/workshop/useTranscriptEnterStage.ts +48 -48
  656. package/app/composables/workshop/useTranscriptHistory.ts +52 -52
  657. package/app/composables/workshop/useTranscriptScroll.ts +113 -113
  658. package/app/composables/workshop/useVisibleInterval.ts +42 -42
  659. package/app/composables/workshop/useWorkshopWs.ts +265 -265
  660. package/app/config/index.ts +1 -1
  661. package/app/middleware/locale-cookie.global.ts +22 -22
  662. package/app/pages/aml/api.ts +6 -6
  663. package/app/pages/aml/composables/useAmlDatasets.ts +38 -38
  664. package/app/pages/aml/composables/useAmlEntities.ts +57 -57
  665. package/app/pages/aml/composables/useAmlEnv.ts +191 -191
  666. package/app/pages/aml/composables/useAmlExperiments.ts +45 -45
  667. package/app/pages/aml/composables/useAmlFormat.ts +44 -44
  668. package/app/pages/aml/composables/useAmlJobs.ts +131 -131
  669. package/app/pages/aml/composables/useAmlModels.ts +56 -56
  670. package/app/pages/aml/composables/useAmlNotes.ts +47 -47
  671. package/app/pages/aml/composables/useAmlPredict.ts +93 -93
  672. package/app/pages/aml/constants.ts +63 -63
  673. package/app/pages/aml/index.vue +236 -236
  674. package/app/pages/composables/useDashboardCharts.ts +192 -192
  675. package/app/pages/composables/useDashboardData.ts +144 -144
  676. package/app/pages/daq/composables/useDaqAddNode.ts +126 -126
  677. package/app/pages/daq/composables/useDaqDetailBinding.ts +29 -29
  678. package/app/pages/daq/composables/useDaqDetailFrames.ts +42 -42
  679. package/app/pages/daq/composables/useDaqDetailNode.ts +53 -53
  680. package/app/pages/daq/composables/useDaqDetailParams.ts +138 -138
  681. package/app/pages/daq/composables/useDaqFilters.ts +187 -187
  682. package/app/pages/daq/composables/useDaqNodeWindow.ts +86 -86
  683. package/app/pages/daq/composables/useDaqOptimizations.ts +99 -99
  684. package/app/pages/daq/composables/useDaqTemplates.ts +152 -152
  685. package/app/pages/daq/index.vue +260 -260
  686. package/app/pages/dcw/composables/useDcwCards.ts +27 -27
  687. package/app/pages/dcw/composables/useDcwDetailScope.ts +145 -145
  688. package/app/pages/dcw/composables/useDcwDetailTemplates.ts +94 -94
  689. package/app/pages/dcw/composables/useDcwFilter.ts +29 -29
  690. package/app/pages/dcw/composables/useDcwLedger.ts +34 -34
  691. package/app/pages/dcw/composables/useDcwLineMutations.ts +115 -115
  692. package/app/pages/dcw/composables/useDcwLineRun.ts +60 -60
  693. package/app/pages/dcw/composables/useDcwProducts.ts +54 -54
  694. package/app/pages/dcw/composables/useDcwQuery.ts +68 -68
  695. package/app/pages/dcw/composables/useDcwQuickActions.ts +47 -47
  696. package/app/pages/dcw/composables/useDcwRecipes.ts +256 -256
  697. package/app/pages/dcw/composables/useDcwTemplates.ts +50 -50
  698. package/app/pages/dcw/index.vue +195 -195
  699. package/app/pages/dcw/types.ts +9 -9
  700. package/app/pages/index.vue +126 -126
  701. package/app/pages/logs/composables/useLogsFormat.ts +43 -43
  702. package/app/pages/logs/composables/useLogsScope.ts +39 -39
  703. package/app/pages/monitor/types.ts +61 -61
  704. package/app/pages/ontology/index.vue +1 -1
  705. package/app/pages/operations.vue +61 -61
  706. package/app/pages/permissions/index.vue +369 -369
  707. package/app/pages/studio/pipeline.vue +812 -0
  708. package/app/pages/tokens/composables/useTokenClipboard.ts +33 -33
  709. package/app/pages/tokens/composables/useTokenCreate.ts +93 -93
  710. package/app/pages/tokens/composables/useTokenRename.ts +54 -54
  711. package/app/pages/tokens/composables/useTokenReveal.ts +84 -84
  712. package/app/pages/tokens/composables/useTokensList.ts +60 -60
  713. package/app/pages/tokens.vue +111 -111
  714. package/app/pages/tools/index.vue +98 -98
  715. package/app/pages/workshop/agents.vue +130 -130
  716. package/app/pages/workshop/composables/useAgentHarnessOptions.ts +59 -59
  717. package/app/pages/workshop/composables/useAgentTemplateActions.ts +42 -42
  718. package/app/pages/workshop/composables/useAgentTemplateDialogState.ts +24 -24
  719. package/app/pages/workshop/composables/useAgentTemplateForm.ts +88 -88
  720. package/app/pages/workshop/composables/useAgentTemplatesCatalog.ts +92 -92
  721. package/app/pages/workshop/composables/useTeamActions.ts +44 -44
  722. package/app/pages/workshop/composables/useTeamAddMemberDialog.ts +49 -49
  723. package/app/pages/workshop/composables/useTeamCreateDialog.ts +67 -67
  724. package/app/pages/workshop/composables/useTeamDeployDialog.ts +49 -49
  725. package/app/pages/workshop/composables/useTeamDialogState.ts +46 -46
  726. package/app/pages/workshop/composables/useTeamPluginDialog.ts +72 -72
  727. package/app/pages/workshop/composables/useTeamsCatalog.ts +100 -100
  728. package/app/pages/workshop/composables/useWorkbenchWorkspaces.ts +123 -123
  729. package/app/pages/workshop/composables/useWorkspaceAuth.ts +31 -31
  730. package/app/pages/workshop/composables/useWorkspaceChannels.ts +62 -62
  731. package/app/pages/workshop/composables/useWorkspaceShell.ts +136 -136
  732. package/app/pages/workshop/schedules.vue +553 -553
  733. package/app/pages/workshop/w/[wsId].vue +221 -221
  734. package/app/plugins/aw-plugins.client.ts +213 -213
  735. package/app/plugins/esc-close.client.ts +31 -31
  736. package/app/stores/workshop/hitl.ts +183 -183
  737. package/app/stores/workshop/narrow-fetch.ts +23 -23
  738. package/app/utils/api-error.ts +75 -75
  739. package/app/utils/builtin-catalog.ts +104 -104
  740. package/app/utils/chart-pipeline.ts +193 -0
  741. package/app/utils/chart-trend.ts +97 -97
  742. package/app/utils/dcw-driver-badge.ts +16 -16
  743. package/app/utils/dcw-recipe-form.ts +26 -26
  744. package/cli/commands/tui.mjs +28 -28
  745. package/cli/commands/update.mjs +124 -124
  746. package/cli/core/child-lifecycle.mjs +136 -136
  747. package/cli/core/meta.mjs +38 -38
  748. package/cli/core/post-build.mjs +96 -96
  749. package/config.yml +1 -1
  750. package/docs/cli.en.md +2 -2
  751. package/docs/cli.md +2 -2
  752. package/docs/mcp.en.md +27 -27
  753. package/docs/multi-harness-architecture.md +248 -248
  754. package/docs/plugins.en.md +1 -1
  755. package/docs/plugins.md +1 -1
  756. package/docs/sdk.en.md +1 -1
  757. package/docs/sdk.md +1 -1
  758. package/docs/tui.md +43 -43
  759. package/i18n/dicts/_en.json +1551 -1551
  760. package/i18n/dicts/_en2.json +300 -300
  761. package/i18n/dicts/_en4.json +114 -114
  762. package/i18n/dicts/agentLanesView.json +61 -61
  763. package/i18n/dicts/appHeader.json +17 -17
  764. package/i18n/dicts/channelSessionList.json +51 -51
  765. package/i18n/dicts/chat.json +79 -79
  766. package/i18n/dicts/clusterTool.json +4 -4
  767. package/i18n/dicts/composer.json +38 -38
  768. package/i18n/dicts/ctpl.json +37 -37
  769. package/i18n/dicts/dcwDetail.json +219 -219
  770. package/i18n/dicts/lineOps.json +14 -14
  771. package/i18n/dicts/multiChannelView.json +13 -13
  772. package/i18n/dicts/notifications.json +13 -13
  773. package/i18n/dicts/taskInspectorDrawer.json +25 -25
  774. package/i18n/dicts/teamPlugins.json +10 -10
  775. package/i18n/dicts/townView.json +209 -209
  776. package/i18n/locales/en.ts +46 -0
  777. package/i18n/locales/zh-CN.ts +46 -0
  778. package/mcp/discovery.mjs +227 -227
  779. package/package.json +1 -1
  780. package/public/favicon.svg +14 -14
  781. package/public/robots.txt +3 -3
  782. package/scripts/_audit/audit-harness-adapters.md +664 -664
  783. package/scripts/_audit/aw-mcp-live-e2e.mjs +293 -293
  784. package/scripts/_audit/bump-version.mjs +51 -51
  785. package/scripts/_audit/detached-instance.mjs +112 -112
  786. package/scripts/_audit/detached-start.mjs +103 -103
  787. package/scripts/_audit/eda-ui-fix-acceptance.mjs +212 -212
  788. package/scripts/_audit/guard-upstream-liveness.mjs +104 -104
  789. package/scripts/_audit/http-api-authz-audit.md +657 -657
  790. package/scripts/_audit/kb-team-mock-e2e.mjs +146 -146
  791. package/scripts/_audit/kb-team-omp-e2e.mjs +229 -229
  792. package/scripts/_audit/run.mjs +21 -21
  793. package/scripts/_audit/runtime-audit.md +716 -716
  794. package/scripts/_audit/skills-guided-e2e.mjs +316 -316
  795. package/scripts/_audit/stability-soak.mjs +252 -252
  796. package/scripts/_audit/stubs/nuxt-imports.mjs +67 -67
  797. package/scripts/_audit/ts-register-hook.mjs +12 -12
  798. package/scripts/_audit/ts-resolve-hook.mjs +96 -96
  799. package/scripts/_aw-packaged-start.cjs +22 -22
  800. package/scripts/_aw0746-stage12.mjs +94 -94
  801. package/scripts/_aw0746-stage34.mjs +136 -136
  802. package/scripts/_aw0746-stage6b-train-sweep.mjs +145 -145
  803. package/scripts/_aw0746-stage6c-jobsmoke.mjs +69 -69
  804. package/scripts/_dbg-configroot-audit.mjs +86 -86
  805. package/scripts/_dbg-daq-intervals-func.mjs +115 -115
  806. package/scripts/_dbg-perms-e2e.mjs +142 -142
  807. package/scripts/_dbg-protocol-matrix.mjs +462 -462
  808. package/scripts/_dbg-render-regression.mjs +193 -193
  809. package/scripts/_dbg-schedule-e2e.mjs +262 -262
  810. package/scripts/_e2e-ui-functional.mjs +371 -371
  811. package/scripts/_i18n-en-cjk-scan.mjs +28 -28
  812. package/scripts/_i18n-en-verify.mjs +107 -107
  813. package/scripts/_i18n-extra-checks.mjs +53 -53
  814. package/scripts/_i18n-scan-hardcoded.mjs +180 -180
  815. package/scripts/_lib-aml-python-run.mjs +17 -17
  816. package/scripts/_lint-reflow.mjs +105 -105
  817. package/scripts/_loop-biax-campaign.mjs +130 -130
  818. package/scripts/_plc-sim-detached.cjs +22 -22
  819. package/scripts/_probe-daq-omp-task.mjs +100 -100
  820. package/scripts/_probe-daq-scope-default.mjs +123 -123
  821. package/scripts/_probe-model-channel-link.cjs +25 -25
  822. package/scripts/_probe-recipe-switch.mjs +92 -92
  823. package/scripts/_provision-injection-line.mjs +39 -39
  824. package/scripts/_run-matrix.ps1 +53 -53
  825. package/scripts/_sweep-button-contrast.mjs +87 -87
  826. package/scripts/acceptance-aml-hybrid-e2e.ts +396 -396
  827. package/scripts/acceptance-aml-hybrid-live.mjs +93 -93
  828. package/scripts/acceptance-aml-model-identity.ts +137 -137
  829. package/scripts/agent-daq-isolation-e2e.mjs +91 -91
  830. package/scripts/api-contract-smoke.mjs +126 -126
  831. package/scripts/ask-hitl-e2e.mjs +96 -96
  832. package/scripts/aw-expose.mjs +159 -159
  833. package/scripts/channel-interaction-smoke.mjs +80 -80
  834. package/scripts/check-docs-sync.mjs +1 -1
  835. package/scripts/data-studio-ui-e2e.mjs +163 -163
  836. package/scripts/demo-group-chat-all-real.ts +279 -279
  837. package/scripts/demo-group-chat-omp-cases.ts +210 -210
  838. package/scripts/demo-group-chat-omp.ts +184 -184
  839. package/scripts/demo-group-chat-order.ts +197 -197
  840. package/scripts/dev-modbus-simulator.mjs +55 -55
  841. package/scripts/docs-shots.mjs +36 -36
  842. package/scripts/e2e-agentteam-chat.mjs +473 -473
  843. package/scripts/e2e-agentteam-real-triage.mjs +421 -421
  844. package/scripts/e2e-aml-decoupled.mjs +162 -162
  845. package/scripts/e2e-aw-tui-global.mjs +277 -277
  846. package/scripts/e2e-closedloop/cleanup.mjs +27 -27
  847. package/scripts/e2e-closedloop/lib.mjs +109 -109
  848. package/scripts/e2e-closedloop/main.mjs +59 -59
  849. package/scripts/e2e-closedloop/scenarios-accounts.mjs +210 -210
  850. package/scripts/e2e-closedloop/scenarios-authz.mjs +196 -196
  851. package/scripts/e2e-closedloop/scenarios-daq-dcw.mjs +222 -222
  852. package/scripts/e2e-closedloop/scenarios-plugins.mjs +169 -169
  853. package/scripts/e2e-closedloop/state.mjs +10 -10
  854. package/scripts/e2e-config-groups.mjs +238 -238
  855. package/scripts/e2e-crash-cycle.mjs +108 -108
  856. package/scripts/e2e-eda-pipeline.mjs +286 -0
  857. package/scripts/e2e-full-closedloop.mjs +16 -16
  858. package/scripts/e2e-hil-multi-user.mjs +307 -307
  859. package/scripts/e2e-hil-restart.mjs +339 -339
  860. package/scripts/e2e-injection-recipe-closedloop.mjs +203 -203
  861. package/scripts/e2e-line-governance.mjs +352 -352
  862. package/scripts/e2e-ontology.mjs +393 -393
  863. package/scripts/e2e-plc-plugin-closedloop.mjs +549 -549
  864. package/scripts/e2e-resume-crash.mjs +20 -6
  865. package/scripts/e2e-timezone-settings.mjs +59 -57
  866. package/scripts/full-stack-shots.mjs +145 -145
  867. package/scripts/full-tool-injection-harness-e2e.mjs +214 -214
  868. package/scripts/hitl-reject-e2e.mjs +131 -131
  869. package/scripts/line-log-smoke.mjs +260 -260
  870. package/scripts/live-aml-mockomp.mjs +304 -304
  871. package/scripts/live-aml-optloop-resume.mjs +322 -322
  872. package/scripts/live-aml-optloop.mjs +588 -588
  873. package/scripts/live-aml-stage9.mjs +169 -169
  874. package/scripts/live-aml-two-goals.mjs +315 -315
  875. package/scripts/live-optloop-two-modes.mjs +857 -857
  876. package/scripts/mes-agent-integration-e2e.mjs +361 -361
  877. package/scripts/ops-plugins-e2e.mjs +85 -85
  878. package/scripts/proof-omp-real.ts +189 -189
  879. package/scripts/scenario-suite-setup.mjs +337 -337
  880. package/scripts/scenario-suite-stability.mjs +144 -144
  881. package/scripts/smoke-optimization-verify.ts +72 -72
  882. package/scripts/team-coordination-e2e.mjs +96 -96
  883. package/scripts/test-agentteam-task-chat-flow.ts +420 -420
  884. package/scripts/test-agentteam-workflow.ts +472 -472
  885. package/scripts/test-aw-skills.mjs +102 -102
  886. package/scripts/test-cli-exit.mjs +343 -343
  887. package/scripts/test-daq-frame-race.mjs +358 -358
  888. package/scripts/test-data-root.mjs +208 -208
  889. package/scripts/test-events-index.mjs +176 -176
  890. package/scripts/test-group-chat-hardening.ts +265 -265
  891. package/scripts/test-group-chat-unit/lib.ts +186 -186
  892. package/scripts/test-group-chat-unit/main.ts +45 -45
  893. package/scripts/test-group-chat-unit/section-a-migration.ts +75 -75
  894. package/scripts/test-group-chat-unit/section-b-permission-matrix.ts +88 -88
  895. package/scripts/test-group-chat-unit/section-c-member-lifecycle.ts +64 -64
  896. package/scripts/test-group-chat-unit/section-d-mention-resolution.ts +36 -36
  897. package/scripts/test-group-chat-unit/section-e-chat-facts.ts +97 -97
  898. package/scripts/test-group-chat-unit/section-f-user-notifications.ts +52 -52
  899. package/scripts/test-group-chat-unit/section-g-member-projection.ts +44 -44
  900. package/scripts/test-group-chat-unit/section-h-outbox-consistency.ts +30 -30
  901. package/scripts/test-group-chat-unit/section-i-read-idempotency.ts +24 -24
  902. package/scripts/test-group-chat-unit/section-j-permission-scope.ts +150 -150
  903. package/scripts/test-group-chat-unit.ts +35 -35
  904. package/scripts/test-hitl-decision.ts +526 -526
  905. package/scripts/test-hitl-legacy-channel-auth.ts +143 -143
  906. package/scripts/test-hitl-registry.ts +112 -112
  907. package/scripts/test-log-flooding.mjs +160 -160
  908. package/scripts/test-lru.mjs +101 -101
  909. package/scripts/test-memory-month-query.mjs +70 -70
  910. package/scripts/test-plugin-hardening.mjs +90 -90
  911. package/scripts/test-plugin-lifecycle.mjs +173 -173
  912. package/scripts/test-rollback-index.mjs +137 -137
  913. package/scripts/test-schedule-runtime.ts +309 -309
  914. package/scripts/test-scheduler-loop/scenarios-supervise.ts +25 -25
  915. package/scripts/test-sdk-surface.mjs +158 -158
  916. package/scripts/test-serial-bridge.mjs +418 -418
  917. package/scripts/test-tui-commands.mjs +148 -148
  918. package/scripts/test-tui-reducers.mjs +72 -72
  919. package/scripts/three-system-e2e/lib.mjs +79 -79
  920. package/scripts/three-system-e2e/main.mjs +40 -40
  921. package/scripts/three-system-e2e/phases/phase-0-user-token.mjs +42 -42
  922. package/scripts/three-system-e2e/phases/phase-0a2-line-autoselect.mjs +35 -35
  923. package/scripts/three-system-e2e/phases/phase-0b-fixture-grants.mjs +39 -39
  924. package/scripts/three-system-e2e/phases/phase-0c-plugin-outbound-auth.mjs +95 -95
  925. package/scripts/three-system-e2e/phases/stage-1-health.mjs +47 -47
  926. package/scripts/three-system-e2e/phases/stage-2-5-team-plugins.mjs +84 -84
  927. package/scripts/three-system-e2e/phases/stage-2-teams-tools-hitl.mjs +184 -184
  928. package/scripts/three-system-e2e/phases/stage-3-diag.mjs +73 -73
  929. package/scripts/three-system-e2e/phases/stage-4-plugin-toggle.mjs +53 -53
  930. package/scripts/three-system-e2e/state.mjs +87 -87
  931. package/scripts/three-system-e2e.mjs +40 -40
  932. package/scripts/tool-face-batch-identity-e2e.mjs +222 -222
  933. package/scripts/tsconfig.json +14 -14
  934. package/scripts/tui-smoke.mjs +100 -100
  935. package/scripts/typecheck.mjs +75 -75
  936. package/scripts/ui/admin-shots.mjs +46 -46
  937. package/scripts/ui/bump-microfont.mjs +39 -39
  938. package/scripts/ui/linkcheck2.mjs +37 -37
  939. package/scripts/ui/live-render-check.mjs +72 -72
  940. package/scripts/ui/md-lint.mjs +80 -80
  941. package/scripts/ui/perf-audit.mjs +132 -132
  942. package/scripts/ui/readme-assets.mjs +30 -30
  943. package/scripts/ui/readme-shots.mjs +42 -42
  944. package/scripts/ui/record-demo.mjs +557 -557
  945. package/scripts/ui/record.mjs +225 -225
  946. package/scripts/ui/seed-admin.mjs +68 -68
  947. package/scripts/ui/seed-demo.mjs +83 -83
  948. package/scripts/ui/seed-industrial-demo.mjs +171 -171
  949. package/scripts/ui/shot-hero.mjs +25 -25
  950. package/scripts/ui/shots.mjs +75 -75
  951. package/scripts/ui/sim-ui-shot.mjs +16 -16
  952. package/scripts/ui/smoke-refactor.mjs +258 -258
  953. package/scripts/ui/verify-nav.mjs +51 -51
  954. package/scripts/ui/verify-responsive.mjs +285 -285
  955. package/sdk/client.d.mts +110 -110
  956. package/sdk/examples/line-sentinel/index.mjs +105 -105
  957. package/sdk/examples/ops-notifier/index.mjs +34 -34
  958. package/sdk/examples/sample-insight/index.mjs +39 -39
  959. package/server/api/plugins/client/[name].get.ts +18 -18
  960. package/server/api/plugins/i18n.get.ts +12 -12
  961. package/server/api/plugins/manifest.get.ts +10 -10
  962. package/server/api/system/backup/list.get.ts +32 -32
  963. package/server/api/system/backup/run.post.ts +21 -21
  964. package/server/api/system/config-groups/[id].delete.ts +21 -21
  965. package/server/api/system/config-groups/[id].patch.ts +26 -26
  966. package/server/api/system/config-groups/index.get.ts +21 -21
  967. package/server/api/system/config-groups/index.post.ts +33 -33
  968. package/server/api/system/timezone.get.ts +20 -20
  969. package/server/api/users/tokens/[id]/token.get.ts +11 -11
  970. package/server/api/workshop/[...path].ts +13 -13
  971. package/server/api/workshop/agent-tools/approvals/index.get.ts +43 -43
  972. package/server/api/workshop/agent-tools/bindings/[id].delete.ts +26 -26
  973. package/server/api/workshop/agent-tools/bindings/grant.post.ts +45 -45
  974. package/server/api/workshop/agent-tools/bindings/index.get.ts +41 -41
  975. package/server/api/workshop/agent-tools/bindings/revoke.post.ts +42 -42
  976. package/server/api/workshop/aml/datasets/[id]/preview.get.ts +68 -68
  977. package/server/api/workshop/aml/datasets/[id].delete.ts +39 -39
  978. package/server/api/workshop/aml/datasets/[id].get.ts +53 -53
  979. package/server/api/workshop/aml/datasets/[id].patch.ts +30 -30
  980. package/server/api/workshop/aml/datasets/index.get.ts +20 -20
  981. package/server/api/workshop/aml/datasets/index.post.ts +27 -27
  982. package/server/api/workshop/aml/entities/index.get.ts +13 -13
  983. package/server/api/workshop/aml/entities/prune.post.ts +28 -28
  984. package/server/api/workshop/aml/env/index.get.ts +13 -13
  985. package/server/api/workshop/aml/env/recheck.post.ts +14 -14
  986. package/server/api/workshop/aml/env/uv.post.ts +21 -21
  987. package/server/api/workshop/aml/env/venv.post.ts +24 -24
  988. package/server/api/workshop/aml/experiments/index.get.ts +35 -35
  989. package/server/api/workshop/aml/index.get.ts +37 -37
  990. package/server/api/workshop/aml/jobs/[id]/cancel.post.ts +21 -21
  991. package/server/api/workshop/aml/jobs/[id]/logs.get.ts +23 -23
  992. package/server/api/workshop/aml/jobs/[id]/retry.post.ts +20 -20
  993. package/server/api/workshop/aml/jobs/[id].delete.ts +44 -44
  994. package/server/api/workshop/aml/jobs/[id].get.ts +23 -23
  995. package/server/api/workshop/aml/jobs/index.get.ts +26 -26
  996. package/server/api/workshop/aml/models/[id]/predict.post.ts +24 -24
  997. package/server/api/workshop/aml/models/[id]/promote.post.ts +30 -30
  998. package/server/api/workshop/aml/models/index.get.ts +48 -48
  999. package/server/api/workshop/aml/training-plans/[id]/train.post.ts +18 -18
  1000. package/server/api/workshop/aml/training-plans/[id].delete.ts +18 -18
  1001. package/server/api/workshop/aml/training-plans/[id].patch.ts +30 -30
  1002. package/server/api/workshop/aml/training-plans/index.get.ts +9 -9
  1003. package/server/api/workshop/aml/training-plans/index.post.ts +43 -43
  1004. package/server/api/workshop/analysis/index.post.ts +54 -0
  1005. package/server/api/workshop/approvals/[id]/decide.post.ts +30 -30
  1006. package/server/api/workshop/approvals/index.get.ts +22 -22
  1007. package/server/api/workshop/audit.get.ts +43 -43
  1008. package/server/api/workshop/channels/[id]/chat/messages/[messageId]/read.post.ts +22 -22
  1009. package/server/api/workshop/channels/[id]/chat/messages/index.get.ts +29 -29
  1010. package/server/api/workshop/channels/[id]/chat/messages/index.post.ts +51 -51
  1011. package/server/api/workshop/channels/[id]/chat/permissions.get.ts +35 -35
  1012. package/server/api/workshop/channels/[id]/index.patch.ts +64 -64
  1013. package/server/api/workshop/channels/[id]/members/[userId]/approve.post.ts +20 -20
  1014. package/server/api/workshop/channels/[id]/members/[userId].delete.ts +21 -21
  1015. package/server/api/workshop/channels/[id]/members/index.get.ts +23 -23
  1016. package/server/api/workshop/channels/[id]/members/leave.post.ts +20 -20
  1017. package/server/api/workshop/channels/[id]/twin-profile.get.ts +45 -45
  1018. package/server/api/workshop/channels/[id]/twin-profile.patch.ts +72 -72
  1019. package/server/api/workshop/daq/[id]/test.post.ts +1 -1
  1020. package/server/api/workshop/daq/alarms.get.ts +16 -16
  1021. package/server/api/workshop/dcw/[id]/write.post.ts +4 -4
  1022. package/server/api/workshop/dcw/[id].delete.ts +41 -41
  1023. package/server/api/workshop/dcw/[id].patch.ts +40 -40
  1024. package/server/api/workshop/dcw/mes-test-read.post.ts +24 -24
  1025. package/server/api/workshop/dcw/params/[id]/read.post.ts +17 -17
  1026. package/server/api/workshop/dcw/params/[id]/write.post.ts +21 -21
  1027. package/server/api/workshop/dcw/params/[id].delete.ts +19 -19
  1028. package/server/api/workshop/dcw/params/[id].patch.ts +23 -23
  1029. package/server/api/workshop/dcw/params/index.get.ts +27 -27
  1030. package/server/api/workshop/dcw/params/index.post.ts +25 -25
  1031. package/server/api/workshop/dcw/products/[id].delete.ts +16 -16
  1032. package/server/api/workshop/dcw/products/[id].patch.ts +17 -17
  1033. package/server/api/workshop/dcw/recipes/[id]/index.patch.ts +22 -22
  1034. package/server/api/workshop/dcw/recipes/[id]/versions.get.ts +14 -14
  1035. package/server/api/workshop/dcw/recipes/[id].delete.ts +25 -25
  1036. package/server/api/workshop/dcw/recipes/index.get.ts +12 -12
  1037. package/server/api/workshop/dcw/runs/[id]/close.post.ts +15 -15
  1038. package/server/api/workshop/dcw/templates/[key].delete.ts +14 -14
  1039. package/server/api/workshop/dcw/templates/[key].patch.ts +16 -16
  1040. package/server/api/workshop/dcw/templates/index.post.ts +15 -15
  1041. package/server/api/workshop/dcw/test-driver.post.ts +16 -16
  1042. package/server/api/workshop/device-twins/[id].delete.ts +25 -25
  1043. package/server/api/workshop/eda/runs/[id]/labels.patch.ts +25 -25
  1044. package/server/api/workshop/eda/templates/[id].delete.ts +14 -0
  1045. package/server/api/workshop/eda/templates/[id].get.ts +15 -0
  1046. package/server/api/workshop/eda/templates/[id].patch.ts +20 -0
  1047. package/server/api/workshop/eda/templates/index.get.ts +11 -0
  1048. package/server/api/workshop/eda/templates/index.post.ts +20 -0
  1049. package/server/api/workshop/exp/confirmations/[id]/decide.post.ts +41 -41
  1050. package/server/api/workshop/exp/confirmations/index.get.ts +25 -25
  1051. package/server/api/workshop/harnesses/[id]/providers.get.ts +16 -16
  1052. package/server/api/workshop/hitl/respond.post.ts +94 -94
  1053. package/server/api/workshop/notifications/index.get.ts +60 -60
  1054. package/server/api/workshop/notifications/read.post.ts +31 -31
  1055. package/server/api/workshop/ontology/drafts/[draftId]/subgraph.ts +24 -24
  1056. package/server/api/workshop/plugins/[name]/disable.post.ts +21 -21
  1057. package/server/api/workshop/plugins/[name]/enable.post.ts +21 -21
  1058. package/server/api/workshop/plugins/[name]/index.get.ts +14 -14
  1059. package/server/api/workshop/schedules/[id]/run.post.ts +15 -15
  1060. package/server/api/workshop/schedules/[id]/runs.get.ts +15 -15
  1061. package/server/api/workshop/schedules/[id].delete.ts +14 -14
  1062. package/server/api/workshop/schedules/[id].get.ts +13 -13
  1063. package/server/api/workshop/schedules/[id].patch.ts +29 -29
  1064. package/server/api/workshop/schedules/index.get.ts +12 -12
  1065. package/server/api/workshop/schedules/index.post.ts +32 -32
  1066. package/server/api/workshop/tasks/[id]/reassign.post.ts +32 -32
  1067. package/server/api/workshop/tasks/[id]/update.post.ts +35 -35
  1068. package/server/api/workshop/teams/[id]/plugins/index.get.ts +36 -36
  1069. package/server/api/workshop/teams/[id]/plugins/index.put.ts +42 -42
  1070. package/server/api/workshop/ws/audience.ts +56 -56
  1071. package/server/api/workshop/ws/db-buffer.ts +68 -68
  1072. package/server/api/workshop/ws/event-mapping.ts +47 -47
  1073. package/server/api/workshop/ws/handlers.ts +132 -132
  1074. package/server/api/workshop/ws/hub.ts +133 -133
  1075. package/server/api/workshop/ws/index.ts +23 -23
  1076. package/server/api/workshop/ws/notification-uplink.ts +77 -77
  1077. package/server/api/workshop/ws/shared.ts +94 -94
  1078. package/server/api/workshop/ws/streams.ts +146 -146
  1079. package/server/middleware/00-security-headers.ts +38 -38
  1080. package/server/middleware/01-rate-guard.ts +101 -101
  1081. package/server/plugins/aml-twin-worker.ts +32 -32
  1082. package/server/plugins/dev-stability-guard.ts +42 -42
  1083. package/server/plugins-builtin/diag-bridge/host/constants.mjs +25 -25
  1084. package/server/plugins-builtin/diag-bridge/host/exports.mjs +104 -104
  1085. package/server/plugins-builtin/diag-bridge/host/helpers.mjs +2 -2
  1086. package/server/plugins-builtin/diag-bridge/host/index.mjs +15 -15
  1087. package/server/plugins-builtin/diag-bridge/host/intents.mjs +62 -62
  1088. package/server/plugins-builtin/diag-bridge/host/plugin.mjs +5 -3
  1089. package/server/plugins-builtin/diag-bridge/host/snapshot.mjs +93 -93
  1090. package/server/plugins-builtin/diag-bridge/index.mjs +9 -9
  1091. package/server/plugins-builtin/serial-bridge/client.mjs +211 -211
  1092. package/server/plugins-builtin/serial-bridge/drivers.mjs +409 -409
  1093. package/server/plugins-builtin/serial-bridge/i18n.json +62 -62
  1094. package/server/plugins-builtin/serial-bridge/index.mjs +247 -247
  1095. package/server/plugins-builtin/serial-bridge/lib.mjs +208 -208
  1096. package/server/plugins-builtin/serial-bridge/rtu.mjs +168 -168
  1097. package/server/services/system-config/contracts.ts +29 -29
  1098. package/server/services/system-config/dispose.ts +19 -19
  1099. package/server/services/system-config/facade.ts +26 -26
  1100. package/server/services/system-config/groups.ts +108 -108
  1101. package/server/services/system-config/index.ts +21 -21
  1102. package/server/services/system-config/init.ts +26 -26
  1103. package/server/services/system-config/mutate.ts +103 -103
  1104. package/server/services/system-config/plugins.ts +104 -104
  1105. package/server/services/system-config/snapshot.ts +59 -59
  1106. package/server/services/system-config/state.ts +79 -79
  1107. package/server/services/system-config/types.ts +58 -58
  1108. package/server/services/workshop/agents/adapters/omp-rpc-client/api.ts +111 -111
  1109. package/server/services/workshop/agents/adapters/omp-rpc-client/contracts.ts +22 -22
  1110. package/server/services/workshop/agents/adapters/omp-rpc-client/facade.ts +7 -7
  1111. package/server/services/workshop/agents/adapters/omp-rpc-client/frames.ts +0 -18
  1112. package/server/services/workshop/agents/adapters/omp-rpc-client/helpers.ts +38 -38
  1113. package/server/services/workshop/agents/adapters/omp-rpc-client/index.ts +25 -25
  1114. package/server/services/workshop/agents/adapters/omp-rpc-client/start.ts +70 -70
  1115. package/server/services/workshop/agents/adapters/omp-rpc-client/state.ts +65 -65
  1116. package/server/services/workshop/agents/adapters/omp-rpc-client/stdout.ts +92 -92
  1117. package/server/services/workshop/agents/adapters/omp-rpc-client/usage.ts +47 -47
  1118. package/server/services/workshop/agents/agent-badge.ts +38 -38
  1119. package/server/services/workshop/agents/binding-authz.ts +60 -60
  1120. package/server/services/workshop/agents/binding-mode.ts +51 -51
  1121. package/server/services/workshop/agents/codex-agent/client.ts +170 -170
  1122. package/server/services/workshop/agents/codex-agent/core.ts +119 -119
  1123. package/server/services/workshop/agents/codex-agent/facade.ts +8 -8
  1124. package/server/services/workshop/agents/codex-agent/helpers.ts +13 -13
  1125. package/server/services/workshop/agents/codex-agent/hitl.ts +138 -138
  1126. package/server/services/workshop/agents/codex-agent/index.ts +14 -14
  1127. package/server/services/workshop/agents/codex-agent/turn.ts +367 -367
  1128. package/server/services/workshop/agents/codex-agent/types.ts +42 -42
  1129. package/server/services/workshop/agents/harness-process.ts +3 -3
  1130. package/server/services/workshop/agents/harness-terminal/api.ts +197 -197
  1131. package/server/services/workshop/agents/harness-terminal/index.ts +17 -17
  1132. package/server/services/workshop/agents/harness-terminal/io.ts +120 -120
  1133. package/server/services/workshop/agents/harness-terminal/park.ts +55 -55
  1134. package/server/services/workshop/agents/harness-terminal/sanitize.ts +98 -98
  1135. package/server/services/workshop/agents/harness-terminal/session.ts +124 -124
  1136. package/server/services/workshop/agents/harness-terminal/shared.ts +74 -74
  1137. package/server/services/workshop/agents/hitl-capabilities.ts +312 -312
  1138. package/server/services/workshop/agents/hitl-decision/answers.ts +32 -32
  1139. package/server/services/workshop/agents/hitl-decision/decide.ts +268 -268
  1140. package/server/services/workshop/agents/hitl-decision/payload.ts +45 -45
  1141. package/server/services/workshop/agents/hitl-decision/shared.ts +108 -108
  1142. package/server/services/workshop/agents/hitl-decision/visibility.ts +94 -94
  1143. package/server/services/workshop/agents/host-tool-bridge/tools/progress.ts +84 -84
  1144. package/server/services/workshop/agents/host-tool-bridge/tools/team-delegation.ts +104 -104
  1145. package/server/services/workshop/agents/host-tool-bridge/tools/team.ts +70 -70
  1146. package/server/services/workshop/agents/industrial/aml-activity.ts +131 -131
  1147. package/server/services/workshop/agents/industrial/audit-query.ts +66 -66
  1148. package/server/services/workshop/agents/industrial/daq-tools.ts +352 -352
  1149. package/server/services/workshop/agents/industrial/exp-tools.ts +104 -104
  1150. package/server/services/workshop/agents/industrial/ops-tools.ts +16 -54
  1151. package/server/services/workshop/agents/industrial/param-tools.ts +69 -69
  1152. package/server/services/workshop/agents/industrial/recipe-gate.ts +6 -19
  1153. package/server/services/workshop/agents/industrial/recipe-propose-tools.ts +1 -1
  1154. package/server/services/workshop/agents/node-bindings.repo.ts +207 -207
  1155. package/server/services/workshop/agents/node-delegation.ts +159 -159
  1156. package/server/services/workshop/agents/omp-agent/core.ts +146 -146
  1157. package/server/services/workshop/agents/omp-agent/facade.ts +8 -8
  1158. package/server/services/workshop/agents/omp-agent/helpers.ts +37 -37
  1159. package/server/services/workshop/agents/omp-agent/index.ts +16 -16
  1160. package/server/services/workshop/agents/omp-agent/tools-steer.ts +1 -18
  1161. package/server/services/workshop/agents/omp-agent/types.ts +45 -45
  1162. package/server/services/workshop/agents/opencode-agent/core.ts +77 -77
  1163. package/server/services/workshop/agents/opencode-agent/facade.ts +8 -8
  1164. package/server/services/workshop/agents/opencode-agent/helpers.ts +29 -29
  1165. package/server/services/workshop/agents/opencode-agent/hitl.ts +113 -113
  1166. package/server/services/workshop/agents/opencode-agent/index.ts +16 -16
  1167. package/server/services/workshop/agents/opencode-agent/lifecycle.ts +44 -44
  1168. package/server/services/workshop/agents/opencode-agent/server.ts +244 -244
  1169. package/server/services/workshop/agents/opencode-agent/turn.ts +278 -278
  1170. package/server/services/workshop/agents/opencode-agent/types.ts +54 -54
  1171. package/server/services/workshop/agents/tool-classes.ts +44 -44
  1172. package/server/services/workshop/aml/clean.ts +120 -120
  1173. package/server/services/workshop/aml/entity.ts +367 -367
  1174. package/server/services/workshop/aml/job-orchestrator/broadcast.ts +37 -37
  1175. package/server/services/workshop/aml/job-orchestrator/control.ts +94 -94
  1176. package/server/services/workshop/aml/job-orchestrator/failure.ts +96 -96
  1177. package/server/services/workshop/aml/job-orchestrator/index.ts +22 -22
  1178. package/server/services/workshop/aml/job-orchestrator/process.ts +101 -101
  1179. package/server/services/workshop/aml/job-orchestrator/shared.ts +53 -53
  1180. package/server/services/workshop/aml/job-orchestrator/status.ts +20 -20
  1181. package/server/services/workshop/aml/job-orchestrator/tick.ts +37 -37
  1182. package/server/services/workshop/aml/python/train-example.py +92 -92
  1183. package/server/services/workshop/aml/runtime.ts +137 -137
  1184. package/server/services/workshop/aml/stats.ts +140 -140
  1185. package/server/services/workshop/aml/twin/calibration-worker.ts +150 -150
  1186. package/server/services/workshop/aml/twin/model-backed-provider.ts +332 -332
  1187. package/server/services/workshop/aml/twin/physics-spec-draft.ts +185 -185
  1188. package/server/services/workshop/aml/twin/prompt-composer.ts +143 -143
  1189. package/server/services/workshop/aml/twin/training-plans.ts +260 -260
  1190. package/server/services/workshop/aml/twin/write-guard.ts +19 -19
  1191. package/server/services/workshop/assets/character-asset.repo.ts +1 -1
  1192. package/server/services/workshop/assets/device-twin.repo.ts +1 -1
  1193. package/server/services/workshop/daq/bus/index.ts +5 -12
  1194. package/server/services/workshop/daq/daq-controller/contracts.ts +39 -39
  1195. package/server/services/workshop/daq/daq-controller/facade.ts +28 -28
  1196. package/server/services/workshop/daq/daq-controller/frames.ts +137 -137
  1197. package/server/services/workshop/daq/daq-controller/helpers.ts +52 -52
  1198. package/server/services/workshop/daq/daq-controller/index.ts +22 -22
  1199. package/server/services/workshop/daq/daq-controller/runtime-control.ts +72 -72
  1200. package/server/services/workshop/daq/daq-controller/sweep-alarms.ts +176 -176
  1201. package/server/services/workshop/daq/daq-controller/tsdb-twin.ts +138 -138
  1202. package/server/services/workshop/daq/drivers/http.ts +95 -95
  1203. package/server/services/workshop/daq/drivers/mock.ts +130 -130
  1204. package/server/services/workshop/daq/drivers/modbus-rtu.ts +67 -67
  1205. package/server/services/workshop/daq/drivers/modbus-tcp.ts +307 -307
  1206. package/server/services/workshop/daq/drivers/opcua.ts +227 -227
  1207. package/server/services/workshop/daq/drivers/s7-stub.ts +29 -29
  1208. package/server/services/workshop/daq/host-bindings.ts +71 -71
  1209. package/server/services/workshop/daq/host-ports.ts +65 -65
  1210. package/server/services/workshop/db/aml-team-seeds.ts +118 -118
  1211. package/server/services/workshop/db/backup-registry.ts +33 -33
  1212. package/server/services/workshop/db/channel-member.repo.ts +122 -122
  1213. package/server/services/workshop/db/channel.repo.ts +203 -203
  1214. package/server/services/workshop/db/chat-message.repo.ts +233 -233
  1215. package/server/services/workshop/db/database/index.ts +18 -18
  1216. package/server/services/workshop/db/database/json.ts +14 -14
  1217. package/server/services/workshop/db/database/open.ts +97 -97
  1218. package/server/services/workshop/db/database/seed-data.ts +60 -60
  1219. package/server/services/workshop/db/hitl-request.repo.ts +221 -221
  1220. package/server/services/workshop/db/notification.repo.ts +199 -199
  1221. package/server/services/workshop/db/readonly.ts +30 -30
  1222. package/server/services/workshop/db/scheduled-task.repo.ts +235 -235
  1223. package/server/services/workshop/db/transaction.ts +72 -72
  1224. package/server/services/workshop/dcw/dcw-controller/contracts.ts +16 -16
  1225. package/server/services/workshop/dcw/dcw-controller/control.ts +78 -78
  1226. package/server/services/workshop/dcw/dcw-controller/facade.ts +19 -19
  1227. package/server/services/workshop/dcw/dcw-controller/index.ts +22 -22
  1228. package/server/services/workshop/dcw/dcw-controller/params.ts +97 -97
  1229. package/server/services/workshop/dcw/dcw-controller/products.ts +103 -103
  1230. package/server/services/workshop/dcw/dcw-controller/write-audit.ts +49 -49
  1231. package/server/services/workshop/dcw/dcw-templates.ts +136 -136
  1232. package/server/services/workshop/dcw/param-conversion.ts +78 -78
  1233. package/server/services/workshop/dcw/param-map.repo.ts +349 -349
  1234. package/server/services/workshop/dcw/plugin-bridge.ts +45 -45
  1235. package/server/services/workshop/dcw/recipe-rollback-manager/contracts.ts +26 -26
  1236. package/server/services/workshop/dcw/recipe-rollback-manager/facade.ts +13 -13
  1237. package/server/services/workshop/dcw/recipe-rollback-manager/helpers.ts +30 -30
  1238. package/server/services/workshop/dcw/recipe-rollback-manager/index.ts +17 -17
  1239. package/server/services/workshop/dcw/recipe-rollback-manager/internal.ts +33 -33
  1240. package/server/services/workshop/dcw/recipe-rollback-manager/judge.ts +52 -52
  1241. package/server/services/workshop/dcw/recipe-rollback-manager/lock.ts +137 -137
  1242. package/server/services/workshop/dcw/recipe-rollback-manager/rollback.ts +190 -190
  1243. package/server/services/workshop/dcw/recipe-rollback-manager/state.ts +21 -21
  1244. package/server/services/workshop/dcw/recipe-rollback-manager/sweep.ts +77 -77
  1245. package/server/services/workshop/dcw/recipe-rollback-manager/types.ts +3 -3
  1246. package/server/services/workshop/dcw/recipe-rollback-manager/views.ts +214 -214
  1247. package/server/services/workshop/eda/chart-repo.ts +1 -1
  1248. package/server/services/workshop/eda/eda-db.ts +13 -0
  1249. package/server/services/workshop/eda/template-repo.ts +101 -0
  1250. package/server/services/workshop/exp/exp-collector.ts +275 -275
  1251. package/server/services/workshop/exp/exp-state.repo.ts +339 -339
  1252. package/server/services/workshop/mes/mes-controller.ts +1155 -1155
  1253. package/server/services/workshop/mes/mes-hook.ts +567 -567
  1254. package/server/services/workshop/ontology/subgraph.core.ts +300 -300
  1255. package/server/services/workshop/ontology/subgraph.service.ts +113 -113
  1256. package/server/services/workshop/plugins/host/api.mjs +90 -90
  1257. package/server/services/workshop/plugins/host/config.mjs +135 -135
  1258. package/server/services/workshop/plugins/host/index.mjs +23 -23
  1259. package/server/services/workshop/plugins/host/init.mjs +109 -109
  1260. package/server/services/workshop/plugins/host/load.mjs +321 -321
  1261. package/server/services/workshop/plugins/host/reload.mjs +94 -94
  1262. package/server/services/workshop/plugins/host/rollback.mjs +72 -72
  1263. package/server/services/workshop/plugins/host/state.mjs +54 -54
  1264. package/server/services/workshop/plugins/host/toggle.mjs +64 -64
  1265. package/server/services/workshop/plugins/host.mjs +9 -9
  1266. package/server/services/workshop/runtime/agent-runtime/facade.ts +7 -7
  1267. package/server/services/workshop/runtime/agent-runtime/helpers.ts +18 -18
  1268. package/server/services/workshop/runtime/agent-runtime/index.ts +19 -19
  1269. package/server/services/workshop/runtime/agent-runtime/lifecycle.ts +137 -137
  1270. package/server/services/workshop/runtime/chat-mention.ts +164 -164
  1271. package/server/services/workshop/runtime/chat-projection.ts +246 -246
  1272. package/server/services/workshop/runtime/manager/admin-agents.ts +268 -268
  1273. package/server/services/workshop/runtime/manager/bus.ts +182 -182
  1274. package/server/services/workshop/runtime/manager/channel-template-constants.ts +20 -20
  1275. package/server/services/workshop/runtime/manager/chat-reply.ts +181 -181
  1276. package/server/services/workshop/runtime/manager/chat.ts +384 -384
  1277. package/server/services/workshop/runtime/manager/facade.ts +24 -24
  1278. package/server/services/workshop/runtime/manager/helpers.ts +119 -119
  1279. package/server/services/workshop/runtime/manager/index.ts +42 -42
  1280. package/server/services/workshop/runtime/manager/internal.ts +73 -73
  1281. package/server/services/workshop/runtime/manager/notifications.ts +108 -108
  1282. package/server/services/workshop/runtime/manager/teams.ts +148 -148
  1283. package/server/services/workshop/runtime/memory/contracts.ts +18 -18
  1284. package/server/services/workshop/runtime/memory/facade.ts +10 -10
  1285. package/server/services/workshop/runtime/memory/helpers.ts +196 -196
  1286. package/server/services/workshop/runtime/memory/index.ts +27 -27
  1287. package/server/services/workshop/runtime/memory/score.ts +33 -33
  1288. package/server/services/workshop/runtime/memory/state.ts +40 -40
  1289. package/server/services/workshop/runtime/monitor.ts +3 -3
  1290. package/server/services/workshop/runtime/platform-notice.ts +113 -113
  1291. package/server/services/workshop/runtime/schedule-runtime.ts +347 -347
  1292. package/server/services/workshop/runtime/scheduler-loop/contracts.ts +29 -29
  1293. package/server/services/workshop/runtime/scheduler-loop/facade.ts +7 -7
  1294. package/server/services/workshop/runtime/scheduler-loop/helpers.ts +14 -14
  1295. package/server/services/workshop/runtime/scheduler-loop/index.ts +16 -16
  1296. package/server/services/workshop/runtime/task-engine/facade.ts +7 -7
  1297. package/server/services/workshop/runtime/task-engine/index.ts +15 -15
  1298. package/server/services/workshop/runtime/task-engine/types.ts +3 -3
  1299. package/server/services/workshop/runtime/user-notification-hub.ts +192 -192
  1300. package/server/types/pg.d.ts +49 -49
  1301. package/server/utils/approval-gate.ts +67 -67
  1302. package/server/utils/mojibake-guard.ts +29 -29
  1303. package/server/utils/stability-severity.ts +77 -77
  1304. package/shared/config/groups.mjs +241 -241
  1305. package/shared/dcw-protocol/catalog.ts +232 -232
  1306. package/shared/dcw-protocol/closed-loop.ts +137 -137
  1307. package/shared/lru.mjs +97 -97
  1308. package/tui/README.md +74 -74
  1309. package/tui/aw-tui.mjs +445 -445
  1310. package/tui/commands/index.mjs +287 -287
  1311. package/tui/components/chat-log.mjs +42 -42
  1312. package/tui/components/monitor-pane.mjs +39 -39
  1313. package/tui/components/root.mjs +53 -53
  1314. package/tui/components/status-bar.mjs +33 -33
  1315. package/tui/lib/api.mjs +82 -82
  1316. package/tui/lib/pickers.mjs +121 -121
  1317. package/tui/lib/reducers.mjs +218 -218
  1318. package/tui/lib/state.mjs +86 -86
  1319. package/tui/lib/virtual-terminal.mjs +48 -48
  1320. package/tui/lib/ws.mjs +125 -125
  1321. package/tui/theme.mjs +38 -38
  1322. package/.output/.AgentWorkShop/aml-python/__pycache__/aml_eval.cpython-312.pyc +0 -0
  1323. package/.output/.AgentWorkShop/aml-python/__pycache__/amlkit.cpython-312.pyc +0 -0
  1324. package/.output/.AgentWorkShop/aml-python/__pycache__/train-example.cpython-312.pyc +0 -0
  1325. package/.output/.AgentWorkShop/aml-python/__pycache__/train-hybrid-example.cpython-312.pyc +0 -0
  1326. package/.output/public/_nuxt/BRYBzVMJ.js +0 -1
  1327. package/.output/public/_nuxt/BW2uTUx52.js +0 -2
  1328. package/.output/public/_nuxt/BtZKe9ZV.js +0 -1
  1329. package/.output/public/_nuxt/CfFUK6932.js +0 -2
  1330. package/.output/public/_nuxt/D6FhDrYe2.js +0 -1
  1331. package/.output/public/_nuxt/DF9ETYJ32.js +0 -1
  1332. package/.output/public/_nuxt/DGu_fna7.js +0 -1
  1333. package/.output/public/_nuxt/D_59BNP1.js +0 -14
  1334. package/.output/public/_nuxt/DhW7cFOa.js +0 -1
  1335. package/.output/public/_nuxt/Dz9C2pTa.js +0 -1
  1336. package/.output/public/_nuxt/OmpTerminalPanel.ComMDrA8.css +0 -1
  1337. package/.output/public/_nuxt/PluginSlot.CGH0vb95.css +0 -1
  1338. package/.output/public/_nuxt/TownView.CC3t-Dte.css +0 -1
  1339. package/.output/public/_nuxt/YNhAoK-R2.js +0 -1
  1340. package/.output/public/_nuxt/aml.PalMp-5n.css +0 -1
  1341. package/.output/public/_nuxt/builds/meta/20934eea-96ab-412d-b0cd-0061716d8cc4.json +0 -1
  1342. package/.output/public/_nuxt/ontology.B_3Wn907.css +0 -1
  1343. package/.output/public/_nuxt/permissions.DxuOOIqQ.css +0 -1
  1344. package/.output/public/_nuxt/schedules.BXNJ9q_I.css +0 -1
  1345. package/.output/public/_nuxt/tools.BwXFAb-X.css +0 -1
  1346. package/.output/server/chunks/build/AuthGate-nF1evO4v.mjs +0 -716
  1347. package/.output/server/chunks/build/AuthGate-nF1evO4v.mjs.map +0 -1
  1348. package/.output/server/chunks/build/FormItemContext-BlyzocS0.mjs +0 -72
  1349. package/.output/server/chunks/build/FormItemContext-BlyzocS0.mjs.map +0 -1
  1350. package/.output/server/chunks/build/OmpTerminalPanel-BhvhQ1gG.mjs +0 -942
  1351. package/.output/server/chunks/build/OmpTerminalPanel-BhvhQ1gG.mjs.map +0 -1
  1352. package/.output/server/chunks/build/PluginSlot-BUKXwV2X.mjs +0 -141
  1353. package/.output/server/chunks/build/PluginSlot-BUKXwV2X.mjs.map +0 -1
  1354. package/.output/server/chunks/build/TownView-BWMDbosY.mjs +0 -6489
  1355. package/.output/server/chunks/build/TownView-BWMDbosY.mjs.map +0 -1
  1356. package/.output/server/chunks/build/_id_-BK-t8nRG.mjs +0 -392
  1357. package/.output/server/chunks/build/_id_-BK-t8nRG.mjs.map +0 -1
  1358. package/.output/server/chunks/build/_id_-CZPlPDm4.mjs +0 -2045
  1359. package/.output/server/chunks/build/_id_-CZPlPDm4.mjs.map +0 -1
  1360. package/.output/server/chunks/build/_wsId_-BPy-Aj9L.mjs +0 -14297
  1361. package/.output/server/chunks/build/_wsId_-BPy-Aj9L.mjs.map +0 -1
  1362. package/.output/server/chunks/build/agents-CpNLdI8E.mjs +0 -1078
  1363. package/.output/server/chunks/build/agents-CpNLdI8E.mjs.map +0 -1
  1364. package/.output/server/chunks/build/alert-D0ivtTGy.mjs +0 -263
  1365. package/.output/server/chunks/build/alert-D0ivtTGy.mjs.map +0 -1
  1366. package/.output/server/chunks/build/aml-DRAFRcGU.mjs +0 -814
  1367. package/.output/server/chunks/build/aml-DRAFRcGU.mjs.map +0 -1
  1368. package/.output/server/chunks/build/analysis-p-dBkjoK.mjs +0 -533
  1369. package/.output/server/chunks/build/analysis-p-dBkjoK.mjs.map +0 -1
  1370. package/.output/server/chunks/build/api-B4Om0mEc.mjs.map +0 -1
  1371. package/.output/server/chunks/build/api-BEW_ebY_.mjs.map +0 -1
  1372. package/.output/server/chunks/build/api-BsAgXWxi.mjs.map +0 -1
  1373. package/.output/server/chunks/build/api-error-BwAQLw44.mjs +0 -47
  1374. package/.output/server/chunks/build/api-error-BwAQLw44.mjs.map +0 -1
  1375. package/.output/server/chunks/build/apiClient-BvXtNzC8.mjs +0 -81
  1376. package/.output/server/chunks/build/apiClient-BvXtNzC8.mjs.map +0 -1
  1377. package/.output/server/chunks/build/board-Dl2Ar22r.mjs +0 -178
  1378. package/.output/server/chunks/build/board-Dl2Ar22r.mjs.map +0 -1
  1379. package/.output/server/chunks/build/card-Cqk0Ur-L.mjs +0 -953
  1380. package/.output/server/chunks/build/card-Cqk0Ur-L.mjs.map +0 -1
  1381. package/.output/server/chunks/build/channel-templates-ByHOQQkO.mjs +0 -942
  1382. package/.output/server/chunks/build/channel-templates-ByHOQQkO.mjs.map +0 -1
  1383. package/.output/server/chunks/build/checkbox-CrT4cnfu.mjs +0 -439
  1384. package/.output/server/chunks/build/checkbox-CrT4cnfu.mjs.map +0 -1
  1385. package/.output/server/chunks/build/client-only-qNA2OVV_.mjs +0 -43
  1386. package/.output/server/chunks/build/client-only-qNA2OVV_.mjs.map +0 -1
  1387. package/.output/server/chunks/build/core-CgTOPS4t.mjs +0 -294
  1388. package/.output/server/chunks/build/core-CgTOPS4t.mjs.map +0 -1
  1389. package/.output/server/chunks/build/daq-CdxcfY_G.mjs +0 -1266
  1390. package/.output/server/chunks/build/daq-CdxcfY_G.mjs.map +0 -1
  1391. package/.output/server/chunks/build/data-D8uX1dnm.mjs +0 -481
  1392. package/.output/server/chunks/build/data-D8uX1dnm.mjs.map +0 -1
  1393. package/.output/server/chunks/build/dcw-BlDQtS4q.mjs +0 -505
  1394. package/.output/server/chunks/build/dcw-BlDQtS4q.mjs.map +0 -1
  1395. package/.output/server/chunks/build/default-CNWS6NUw.mjs +0 -2353
  1396. package/.output/server/chunks/build/default-CNWS6NUw.mjs.map +0 -1
  1397. package/.output/server/chunks/build/descriptions-BNlfKG9y.mjs +0 -406
  1398. package/.output/server/chunks/build/descriptions-BNlfKG9y.mjs.map +0 -1
  1399. package/.output/server/chunks/build/drawer-Caji0PLs.mjs +0 -834
  1400. package/.output/server/chunks/build/drawer-Caji0PLs.mjs.map +0 -1
  1401. package/.output/server/chunks/build/dropdown-BNwTVGde.mjs +0 -14
  1402. package/.output/server/chunks/build/dropdown-BNwTVGde.mjs.map +0 -1
  1403. package/.output/server/chunks/build/dropdown-Cd-xPhR6.mjs +0 -540
  1404. package/.output/server/chunks/build/dropdown-Cd-xPhR6.mjs.map +0 -1
  1405. package/.output/server/chunks/build/es-Bxu10NJ2.mjs.map +0 -1
  1406. package/.output/server/chunks/build/firstNotUndefined-8H5_qHUu.mjs +0 -2448
  1407. package/.output/server/chunks/build/firstNotUndefined-8H5_qHUu.mjs.map +0 -1
  1408. package/.output/server/chunks/build/form-D_UpWPN4.mjs +0 -4712
  1409. package/.output/server/chunks/build/form-D_UpWPN4.mjs.map +0 -1
  1410. package/.output/server/chunks/build/hasIn-DBdElbjM.mjs +0 -553
  1411. package/.output/server/chunks/build/hasIn-DBdElbjM.mjs.map +0 -1
  1412. package/.output/server/chunks/build/hitl-Bd30yr1J.mjs +0 -132
  1413. package/.output/server/chunks/build/hitl-Bd30yr1J.mjs.map +0 -1
  1414. package/.output/server/chunks/build/input-GtPuSEgt.mjs +0 -2181
  1415. package/.output/server/chunks/build/input-GtPuSEgt.mjs.map +0 -1
  1416. package/.output/server/chunks/build/input-number-BNlNDK7H.mjs +0 -1120
  1417. package/.output/server/chunks/build/input-number-BNlNDK7H.mjs.map +0 -1
  1418. package/.output/server/chunks/build/interval-DvHBIIZh.mjs +0 -9
  1419. package/.output/server/chunks/build/interval-DvHBIIZh.mjs.map +0 -1
  1420. package/.output/server/chunks/build/isNumeric-CP7q_yhz.mjs +0 -7
  1421. package/.output/server/chunks/build/isNumeric-CP7q_yhz.mjs.map +0 -1
  1422. package/.output/server/chunks/build/logs-pRb-TMWa.mjs +0 -427
  1423. package/.output/server/chunks/build/logs-pRb-TMWa.mjs.map +0 -1
  1424. package/.output/server/chunks/build/menu-BXt-X0dt.mjs +0 -1952
  1425. package/.output/server/chunks/build/menu-BXt-X0dt.mjs.map +0 -1
  1426. package/.output/server/chunks/build/monitor-Cq6hRFeQ.mjs +0 -2253
  1427. package/.output/server/chunks/build/monitor-Cq6hRFeQ.mjs.map +0 -1
  1428. package/.output/server/chunks/build/ontology-DK0Mf0zT.mjs +0 -1406
  1429. package/.output/server/chunks/build/ontology-DK0Mf0zT.mjs.map +0 -1
  1430. package/.output/server/chunks/build/operations-SMQrRAcr.mjs +0 -311
  1431. package/.output/server/chunks/build/operations-SMQrRAcr.mjs.map +0 -1
  1432. package/.output/server/chunks/build/optimizer-BlWTsM-W.mjs +0 -202
  1433. package/.output/server/chunks/build/optimizer-BlWTsM-W.mjs.map +0 -1
  1434. package/.output/server/chunks/build/pages-AFRP4-EL.mjs +0 -542
  1435. package/.output/server/chunks/build/pages-AFRP4-EL.mjs.map +0 -1
  1436. package/.output/server/chunks/build/pagination-DTAconUo.mjs +0 -1346
  1437. package/.output/server/chunks/build/pagination-DTAconUo.mjs.map +0 -1
  1438. package/.output/server/chunks/build/permissions-DgXQZSyx.mjs +0 -637
  1439. package/.output/server/chunks/build/permissions-DgXQZSyx.mjs.map +0 -1
  1440. package/.output/server/chunks/build/plugins-LRjaSEZy.mjs +0 -272
  1441. package/.output/server/chunks/build/plugins-LRjaSEZy.mjs.map +0 -1
  1442. package/.output/server/chunks/build/popconfirm-DxYPGRgS.mjs +0 -340
  1443. package/.output/server/chunks/build/popconfirm-DxYPGRgS.mjs.map +0 -1
  1444. package/.output/server/chunks/build/responsiveObserve-DM3hpzhU.mjs +0 -78
  1445. package/.output/server/chunks/build/responsiveObserve-DM3hpzhU.mjs.map +0 -1
  1446. package/.output/server/chunks/build/schedules-dSnr8url.mjs +0 -7172
  1447. package/.output/server/chunks/build/schedules-dSnr8url.mjs.map +0 -1
  1448. package/.output/server/chunks/build/segmented-D3HWtHPw.mjs +0 -341
  1449. package/.output/server/chunks/build/segmented-D3HWtHPw.mjs.map +0 -1
  1450. package/.output/server/chunks/build/select-B3Dsb9yq.mjs +0 -3923
  1451. package/.output/server/chunks/build/select-B3Dsb9yq.mjs.map +0 -1
  1452. package/.output/server/chunks/build/settings-BrIhnS2Z.mjs +0 -1014
  1453. package/.output/server/chunks/build/settings-BrIhnS2Z.mjs.map +0 -1
  1454. package/.output/server/chunks/build/space-Dwu2Skt8.mjs +0 -110
  1455. package/.output/server/chunks/build/space-Dwu2Skt8.mjs.map +0 -1
  1456. package/.output/server/chunks/build/spin-C2cuvGth.mjs +0 -357
  1457. package/.output/server/chunks/build/spin-C2cuvGth.mjs.map +0 -1
  1458. package/.output/server/chunks/build/studio-cdoNCfyy.mjs +0 -332
  1459. package/.output/server/chunks/build/studio-cdoNCfyy.mjs.map +0 -1
  1460. package/.output/server/chunks/build/switch-CyR-H6Fb.mjs +0 -377
  1461. package/.output/server/chunks/build/switch-CyR-H6Fb.mjs.map +0 -1
  1462. package/.output/server/chunks/build/table-CmVD-cA9.mjs +0 -7546
  1463. package/.output/server/chunks/build/table-CmVD-cA9.mjs.map +0 -1
  1464. package/.output/server/chunks/build/tabs-Vg0e7cZE.mjs +0 -1924
  1465. package/.output/server/chunks/build/tabs-Vg0e7cZE.mjs.map +0 -1
  1466. package/.output/server/chunks/build/tag-y0sn-xv9.mjs +0 -1156
  1467. package/.output/server/chunks/build/tag-y0sn-xv9.mjs.map +0 -1
  1468. package/.output/server/chunks/build/teams-B1d32eHK.mjs +0 -1203
  1469. package/.output/server/chunks/build/teams-B1d32eHK.mjs.map +0 -1
  1470. package/.output/server/chunks/build/tokens-GYaGJ35Z.mjs +0 -1062
  1471. package/.output/server/chunks/build/tokens-GYaGJ35Z.mjs.map +0 -1
  1472. package/.output/server/chunks/build/tools-s_9U1Djj.mjs +0 -487
  1473. package/.output/server/chunks/build/tools-s_9U1Djj.mjs.map +0 -1
  1474. package/.output/server/chunks/build/tooltip-C2n2nNiQ.mjs +0 -920
  1475. package/.output/server/chunks/build/tooltip-C2n2nNiQ.mjs.map +0 -1
  1476. package/.output/server/chunks/build/town-B5aoiG98.mjs +0 -133
  1477. package/.output/server/chunks/build/town-B5aoiG98.mjs.map +0 -1
  1478. package/.output/server/chunks/build/useAgentHarnessOptions-DOrQHeBh.mjs +0 -124
  1479. package/.output/server/chunks/build/useAgentHarnessOptions-DOrQHeBh.mjs.map +0 -1
  1480. package/.output/server/chunks/build/useAgentTemplateActions-CzlplRWh.mjs +0 -77
  1481. package/.output/server/chunks/build/useAgentTemplateActions-CzlplRWh.mjs.map +0 -1
  1482. package/.output/server/chunks/build/useAgentTemplateForm-DQo1enf2.mjs +0 -117
  1483. package/.output/server/chunks/build/useAgentTemplateForm-DQo1enf2.mjs.map +0 -1
  1484. package/.output/server/chunks/build/useAgentTemplatesCatalog-DP-iMmqz.mjs +0 -133
  1485. package/.output/server/chunks/build/useAgentTemplatesCatalog-DP-iMmqz.mjs.map +0 -1
  1486. package/.output/server/chunks/build/useAmlDatasets-DeoE1idn.mjs +0 -92
  1487. package/.output/server/chunks/build/useAmlDatasets-DeoE1idn.mjs.map +0 -1
  1488. package/.output/server/chunks/build/useAmlEntities-BJhvdqHJ.mjs +0 -86
  1489. package/.output/server/chunks/build/useAmlEntities-BJhvdqHJ.mjs.map +0 -1
  1490. package/.output/server/chunks/build/useAmlEnv-CDIZ6xTe.mjs +0 -194
  1491. package/.output/server/chunks/build/useAmlEnv-CDIZ6xTe.mjs.map +0 -1
  1492. package/.output/server/chunks/build/useAmlExperiments-Dloi834i.mjs +0 -89
  1493. package/.output/server/chunks/build/useAmlExperiments-Dloi834i.mjs.map +0 -1
  1494. package/.output/server/chunks/build/useAmlJobs-BF9LpwXz.mjs +0 -267
  1495. package/.output/server/chunks/build/useAmlJobs-BF9LpwXz.mjs.map +0 -1
  1496. package/.output/server/chunks/build/useAmlModels-_bweOr3R.mjs +0 -93
  1497. package/.output/server/chunks/build/useAmlModels-_bweOr3R.mjs.map +0 -1
  1498. package/.output/server/chunks/build/useAmlNotes-DQj980iX.mjs +0 -86
  1499. package/.output/server/chunks/build/useAmlNotes-DQj980iX.mjs.map +0 -1
  1500. package/.output/server/chunks/build/useAmlPredict-DHNgDSJn.mjs +0 -130
  1501. package/.output/server/chunks/build/useAmlPredict-DHNgDSJn.mjs.map +0 -1
  1502. package/.output/server/chunks/build/useAnalysisFeed-BrEGV_9x.mjs +0 -129
  1503. package/.output/server/chunks/build/useAnalysisFeed-BrEGV_9x.mjs.map +0 -1
  1504. package/.output/server/chunks/build/useDaqAddNode-D_Rkju0f.mjs +0 -142
  1505. package/.output/server/chunks/build/useDaqAddNode-D_Rkju0f.mjs.map +0 -1
  1506. package/.output/server/chunks/build/useDaqDetailBinding-DCWaLKXT.mjs +0 -70
  1507. package/.output/server/chunks/build/useDaqDetailBinding-DCWaLKXT.mjs.map +0 -1
  1508. package/.output/server/chunks/build/useDaqDetailFrames-BOIcOJRB.mjs +0 -79
  1509. package/.output/server/chunks/build/useDaqDetailFrames-BOIcOJRB.mjs.map +0 -1
  1510. package/.output/server/chunks/build/useDaqDetailHistory-D6WulPVs.mjs +0 -176
  1511. package/.output/server/chunks/build/useDaqDetailHistory-D6WulPVs.mjs.map +0 -1
  1512. package/.output/server/chunks/build/useDaqDetailNode-DeOsDxK5.mjs +0 -99
  1513. package/.output/server/chunks/build/useDaqDetailNode-DeOsDxK5.mjs.map +0 -1
  1514. package/.output/server/chunks/build/useDaqDetailParams-Cm9a9r5G.mjs +0 -159
  1515. package/.output/server/chunks/build/useDaqDetailParams-Cm9a9r5G.mjs.map +0 -1
  1516. package/.output/server/chunks/build/useDaqFilters-CctmO03p.mjs +0 -222
  1517. package/.output/server/chunks/build/useDaqFilters-CctmO03p.mjs.map +0 -1
  1518. package/.output/server/chunks/build/useDaqOptimizations-CmX_dpBc.mjs +0 -136
  1519. package/.output/server/chunks/build/useDaqOptimizations-CmX_dpBc.mjs.map +0 -1
  1520. package/.output/server/chunks/build/useDaqStream-B9ZBVQrI.mjs +0 -395
  1521. package/.output/server/chunks/build/useDaqStream-B9ZBVQrI.mjs.map +0 -1
  1522. package/.output/server/chunks/build/useDaqTemplates-CK37sMfi.mjs +0 -187
  1523. package/.output/server/chunks/build/useDaqTemplates-CK37sMfi.mjs.map +0 -1
  1524. package/.output/server/chunks/build/useDashboardData-B36wVWo2.mjs +0 -153
  1525. package/.output/server/chunks/build/useDashboardData-B36wVWo2.mjs.map +0 -1
  1526. package/.output/server/chunks/build/useDcwAddNode-DACVcEHs.mjs +0 -219
  1527. package/.output/server/chunks/build/useDcwAddNode-DACVcEHs.mjs.map +0 -1
  1528. package/.output/server/chunks/build/useDcwCards-SaiImIYQ.mjs.map +0 -1
  1529. package/.output/server/chunks/build/useDcwDetailScope-DLOklSMO.mjs +0 -184
  1530. package/.output/server/chunks/build/useDcwDetailScope-DLOklSMO.mjs.map +0 -1
  1531. package/.output/server/chunks/build/useDcwDetailTemplates-ClmIdZ40.mjs +0 -148
  1532. package/.output/server/chunks/build/useDcwDetailTemplates-ClmIdZ40.mjs.map +0 -1
  1533. package/.output/server/chunks/build/useDcwFilter-CPMyCltx.mjs +0 -71
  1534. package/.output/server/chunks/build/useDcwFilter-CPMyCltx.mjs.map +0 -1
  1535. package/.output/server/chunks/build/useDcwLedger-0ie-0WTc.mjs.map +0 -1
  1536. package/.output/server/chunks/build/useDcwLineMutations-DNxo66yM.mjs +0 -137
  1537. package/.output/server/chunks/build/useDcwLineMutations-DNxo66yM.mjs.map +0 -1
  1538. package/.output/server/chunks/build/useDcwLineRun-CHskwscT.mjs +0 -104
  1539. package/.output/server/chunks/build/useDcwLineRun-CHskwscT.mjs.map +0 -1
  1540. package/.output/server/chunks/build/useDcwParamApprovals-DtScUc-W.mjs +0 -121
  1541. package/.output/server/chunks/build/useDcwParamApprovals-DtScUc-W.mjs.map +0 -1
  1542. package/.output/server/chunks/build/useDcwProducts-BMaxzLu6.mjs +0 -93
  1543. package/.output/server/chunks/build/useDcwProducts-BMaxzLu6.mjs.map +0 -1
  1544. package/.output/server/chunks/build/useDcwQuery-TVU3Eo0M.mjs +0 -98
  1545. package/.output/server/chunks/build/useDcwQuery-TVU3Eo0M.mjs.map +0 -1
  1546. package/.output/server/chunks/build/useDcwQuickActions-BREFmR9T.mjs +0 -88
  1547. package/.output/server/chunks/build/useDcwQuickActions-BREFmR9T.mjs.map +0 -1
  1548. package/.output/server/chunks/build/useDcwRecipes-Bc9urA1N.mjs +0 -258
  1549. package/.output/server/chunks/build/useDcwRecipes-Bc9urA1N.mjs.map +0 -1
  1550. package/.output/server/chunks/build/useDcwStream-Dir5ufAU.mjs +0 -452
  1551. package/.output/server/chunks/build/useDcwStream-Dir5ufAU.mjs.map +0 -1
  1552. package/.output/server/chunks/build/useDcwTemplates-BzagZztS.mjs +0 -91
  1553. package/.output/server/chunks/build/useDcwTemplates-BzagZztS.mjs.map +0 -1
  1554. package/.output/server/chunks/build/useDcwWrites-BROwTLCn.mjs +0 -140
  1555. package/.output/server/chunks/build/useDcwWrites-BROwTLCn.mjs.map +0 -1
  1556. package/.output/server/chunks/build/useDeviceTwins-BqwVJaZg.mjs +0 -128
  1557. package/.output/server/chunks/build/useDeviceTwins-BqwVJaZg.mjs.map +0 -1
  1558. package/.output/server/chunks/build/useExpConfirmations-BM626N4p.mjs +0 -107
  1559. package/.output/server/chunks/build/useExpConfirmations-BM626N4p.mjs.map +0 -1
  1560. package/.output/server/chunks/build/useLocalTime-uVSM44Um.mjs +0 -55
  1561. package/.output/server/chunks/build/useLocalTime-uVSM44Um.mjs.map +0 -1
  1562. package/.output/server/chunks/build/useLogsManual-cVBZQ_Mt.mjs +0 -88
  1563. package/.output/server/chunks/build/useLogsManual-cVBZQ_Mt.mjs.map +0 -1
  1564. package/.output/server/chunks/build/useLogsQuery-D7hrJ3yn.mjs +0 -150
  1565. package/.output/server/chunks/build/useLogsQuery-D7hrJ3yn.mjs.map +0 -1
  1566. package/.output/server/chunks/build/useLogsScope-aaPQeTRm.mjs +0 -83
  1567. package/.output/server/chunks/build/useLogsScope-aaPQeTRm.mjs.map +0 -1
  1568. package/.output/server/chunks/build/useMonitorData-DIkiLr_h.mjs +0 -135
  1569. package/.output/server/chunks/build/useMonitorData-DIkiLr_h.mjs.map +0 -1
  1570. package/.output/server/chunks/build/useMonitorFormat-CyURtH8N.mjs +0 -91
  1571. package/.output/server/chunks/build/useMonitorFormat-CyURtH8N.mjs.map +0 -1
  1572. package/.output/server/chunks/build/useOperationsFeed-Ci4mZAn_.mjs +0 -195
  1573. package/.output/server/chunks/build/useOperationsFeed-Ci4mZAn_.mjs.map +0 -1
  1574. package/.output/server/chunks/build/useOpsLog-C-M6Eace.mjs +0 -149
  1575. package/.output/server/chunks/build/useOpsLog-C-M6Eace.mjs.map +0 -1
  1576. package/.output/server/chunks/build/useRecipeDispatchApprovals-BYtiqfeb.mjs +0 -156
  1577. package/.output/server/chunks/build/useRecipeDispatchApprovals-BYtiqfeb.mjs.map +0 -1
  1578. package/.output/server/chunks/build/useTeamActions-I_8QWp9w.mjs +0 -79
  1579. package/.output/server/chunks/build/useTeamActions-I_8QWp9w.mjs.map +0 -1
  1580. package/.output/server/chunks/build/useTeamAddMemberDialog-BLn4nTuy.mjs +0 -84
  1581. package/.output/server/chunks/build/useTeamAddMemberDialog-BLn4nTuy.mjs.map +0 -1
  1582. package/.output/server/chunks/build/useTeamCreateDialog-Bp5qKtpI.mjs +0 -97
  1583. package/.output/server/chunks/build/useTeamCreateDialog-Bp5qKtpI.mjs.map +0 -1
  1584. package/.output/server/chunks/build/useTeamDeployDialog-DwIaz6Cx.mjs +0 -80
  1585. package/.output/server/chunks/build/useTeamDeployDialog-DwIaz6Cx.mjs.map +0 -1
  1586. package/.output/server/chunks/build/useTeamPluginDialog-B932gZOI.mjs +0 -103
  1587. package/.output/server/chunks/build/useTeamPluginDialog-B932gZOI.mjs.map +0 -1
  1588. package/.output/server/chunks/build/useTeamsCatalog-DBwaLQBw.mjs +0 -123
  1589. package/.output/server/chunks/build/useTeamsCatalog-DBwaLQBw.mjs.map +0 -1
  1590. package/.output/server/chunks/build/useTokenCreate-Ctl0YGhL.mjs +0 -115
  1591. package/.output/server/chunks/build/useTokenCreate-Ctl0YGhL.mjs.map +0 -1
  1592. package/.output/server/chunks/build/useTokenRename-Cm3ypSfN.mjs +0 -87
  1593. package/.output/server/chunks/build/useTokenRename-Cm3ypSfN.mjs.map +0 -1
  1594. package/.output/server/chunks/build/useTokenReveal-CeoWL5Mt.mjs +0 -118
  1595. package/.output/server/chunks/build/useTokenReveal-CeoWL5Mt.mjs.map +0 -1
  1596. package/.output/server/chunks/build/useTokensList-CNIzON3u.mjs +0 -92
  1597. package/.output/server/chunks/build/useTokensList-CNIzON3u.mjs.map +0 -1
  1598. package/.output/server/chunks/build/useWorkbenchAuth-CY-bVFMu.mjs +0 -141
  1599. package/.output/server/chunks/build/useWorkbenchAuth-CY-bVFMu.mjs.map +0 -1
  1600. package/.output/server/chunks/build/useWorkbenchWorkspaces-DhZQFss9.mjs +0 -138
  1601. package/.output/server/chunks/build/useWorkbenchWorkspaces-DhZQFss9.mjs.map +0 -1
  1602. package/.output/server/chunks/build/useWorkshopApi-CaSItJVq.mjs +0 -119
  1603. package/.output/server/chunks/build/useWorkshopApi-CaSItJVq.mjs.map +0 -1
  1604. package/.output/server/chunks/build/useWorkshopWs-YQ5URrbt.mjs +0 -1659
  1605. package/.output/server/chunks/build/useWorkshopWs-YQ5URrbt.mjs.map +0 -1
  1606. package/.output/server/chunks/build/useWorkspaceAuth-Dlvj9csD.mjs.map +0 -1
  1607. package/.output/server/chunks/build/useWorkspaceChannels-CPFepxTN.mjs +0 -92
  1608. package/.output/server/chunks/build/useWorkspaceChannels-CPFepxTN.mjs.map +0 -1
  1609. package/.output/server/chunks/build/useWorkspaceShell-BCypjjjE.mjs +0 -168
  1610. package/.output/server/chunks/build/useWorkspaceShell-BCypjjjE.mjs.map +0 -1
  1611. package/.output/server/chunks/build/users-DjiVC_tS.mjs +0 -569
  1612. package/.output/server/chunks/build/users-DjiVC_tS.mjs.map +0 -1
  1613. package/.output/server/chunks/build/workshop-1gKeDASV.mjs +0 -546
  1614. package/.output/server/chunks/build/workshop-1gKeDASV.mjs.map +0 -1
  1615. package/app/.mimosa/hook-state/sess_05189059-e42d-4188-8911-4f7baabe009b.json +0 -1
  1616. package/app/.mimosa/hook-state/sess_05189059-e42d-4188-8911-4f7baabe009b.mtg0vz68-49792-75b0709555.baseline/1459e6269990a5d229b9228c8b2f62ffaa7d350068380ae8b875fee0db45cca6.source +0 -180
  1617. package/app/.mimosa/hook-state/sess_05189059-e42d-4188-8911-4f7baabe009b.mtg0vz68-49792-75b0709555.baseline/c2991e909c70c5c12b90a407c7adcf63384c51668a2b334e6e047fa675c268fe.source +0 -305
  1618. package/app/.mimosa/hook-state/sess_05189059-e42d-4188-8911-4f7baabe009b.mtg0vz68-49792-75b0709555.baseline/e09129039d1e27e3fac24becc9bdafd2d1a7c8049bff24173df007be865f0165.source +0 -264
  1619. package/app/.mimosa/hook-status/sess_05189059-e42d-4188-8911-4f7baabe009b-28ef7c75ea.json +0 -14
  1620. package/scripts/e2e-direct-rest-simulator-paper.mjs +0 -624
  1621. package/scripts/e2e-pi-simulator-paper.mjs +0 -2316
  1622. package/scripts/e2e-registered-harness-simulator-paper.mjs +0 -1926
  1623. package/scripts/e2e-simulator-optimizer-paper.mjs +0 -264
  1624. package/scripts/fixtures/omp-paper-harness.mjs +0 -163
  1625. package/server/.mimosa/hook-state/sess_869e5bfd-07f4-4b6e-a991-6221fcf6b7d2.json +0 -1
  1626. package/server/.mimosa/hook-state/sess_869e5bfd-07f4-4b6e-a991-6221fcf6b7d2.mvhn1irp-99488-e3fdc1cbfc.baseline/942d2679b87b96c612b4f2a425c3ccc5b6f3234f0cf589a8441602f866fbe277.source +0 -41
  1627. package/server/.mimosa/hook-state/sess_869e5bfd-07f4-4b6e-a991-6221fcf6b7d2.mvhn1irp-99488-e3fdc1cbfc.baseline/dd617a82339d2c61e49e28e416aabeb2fc100fb3cb1beca18d02dfb833214af6.source +0 -51
  1628. package/server/.mimosa/hook-status/sess_869e5bfd-07f4-4b6e-a991-6221fcf6b7d2-e67b6b91bf.json +0 -14
  1629. package/server/services/workshop/.mimosa/hook-state/sess_fed429fb-c8b7-4a50-bbd6-45afc580893f.json +0 -1
  1630. package/server/services/workshop/.mimosa/hook-status/sess_fed429fb-c8b7-4a50-bbd6-45afc580893f-e6b75bbfe6.json +0 -14
  1631. package/server/services/workshop/agents/omp-agent/supervision-history.ts +0 -38
  1632. package/server/services/workshop/aml/python/__pycache__/aml_eval.cpython-312.pyc +0 -0
  1633. package/server/services/workshop/aml/python/__pycache__/amlkit.cpython-312.pyc +0 -0
  1634. package/server/services/workshop/aml/python/__pycache__/train-example.cpython-312.pyc +0 -0
  1635. package/server/services/workshop/aml/python/__pycache__/train-hybrid-example.cpython-312.pyc +0 -0
  1636. package/server/services/workshop/optimization/python/.mimosa/hook-state/session_187ec97f45d4bd02369bbe94da527cf1.json +0 -1
  1637. package/server/services/workshop/optimization/python/.mimosa/hook-state/session_187ec97f45d4bd02369bbe94da527cf1.mvjqkcs6-68688-fb7131a89c.baseline/190a6772a4e43801737b4ba6072eb9d53d3099b5d8a9e6f57bc5e8592a26a6c4.source +0 -274
  1638. package/server/services/workshop/optimization/python/.mimosa/hook-status/session_187ec97f45d4bd02369bbe94da527cf1-01ed7f04fa.json +0 -14
  1639. package/server/services/workshop/optimization/python/__pycache__/problems.cpython-312.pyc +0 -0
  1640. /package/.output/public/_nuxt/{9j2J4k4w.js → 9j2J4k4w2.js} +0 -0
  1641. /package/.output/public/_nuxt/{BY3Lbz3h2.js → BY3Lbz3h.js} +0 -0
  1642. /package/.output/public/_nuxt/{DgrK8UCQ.js → BvRk9kiK2.js} +0 -0
  1643. /package/.output/public/_nuxt/{Iub61dX92.js → Iub61dX9.js} +0 -0
  1644. /package/.output/public/_nuxt/{Q-JpBT032.js → Q-JpBT03.js} +0 -0
  1645. /package/.output/public/_nuxt/{dVw8IHY62.js → dVw8IHY6.js} +0 -0
  1646. /package/.output/public/_nuxt/{k9b520K-.js → k9b520K-2.js} +0 -0
@@ -1,857 +1,857 @@
1
- /**
2
- * LIVE 双模式闭环优化全链路:探索式(optimization_explore)→ AML 模型式(trial/MPC/bayes)。
3
- *
4
- * 与 live-aml-optloop.mjs(单通道 hybrid、REST 激励)的分工:本脚本按 2026-09-26 解耦
5
- * 架构跑**两个 Channel** —— 工艺优化通道(aml_optimization,探索/AML 双模式)与
6
- * 训练通道(hybrid_twin,场景冻结/训练/门禁),全部产线写入走 Agent 治理链:
7
- *
8
- * 隔离平台(home 模式,AW_BASE:3061) + 专用模拟器(SIM_BASE:4012 影子,cast-film 预设)
9
- * → admin 注册(首注册即 admin) → provisionTwinLine(6 DCW + 5 DAQ + 6 SP 回读)
10
- * → 【优化通道 B】实例化(chtpl-aml-optimization-default, exploration) + worker 绑定
11
- * → 负向校验:探索模式下 twin_trial_run 被 dispatch 拒绝(EXPLORATION_MODE_NO_MODEL)
12
- * → 【第一轮·探索式】批次1 内 optimization_explore ×N(割线策略收敛膜厚 50μm,
13
- * 真实写入走 dcw_control 全治理链:绑定鉴权/四层限界/60s 间隔/优化记录)
14
- * → 激励采样:批次 2-3 阶跃(线速/模口间隙,为模型可辨识性;manual REST 写入,同样限频)
15
- * → 【训练通道 A】实例化 + worker 绑定 → 场景发现/编译/冻结(用户确认令牌)
16
- * → 骨架 PhysicsSpec → 数据集(控制=SP 回读,目标=膜厚) → hybrid_residual 训练
17
- * → 晋升 shadow → snapshot → twin_trial_run×10(必传 model_id,UQ 才有效)
18
- * → twin_gate_evaluate(12 判据) → 绑定模型到优化通道 B(fail-closed 校验)
19
- * → 【第二轮·模型式】B 自动进入 aml 模式:mpc_optimize(model_id) → precise_search
20
- * → 推荐经 optimization_explore 治理投用 → 复测膜厚;twin_bayes_optimize 收敛寻优
21
- * → 透明度文档 bench/results/<rid>/OPTIMIZATION-LOG.md + state.json(可断点续跑)
22
- *
23
- * 运行: node scripts/live-optloop-two-modes.mjs [--run-id <rid>]
24
- * 断点续跑: 同 --run-id 重跑,已完成 Stage 自动跳过(state.json)。
25
- */
26
- import { mkdirSync, writeFileSync, appendFileSync, existsSync, readFileSync } from 'node:fs'
27
- import { spawn } from 'node:child_process'
28
- import { join, resolve, dirname } from 'node:path'
29
- import { fileURLToPath } from 'node:url'
30
-
31
- const REPO = resolve(dirname(fileURLToPath(import.meta.url)), '..')
32
- const arg = (k, d) => {
33
- const i = process.argv.indexOf(k)
34
- return i >= 0 ? process.argv[i + 1] : d
35
- }
36
- const AW_BASE = process.env.AW_BASE ?? 'http://127.0.0.1:3061'
37
- const AW_PORT = Number(new URL(AW_BASE).port)
38
- const RUN_ID = arg('--run-id', new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19))
39
- const OUT_DIR = join(REPO, 'bench', 'results', `${RUN_ID}-optloop-two-modes`)
40
- mkdirSync(OUT_DIR, { recursive: true })
41
- const LOG_PATH = join(OUT_DIR, 'live-run.log')
42
- const STATE_PATH = join(OUT_DIR, 'state.json')
43
- const DOC_PATH = join(OUT_DIR, 'OPTIMIZATION-LOG.md')
44
- const AML_ROOT = process.env.AW_AML_DIR_LIVE ?? join(REPO, 'aml')
45
- const HOME_DIR = process.env.AW_HOME_DIR ?? join(REPO, '.e2e-optloop-home')
46
-
47
- // 模拟器端口/影子目录必须在 import sim.mjs 之前定死(模块级常量)
48
- process.env.SIM_BASE = process.env.SIM_BASE ?? 'http://127.0.0.1:4012'
49
- process.env.SIM_SHADOW_DIR = process.env.SIM_SHADOW_DIR ?? resolve(REPO, '..', 'plc-node-simulator-bench-4012')
50
- process.env.NO_PROXY = '127.0.0.1,localhost'
51
- process.env.no_proxy = '127.0.0.1,localhost'
52
-
53
- const L = []
54
- function log(line) {
55
- const text = typeof line === 'string' ? line : JSON.stringify(line)
56
- const stamped = `[${new Date().toISOString()}] ${text}`
57
- console.log(stamped)
58
- L.push(text)
59
- appendFileSync(LOG_PATH, stamped + '\n')
60
- }
61
- function section(title) {
62
- log('')
63
- log('════════════════════════════════════════════════════════')
64
- log(` ${title}`)
65
- log('════════════════════════════════════════════════════════')
66
- }
67
- const sleep = ms => new Promise(r => setTimeout(r, ms))
68
-
69
- async function api(method, path, body, token) {
70
- const r = await fetch(AW_BASE + path, {
71
- method,
72
- headers: { 'content-type': 'application/json', ...(token ? { authorization: `Bearer ${token}` } : {}) },
73
- body: body === undefined ? undefined : JSON.stringify(body),
74
- signal: AbortSignal.timeout(120_000),
75
- })
76
- const json = await r.json().catch(() => null)
77
- return { status: r.status, json }
78
- }
79
- const dataOf = r => r.json?.data ?? r.json
80
-
81
- async function invoke(tool, args, agentId, token) {
82
- const r = await api('POST', '/api/workshop/agent-tools/invoke', { agentId, tool, args }, token)
83
- const text = r.json?.data?.result?.text ?? r.json?.result?.text ?? JSON.stringify(r.json ?? {}).slice(0, 600)
84
- log(` [invoke:${agentId.slice(-6)}] ${tool} → ${r.status}`)
85
- return { status: r.status, text, isError: Boolean(r.json?.data?.result?.isError ?? r.json?.result?.isError) }
86
- }
87
-
88
- async function waitFor(predicate, { timeoutMs, everyMs = 4000, what }) {
89
- const t0 = Date.now()
90
- while (Date.now() - t0 < timeoutMs) {
91
- const v = await predicate()
92
- if (v) return v
93
- await sleep(everyMs)
94
- }
95
- throw new Error(`等待超时: ${what}(${timeoutMs}ms)`)
96
- }
97
-
98
- /* ── 断点续跑状态 ── */
99
- const ctx = {
100
- stages: {},
101
- ...(existsSync(STATE_PATH) ? JSON.parse(readFileSync(STATE_PATH, 'utf8')) : {}),
102
- }
103
- function saveState() {
104
- writeFileSync(STATE_PATH, JSON.stringify(ctx, null, 2))
105
- }
106
- async function stage(id, title, fn) {
107
- if (ctx.stages[id]?.done) {
108
- log(`↷ 跳过 Stage ${id} · ${title}(已于 ${ctx.stages[id].at} 完成)`)
109
- return
110
- }
111
- section(`Stage ${id} · ${title}`)
112
- await fn()
113
- ctx.stages[id] = { done: true, at: new Date().toISOString() }
114
- saveState()
115
- }
116
-
117
- /** 膜厚最近窗口均值(平台数采 = 闭环真实观测路径;samples 新→旧,须按 at 排序) */
118
- async function thicknessMean(token, nodeId, windowS = 30) {
119
- const r = await api('GET', `/api/workshop/daq/${nodeId}/samples?bucketMs=1000&limit=${Math.max(60, windowS)}`, undefined, token)
120
- const pts = (dataOf(r)?.points ?? [])
121
- .map(p => ({ at: Number(p.at ?? 0), v: Number(p.avg ?? p.value) }))
122
- .filter(p => Number.isFinite(p.v))
123
- .sort((a, b) => a.at - b.at)
124
- .slice(-windowS)
125
- if (!pts.length) return null
126
- return pts.reduce((a, b) => a + b.v, 0) / pts.length
127
- }
128
-
129
- /** 平台重启后 DAQ 控制器为内存态不会自启 —— 快照/采样前必须显式拉起(幂等) */
130
- async function ensureDaqRunning() {
131
- const r = await api('POST', '/api/workshop/daq/controller', { action: 'start' }, ctx.token)
132
- log(` daq controller start → HTTP ${r.status}`)
133
- await sleep(4000)
134
- }
135
-
136
- /* ════════ S0 · 隔离平台 + 专用模拟器 ════════ */
137
- await stage('S0', '隔离平台 + 专用模拟器(cast-film 预设)', async () => {
138
- const platformUp = async () => {
139
- try {
140
- const r = await fetch(`${AW_BASE}/api/users/setup-status`, { signal: AbortSignal.timeout(5000) })
141
- const j = await r.json().catch(() => null)
142
- return r.status === 200 && j?.data != null
143
- }
144
- catch { return false }
145
- }
146
- if (!(await platformUp())) {
147
- const out = appendFileSync === undefined ? 'ignore' : 'ignore'
148
- const child = spawn(process.execPath, [join(REPO, 'bin', 'aw.mjs'), 'start', '--port', String(AW_PORT)], {
149
- cwd: REPO,
150
- env: {
151
- ...process.env,
152
- AW_MODE: 'home',
153
- AW_HOME: HOME_DIR,
154
- AW_AML_DIR: AML_ROOT,
155
- NUXT_SESSION_PASSWORD: process.env.NUXT_SESSION_PASSWORD ?? 'e2e-session-password-0123456789abcdef',
156
- PORT: String(AW_PORT),
157
- },
158
- detached: true,
159
- stdio: 'ignore',
160
- })
161
- child.unref()
162
- log(`平台冷启: port=${AW_PORT} pid=${child.pid}(home 模式,AW_HOME=${HOME_DIR})`)
163
- log(` AW_AML_DIR=${AML_ROOT}(复用真实训练 venv;模型工件落 repo ./aml)`)
164
- void out
165
- }
166
- await waitFor(platformUp, { timeoutMs: 180_000, what: '平台就绪' })
167
- log(`✔ 平台在线 ${AW_BASE}(home 模式,数据与生产实例零交集)`)
168
-
169
- const { ensureSimulator, applyPreset, simNodes } = await import('../bench/lib/sim.mjs')
170
- const sim = await ensureSimulator({ log: m => log(`[sim] ${m}`) })
171
- log(`✔ 模拟器在线: ${JSON.stringify(sim).slice(0, 140)}`)
172
- await applyPreset('cast-film-physics')
173
- ctx.simDevices = await simNodes()
174
- log(`✔ cast-film 预设应用,设备 ${ctx.simDevices.length} 台: ${ctx.simDevices.map(d => `${d.id}(${d.protocol})`).join(', ')}`)
175
- })
176
-
177
- /* ════════ S1 · admin 注册 + 产线 provisioning ════════ */
178
- await stage('S1', 'admin 注册 + 产线 provisioning(6 DCW + 5 DAQ + 6 SP 回读)', async () => {
179
- const reg = await api('POST', '/api/workshop/users/register', { name: `optloop-${RUN_ID}` })
180
- ctx.token = reg.json?.data?.token
181
- const who = dataOf(reg)?.user ?? reg.json?.data
182
- if (!ctx.token) throw new Error(`注册失败: ${JSON.stringify(reg.json).slice(0, 200)}`)
183
- log(`✔ token 就绪(user=${who?.name ?? who?.email ?? '?'} role=${who?.role ?? '?'};home 模式首注册即 admin)`)
184
-
185
- const { provisionTwinLine, startTwinBatch } = await import('../bench/lib/closedloop.mjs')
186
- const { simExport } = await import('../bench/lib/sim.mjs')
187
- const call = async (m, p, b) => {
188
- const r = await api(m, p, b, ctx.token)
189
- return { status: r.status, ...(r.json ?? {}) }
190
- }
191
- const sfx = RUN_ID.slice(5, 16).replace(/-/g, '')
192
- ctx.sfx = sfx
193
- const twin = await provisionTwinLine({ call }, { simDevices: ctx.simDevices, sfx })
194
- for (const e of twin.ev) log(' ' + e)
195
- if (!twin.ok) throw new Error(`provision 失败: ${(twin.errors ?? []).join('; ')}`)
196
- ctx.lineId = twin.lineId
197
- ctx.productId = twin.productId
198
- ctx.dcw = twin.dcw
199
- ctx.daq = twin.daq
200
- log(`✔ lineId=${ctx.lineId} productId=${ctx.productId}`)
201
- log(` DCW: ${JSON.stringify(ctx.dcw)}`)
202
- log(` DAQ: ${JSON.stringify(ctx.daq)}`)
203
-
204
- // 控制器显式启动(采样节拍入口)
205
- const ctl = await api('POST', '/api/workshop/daq/controller', { action: 'start' }, ctx.token)
206
- log(`✔ daq controller start → HTTP ${ctl.status}`)
207
-
208
- // 膜厚语义补『厚度』(scene compile 的 target 词表推断依据)
209
- await api('PATCH', `/api/workshop/daq/${ctx.daq['film-thickness']}`, { semantics: '流延膜厚度测量(优化目标 goal,单位 μm;厚度质量输出)' }, ctx.token)
210
-
211
- // SP 设定点回读 DAQ 节点:AML 数据集的 control 输入取自数采时序库,执行器设定点必须有回读节点
212
- ctx.spReadback = {}
213
- for (const dev of ctx.simDevices) {
214
- const exp = await simExport(dev.id)
215
- const items = exp?.items ?? []
216
- for (const spId of Object.keys(ctx.dcw)) {
217
- if (ctx.spReadback[spId]) continue
218
- const sig = (dev.signals ?? []).find(s => s.id === spId)
219
- if (!sig) continue
220
- const item = items.find(i => i.signal === sig.name)
221
- if (!item?.driverConfig) continue
222
- const cfg = { ...item.driverConfig }
223
- if (cfg.jsonKey !== undefined && cfg.jsonPath === undefined) {
224
- cfg.jsonPath = cfg.jsonKey
225
- delete cfg.jsonKey
226
- }
227
- const r = await api('POST', '/api/workshop/daq', {
228
- name: `${sig.name} 回读 ${sfx}`, templateRef: 'daq-temp-tc', driver: dev.protocol, driverConfig: cfg,
229
- unit: sig.unit, min: sig.min, max: sig.max, lineId: ctx.lineId, intervalMs: 1000, publishIntervalMs: 0,
230
- semantics: `执行器设定点回读(AML control 输入) ${item.signal}`,
231
- }, ctx.token)
232
- if (dataOf(r)?.node?.id) ctx.spReadback[spId] = dataOf(r).node.id
233
- }
234
- }
235
- log(`✔ SP 回读 DAQ 节点 ${Object.keys(ctx.spReadback).length}/6: ${JSON.stringify(ctx.spReadback)}`)
236
-
237
- const batch = await startTwinBatch({ call }, { lineId: ctx.lineId, productId: ctx.productId, dcw: ctx.dcw, sfx })
238
- if (!batch.ok) throw new Error(`开跑失败: ${batch.errors?.join('; ')}`)
239
- ctx.recipeId = batch.recipeId
240
- log(`✔ 配方开跑 recipeId=${ctx.recipeId}`)
241
- })
242
-
243
- /* ════════ S2 · 优化通道 B(exploration)+ worker 绑定 + 门控负向校验 ════════ */
244
- await stage('S2', '工艺优化通道 B 实例化(exploration)+ worker 绑定 + 探索期门控负向校验', async () => {
245
- const scene = { sceneId: `castfilm-hold-opt-${ctx.sfx}`, sceneVersion: '1.0.0', lineId: ctx.lineId, productId: ctx.productId, recipeId: ctx.recipeId }
246
- const inst = await api('POST', '/api/workshop/channel-templates/chtpl-aml-optimization-default/instantiate', {
247
- name: `双模式闭环优化 ${RUN_ID}`,
248
- toolProfile: 'aml_optimization',
249
- scene,
250
- objective: { objectiveId: 'thickness-50um', targets: { film_thickness: 50 }, weights: { film_thickness: 1 } },
251
- controlPolicy: 'recommendation_only',
252
- optimizationMode: 'exploration',
253
- }, ctx.token)
254
- const d = dataOf(inst)
255
- ctx.channelB = d?.channelId
256
- const worker = (d?.agents ?? []).find(a => a.role === 'worker' && a.name === '优化执行器') ?? (d?.agents ?? []).find(a => a.role === 'worker')
257
- ctx.workerB = worker?.id
258
- if (!ctx.channelB || !ctx.workerB) throw new Error(`优化通道实例化失败: ${JSON.stringify(inst.json).slice(0, 300)}`)
259
- log(`✔ 优化通道 B=${ctx.channelB} worker(优化执行器)=${ctx.workerB}`)
260
-
261
- for (const nodeId of Object.values(ctx.dcw)) await api('POST', '/api/workshop/agent-tools/bindings', { agentId: ctx.workerB, nodeId, kind: 'dcw', mode: 'auto' }, ctx.token)
262
- for (const nodeId of Object.values(ctx.daq)) await api('POST', '/api/workshop/agent-tools/bindings', { agentId: ctx.workerB, nodeId, kind: 'daq', mode: 'auto' }, ctx.token)
263
- log(`✔ workerB 绑定 ${Object.keys(ctx.dcw).length} DCW + ${Object.keys(ctx.daq).length} DAQ(auto 模式)`)
264
-
265
- // 注入面校验:工具清单应含 optimization_explore;探索模式下孪生工具被 dispatch 拒绝
266
- const list = await api('GET', `/api/workshop/agent-tools/list?agentId=${ctx.workerB}`, undefined, ctx.token)
267
- const names = (dataOf(list)?.tools ?? dataOf(list) ?? []).map(t => t.name ?? t)
268
- const hasExplore = names.includes('optimization_explore')
269
- const hasDcwDirect = names.includes('dcw_control')
270
- log(`✔ 工具面: optimization_explore=${hasExplore ? '√' : '✘'} dcw 直写(应为 false)=${hasDcwDirect ? '✘ 泄漏' : '√ 已收敛到探索治理链'}`)
271
- if (!hasExplore) throw new Error('优化通道工具面缺 optimization_explore')
272
-
273
- const neg = await invoke('twin_trial_run', { snapshot_id: 'fake-snap' }, ctx.workerB, ctx.token)
274
- const blocked = neg.isError && (neg.text.includes('探索') || neg.text.includes('EXPLORATION_MODE_NO_MODEL'))
275
- log(`✔ 负向校验: 探索模式 twin_trial_run 被拒 = ${blocked ? '√(EXPLORATION_MODE_NO_MODEL)' : `✘ ${neg.text.slice(0, 120)}`}`)
276
- if (!blocked) throw new Error('探索模式下孪生工具未被拒绝 —— 门控失效')
277
- })
278
-
279
- /* ════════ S3 · 第一轮:探索式闭环(批次1 内,optimization_explore 贪心多通道) ════════ */
280
- await stage('S3', '第一轮·探索式闭环(optimization_explore 真实写入,贪心多通道收敛膜厚 50μm)', async () => {
281
- const film = ctx.daq['film-thickness']
282
- const TARGET = 50
283
- // 单步限制 = 参数基准限界层的 2% 量程(screw 3rpm / linespeed 2 / diegap 0.03,实测 6rpm 被拒 400)
284
- const CH = {
285
- screw: { node: ctx.dcw['screw-sp'], limit: 3, gain: 0.144, value: 150, unit: 'rpm' },
286
- linespeed: { node: ctx.dcw['linespeed-sp'], limit: 2, gain: -0.568, value: 95, unit: 'm/min' },
287
- diegap: { node: ctx.dcw['diegap-sp'], limit: 0.03, gain: 54, value: 1.0, unit: 'mm' },
288
- }
289
- let h = await thicknessMean(ctx.token, film, 20)
290
- log(` 探索起点: 膜厚≈${h?.toFixed(2) ?? '?'}μm(screw=150, v=95, diegap=1.0;目标 ${TARGET}μm)`)
291
- const traj = [{ step: 0, h }]
292
- // 首个写入前等过 60s 治理间隔(全新跑时 S1 配方下发刚写完各节点)
293
- await sleep(45_000)
294
-
295
- // 贪心策略:每步选「预计移动量 = |增益×限步| 最大」的通道,按残差在线修正增益;
296
- // 同通道两次写入 ≥60s(在线探索硬卡控)→ 相邻步强制换通道 + 步间 25s。
297
- let lastKey = ''
298
- let lastH = h
299
- for (let i = 1; i <= 9; i++) {
300
- if (h != null && Math.abs(h - TARGET) <= 1.2) {
301
- log(` ✔ 第 ${i - 1} 步已入带: 膜厚 ${h.toFixed(2)}μm ∈ [${TARGET - 2},${TARGET + 2}],提前收敛`)
302
- break
303
- }
304
- await sleep(25_000)
305
- const err = TARGET - (h ?? TARGET)
306
- const candidates = Object.entries(CH)
307
- .filter(([k, c]) => k !== lastKey && Math.abs(c.gain) * c.limit > 0.05)
308
- .map(([k, c]) => ({ k, c, move: Math.abs(c.gain) * c.limit, dir: Math.sign(err) * Math.sign(c.gain) >= 0 ? 'up' : 'down' }))
309
- if (!candidates.length) break
310
- candidates.sort((a, b) => b.move - a.move)
311
- const pick = candidates[0]
312
- const c = pick.c
313
- const before = c.value
314
- const r = await invoke('optimization_explore', {
315
- control_node_id: c.node, target_node_id: film,
316
- direction: pick.dir, step: c.limit, settle_seconds: 15,
317
- hypothesis: `贪心探索(${pick.k}): h=${h?.toFixed(2)}μm → 目标 ${TARGET}μm,预计 ${pick.dir === 'up' ? '+' : '-'}${(Math.abs(c.gain) * c.limit).toFixed(2)}μm(增益 ${c.gain.toFixed(3)}μm/${c.unit}×限步${c.limit})`,
318
- }, ctx.workerB, ctx.token)
319
- if (r.isError) {
320
- log(` ⚠ [${pick.k}#${i}] 被拒: ${r.text.split('\n').slice(0, 2).join(' ').slice(0, 150)}`)
321
- CH[pick.k].gain *= 0.3 // 降权避免反复撞墙
322
- continue
323
- }
324
- c.value = Math.round((before + (pick.dir === 'up' ? c.limit : -c.limit)) * 1000) / 1000
325
- lastKey = pick.k
326
- const hNow = await thicknessMean(ctx.token, film, 12)
327
- // 残差归因:实际响应与预计之差修正该通道增益(在线辨识)
328
- if (hNow != null && lastH != null) {
329
- const predicted = Math.abs(c.gain) * c.limit * (pick.dir === 'up' ? Math.sign(c.gain) : -Math.sign(c.gain))
330
- const observed = hNow - (h ?? hNow)
331
- if (Number.isFinite(observed)) c.gain = c.gain * 0.5 + (observed / (pick.dir === 'up' ? c.limit : -c.limit)) * 0.5
332
- log(` [${pick.k}#${i}] ${pick.dir} ${c.limit} → ${pick.k}=${c.value} · h ${h?.toFixed(2)}→${hNow.toFixed(2)}μm(预计 ${predicted.toFixed(2)},实批 ${observed.toFixed(2)})`)
333
- }
334
- else log(` [${pick.k}#${i}] ${pick.dir} ${c.limit} → ${pick.k}=${c.value} · 读数 n/a`)
335
- h = hNow
336
- lastH = h
337
- traj.push({ step: i, channel: pick.k, dir: pick.dir, value: c.value, h })
338
- }
339
-
340
- const hEnd = await thicknessMean(ctx.token, film, 30)
341
- const inBand = hEnd != null && Math.abs(hEnd - TARGET) <= 2
342
- ctx.exploration = {
343
- traj, hStart: traj[0]?.h ?? null, hEnd, inBand,
344
- screwEnd: CH.screw.value, linespeedEnd: CH.linespeed.value, diegapEnd: CH.diegap.value,
345
- }
346
- log(`${inBand ? '✔' : '▲'} 探索收敛: ${traj[0]?.h?.toFixed(2)} → ${hEnd?.toFixed(2)}μm(目标带 [48,52];screw=${CH.screw.value} v=${CH.linespeed.value} diegap=${CH.diegap.value})`)
347
-
348
- // 调控闭环判定收口:最近一条 open 优化记录落 keep(收敛)——真实 ledger 闭环
349
- const opts = await api('GET', `/api/workshop/dcw/optimizations?lineId=${ctx.lineId}&limit=10`, undefined, ctx.token)
350
- const openRec = (dataOf(opts)?.records ?? []).find(x => x.status === 'open')
351
- if (openRec && inBand) {
352
- const j = await invoke('dcw_judge', { record_id: openRec.id, verdict: 'keep', reason: `探索收敛: 膜厚 ${hEnd.toFixed(2)}μm 入带 [48,52]` }, ctx.workerB, ctx.token)
353
- log(` dcw_judge keep(${openRec.nodeId.slice(-6)}) → ${j.isError ? j.text.slice(0, 120) : '已入册'}`)
354
- }
355
-
356
- // 批次1 保持至 ~450s(与批次2/3 同量级,保证样本量)
357
- await sleep(150_000)
358
- await api('POST', `/api/workshop/dcw/lines/${ctx.lineId}/stop`, {}, ctx.token)
359
- log(' 批次1 停止(探索期数据已全部落 TSDB)')
360
- })
361
-
362
- /* ════════ S4 · 激励采样(批次2-3,阶跃辨识) ════════ */
363
- await stage('S4', '激励采样:批次2-3 阶跃(线速/模口间隙;manual 写入,同受治理限频与 2% 单步限)', async () => {
364
- const BASE_SP = { 'linespeed-sp': 95, 'diegap-sp': 1.0 }
365
- // 阶跃幅度受参数单步限制(2% 量程:v ±2, diegap ±0.03,按**当前值**起算),越限写入会被 400 拒绝
366
- const EXCITE_RUNS = [
367
- [{ dls: 2.0, ddg: 0.03 }, { dls: -2.0, ddg: -0.03 }],
368
- [{ dls: -2.0, ddg: 0.03 }, { dls: 1.5, ddg: -0.03 }],
369
- ]
370
- const writeOrThrow = async (nodeId, value, tag) => {
371
- const w = await api('POST', `/api/workshop/dcw/${nodeId}/write`, { value }, ctx.token)
372
- if (w.status >= 400) throw new Error(`激励写入被拒(${tag} ← ${value}): ${JSON.stringify(w.json?.message ?? w.json).slice(0, 160)}`)
373
- log(` ${tag} ← ${value} √`)
374
- }
375
- // 续跑安全:上一进程可能留下在跑批次,先停(未跑时忽略 409)
376
- await api('POST', `/api/workshop/dcw/lines/${ctx.lineId}/stop`, {}, ctx.token).catch(() => {})
377
- await sleep(3000)
378
- for (let run = 0; run < 2; run++) {
379
- // stop→start 竞态防护:stop 后等 8s;start 失败重试一次(409 常为状态机未落定)
380
- await api('POST', `/api/workshop/dcw/lines/${ctx.lineId}/stop`, {}, ctx.token).catch(() => {})
381
- await sleep(8000)
382
- let st = await api('POST', `/api/workshop/dcw/lines/${ctx.lineId}/start`, { recipeId: ctx.recipeId }, ctx.token)
383
- if (st.status !== 200) {
384
- log(` 批次 ${run + 2} 首次开跑 HTTP ${st.status}: ${JSON.stringify(st.json?.message ?? st.json).slice(0, 120)} → 8s 后重试`)
385
- await sleep(8000)
386
- st = await api('POST', `/api/workshop/dcw/lines/${ctx.lineId}/start`, { recipeId: ctx.recipeId }, ctx.token)
387
- }
388
- if (st.status !== 200) throw new Error(`批次 ${run + 2} 开跑失败: ${JSON.stringify(st.json).slice(0, 200)}`)
389
- log(` 批次 ${run + 2} 开跑(同配方 ${ctx.recipeId})`)
390
- await sleep(65_000)
391
- const [e1, e2] = EXCITE_RUNS[run]
392
- let curLs = BASE_SP['linespeed-sp']
393
- let curDg = BASE_SP['diegap-sp']
394
- curLs = Math.round((curLs + e1.dls) * 1000) / 1000
395
- await writeOrThrow(ctx.dcw['linespeed-sp'], curLs, `批次${run + 2} linespeed 阶跃1`)
396
- curDg = Math.round((curDg + e1.ddg) * 1000) / 1000
397
- await writeOrThrow(ctx.dcw['diegap-sp'], curDg, `批次${run + 2} diegap 阶跃1`)
398
- await sleep(150_000)
399
- curLs = Math.round((curLs + e2.dls) * 1000) / 1000
400
- await writeOrThrow(ctx.dcw['linespeed-sp'], curLs, `批次${run + 2} linespeed 阶跃2`)
401
- curDg = Math.round((curDg + e2.ddg) * 1000) / 1000
402
- await writeOrThrow(ctx.dcw['diegap-sp'], curDg, `批次${run + 2} diegap 阶跃2`)
403
- await sleep(290_000)
404
- const latest = await thicknessMean(ctx.token, ctx.daq['film-thickness'], 10)
405
- log(` 批次${run + 2} 完成(500s) · 膜厚当前≈${latest?.toFixed(2) ?? '?'} μm`)
406
- }
407
- await api('POST', `/api/workshop/dcw/lines/${ctx.lineId}/stop`, {}, ctx.token)
408
- log('✔ 采样完成(批次1 探索 + 批次2/3 各 500s),产线停止')
409
- })
410
-
411
- /* ════════ S4B · 补充扫描激励(扩大目标方差,提升可辨识性) ════════ */
412
- await stage('S4B', '补充激励:模口间隙/线速宽扫描(2 批次;扩大 y 方差 → NRMSE 分母)', async () => {
413
- const writeOrThrow = async (nodeId, value, tag) => {
414
- const w = await api('POST', `/api/workshop/dcw/${nodeId}/write`, { value }, ctx.token)
415
- if (w.status >= 400) throw new Error(`扫描写入被拒(${tag} ← ${value}): ${JSON.stringify(w.json?.message ?? w.json).slice(0, 160)}`)
416
- log(` ${tag} ← ${value} √`)
417
- }
418
- // 单步 ≤2% 限(dg ±0.03 / v ±2),按当前值起算;步间 80s(>60s 治理间隔)
419
- const SWEEPS = [
420
- { dg: [1.0, 0.97, 0.94, 0.97, 1.0], ls: null },
421
- { dg: [1.0, 1.03, 1.06, 1.03, 1.0], ls: [95, 97, 99, 97, 95] },
422
- ]
423
- for (let run = 0; run < SWEEPS.length; run++) {
424
- const sw = SWEEPS[run]
425
- // stop→start 竞态防护(同 S4):循环头先停+等 8s,start 失败重试一次
426
- await api('POST', `/api/workshop/dcw/lines/${ctx.lineId}/stop`, {}, ctx.token).catch(() => {})
427
- await sleep(8000)
428
- let st = await api('POST', `/api/workshop/dcw/lines/${ctx.lineId}/start`, { recipeId: ctx.recipeId }, ctx.token)
429
- if (st.status !== 200) {
430
- log(` 扫描批次 ${run + 1} 首次开跑 HTTP ${st.status} → 8s 后重试`)
431
- await sleep(8000)
432
- st = await api('POST', `/api/workshop/dcw/lines/${ctx.lineId}/start`, { recipeId: ctx.recipeId }, ctx.token)
433
- }
434
- if (st.status !== 200) throw new Error(`扫描批次 ${run + 1} 开跑失败: ${JSON.stringify(st.json).slice(0, 200)}`)
435
- log(` 扫描批次 ${run + 1} 开跑`)
436
- await sleep(65_000)
437
- for (let i = 1; i < sw.dg.length; i++) {
438
- await writeOrThrow(ctx.dcw['diegap-sp'], sw.dg[i], `扫描${run + 1} diegap#${i}`)
439
- if (sw.ls) await writeOrThrow(ctx.dcw['linespeed-sp'], sw.ls[i], `扫描${run + 1} linespeed#${i}`)
440
- await sleep(80_000)
441
- }
442
- await sleep(60_000)
443
- const latest = await thicknessMean(ctx.token, ctx.daq['film-thickness'], 10)
444
- log(` 扫描批次 ${run + 1} 完成 · 膜厚当前≈${latest?.toFixed(2) ?? '?'} μm`)
445
- }
446
- await api('POST', `/api/workshop/dcw/lines/${ctx.lineId}/stop`, {}, ctx.token)
447
- log('✔ 扫描激励完成(dg 0.94~1.06 / v 95~99 全覆盖)')
448
- })
449
-
450
- /* ════════ S5 · 训练通道 A:实例化 + 场景冻结 + PhysicsSpec ════════ */
451
- await stage('S5', '训练通道 A 实例化 + worker 绑定 + 场景发现/编译/冻结 + 骨架 PhysicsSpec', async () => {
452
- const scene = { sceneId: `castfilm-hold-opt-${ctx.sfx}`, sceneVersion: '1.0.0', lineId: ctx.lineId, productId: ctx.productId, recipeId: ctx.recipeId }
453
- const inst = await api('POST', '/api/workshop/channel-templates/chtpl-hybrid-twin-mpc-default/instantiate', {
454
- name: `孪生训练 ${RUN_ID}`,
455
- toolProfile: 'hybrid_twin',
456
- scene,
457
- objective: { objectiveId: 'thickness-50um', targets: { film_thickness: 50 } },
458
- controlPolicy: 'recommendation_only',
459
- }, ctx.token)
460
- const d = dataOf(inst)
461
- ctx.channelA = d?.channelId
462
- const worker = (d?.agents ?? []).find(a => a.role === 'worker')
463
- ctx.workerA = worker?.id
464
- if (!ctx.channelA || !ctx.workerA) throw new Error(`训练通道实例化失败: ${JSON.stringify(inst.json).slice(0, 300)}`)
465
- log(`✔ 训练通道 A=${ctx.channelA} worker=${ctx.workerA}`)
466
- for (const nodeId of Object.values(ctx.dcw)) await api('POST', '/api/workshop/agent-tools/bindings', { agentId: ctx.workerA, nodeId, kind: 'dcw', mode: 'auto' }, ctx.token)
467
- for (const nodeId of Object.values(ctx.daq)) await api('POST', '/api/workshop/agent-tools/bindings', { agentId: ctx.workerA, nodeId, kind: 'daq', mode: 'auto' }, ctx.token)
468
- log(`✔ workerA 绑定 ${Object.keys(ctx.dcw).length} DCW + ${Object.keys(ctx.daq).length} DAQ`)
469
-
470
- const SCENE_ID = scene.sceneId
471
- ctx.sceneId = SCENE_ID
472
- const disco = await invoke('twin_scene_discover', {}, ctx.workerA, ctx.token)
473
- const targetOk = disco.text.includes('"target": 1') || disco.text.includes('"target":1')
474
- log(` 场景发现: target=1 ${targetOk ? '√' : '✘(检查膜厚语义)'}`)
475
- const compiled = await invoke('twin_scene_compile', {
476
- scene_id: SCENE_ID, scene_version: '1.0.0', line_id: ctx.lineId, product_id: ctx.productId, recipe_id: ctx.recipeId,
477
- prompt: '流延膜厚度闭环优化:目标膜厚 50μm。控制=6 个执行器设定点,观测=膜厚(目标)/熔温/熔压。约束:熔温 195~225℃,熔压 ≤22MPa。膜厚为目标输出。',
478
- }, ctx.workerA, ctx.token)
479
- if (compiled.isError) throw new Error(`场景编译失败: ${compiled.text.slice(0, 200)}`)
480
- const frozen = await invoke('twin_scene_freeze', {
481
- scene_id: SCENE_ID, scene_version: '1.0.0', confirmation: 'USER_CONFIRMED_SCENE_CONTRACT', approved_by: 'live-admin',
482
- }, ctx.workerA, ctx.token)
483
- if (frozen.isError) throw new Error(`场景冻结失败: ${frozen.text.slice(0, 200)}`)
484
- log(`✔ 场景已冻结 ${SCENE_ID}@1.0.0(用户确认令牌)`)
485
-
486
- const draft = await invoke('twin_physics_spec_draft', { dt_sec: 1 }, ctx.workerA, ctx.token)
487
- if (draft.isError) throw new Error(`骨架生成失败: ${draft.text.slice(0, 200)}`)
488
- const draftArtifactPath = (draft.text.match(/artifact:\s*([^\n]+)/) || [])[1]?.trim()
489
- if (!draftArtifactPath || !existsSync(draftArtifactPath)) throw new Error(`骨架 spec 工件缺失: ${draftArtifactPath}`)
490
- const physicsSpec = JSON.parse(readFileSync(draftArtifactPath, 'utf8'))
491
- log(`✔ 骨架 PhysicsSpec: model=${physicsSpec.modelId} 状态 ${physicsSpec.states.length} 观测 ${physicsSpec.observations.length}`)
492
-
493
- // 训练前对齐在 S6 数据集构建后做(spec 变量改绑回读节点 + 剔除数据集外变量)
494
- const dwToDn = {}
495
- for (const [sig, dn] of Object.entries(ctx.spReadback)) dwToDn[ctx.dcw[sig]] = dn
496
- ctx.physicsSpec = physicsSpec
497
- ctx.dwToDn = dwToDn
498
- writeFileSync(join(OUT_DIR, 'physics-spec-draft.json'), JSON.stringify(physicsSpec, null, 2))
499
- })
500
-
501
- /* ════════ S6 · 数据集构建 + hybrid_residual 训练 ════════ */
502
- await stage('S6', 'AML 数据集构建 + hybrid_residual 训练(平台参考训练器)', async () => {
503
- const sampledControls = []
504
- for (const [sig, nodeId] of Object.entries(ctx.spReadback)) {
505
- const r = await api('GET', `/api/workshop/daq/${nodeId}/samples?bucketMs=60000&limit=1`, undefined, ctx.token)
506
- const has = (dataOf(r)?.points ?? []).length > 0
507
- log(` 回读采样检查 ${sig}: ${has ? '√' : '✘ 剔除'}`)
508
- if (has) sampledControls.push({ nodeId, role: 'control' })
509
- }
510
- if (sampledControls.length < 4) throw new Error(`可用 control 回读不足: ${sampledControls.length}`)
511
- const dsBody = {
512
- lineId: ctx.lineId, productId: ctx.productId, recipeId: ctx.recipeId,
513
- nodes: [
514
- ...sampledControls,
515
- { nodeId: ctx.daq['film-thickness'], role: 'target' },
516
- { nodeId: ctx.daq['melt-temp'], role: 'feature' },
517
- { nodeId: ctx.daq['melt-pressure'], role: 'feature' },
518
- ],
519
- beatMs: 1000, window: { historySteps: 8, horizonSteps: 4 },
520
- split: { valRatio: 0.34, testRatio: 0.33, seed: Number(process.env.OPTLOOP_SPLIT_SEED ?? 11) },
521
- purpose: 'mpc_surrogate',
522
- note: `双模式闭环数据集(探索+激励) ${RUN_ID}`,
523
- }
524
- const ds = await api('POST', '/api/workshop/aml/datasets', dsBody, ctx.token)
525
- const dataset = dataOf(ds)?.dataset
526
- if (!dataset) throw new Error(`数据集构建失败: ${JSON.stringify(ds.json).slice(0, 300)}`)
527
- ctx.datasetId = dataset.id
528
- log(`✔ 数据集 ${dataset.id}: ${dataset.rowCount} 窗 / ${dataset.runIds.length} 批`)
529
-
530
- // 训练前对齐(spec 变量改绑回读节点 + 剔除数据集外变量)
531
- const manifest = JSON.parse(readFileSync(join(AML_ROOT, 'datasets', dataset.id, 'manifest.json'), 'utf8'))
532
- const datasetNodes = new Set(manifest.allNodes)
533
- const physicsSpec = ctx.physicsSpec
534
- let remapped = 0
535
- for (const v of physicsSpec.variables) {
536
- if (v.nodeId && !datasetNodes.has(v.nodeId) && ctx.dwToDn[v.nodeId]) {
537
- v.nodeId = ctx.dwToDn[v.nodeId]
538
- remapped++
539
- }
540
- }
541
- const keptVars = physicsSpec.variables.filter(v => !v.nodeId || datasetNodes.has(v.nodeId))
542
- const keptIds = new Set(keptVars.map(v => v.id))
543
- physicsSpec.variables = keptVars
544
- physicsSpec.states = physicsSpec.states.filter((e) => {
545
- const base = e.lhs.endsWith('_next') ? e.lhs.slice(0, -5) : e.lhs
546
- return keptIds.has(base)
547
- })
548
- physicsSpec.observations = physicsSpec.observations.filter(e => keptIds.has(e.lhs))
549
- physicsSpec.guards = (physicsSpec.guards ?? []).filter(e => keptIds.has(e.lhs))
550
- physicsSpec.constraints = physicsSpec.constraints.filter(c => keptIds.has(c.id))
551
- writeFileSync(join(OUT_DIR, 'physics-spec-remapped.json'), JSON.stringify(physicsSpec, null, 2))
552
- log(`✔ 训练对齐: 控制改绑 ${remapped};保留变量 ${keptVars.length}`)
553
-
554
- const jobRes = await api('POST', '/api/workshop/aml/jobs', {
555
- datasetId: dataset.id,
556
- purpose: 'mpc_surrogate',
557
- changeNote: '双模式闭环:骨架物理+数据残差(全部 DCW → 膜厚 goal)',
558
- params: { epochs: Number(process.env.OPTLOOP_EPOCHS ?? 600), hidden: Number(process.env.OPTLOOP_HIDDEN ?? 128), lr: 0.0015, residual_scale: Number(process.env.OPTLOOP_RESIDUAL ?? 2.0), ensemble: 3 },
559
- seed: Number(process.env.OPTLOOP_SEED ?? 11),
560
- jobKind: 'hybrid_residual',
561
- sceneId: ctx.sceneId,
562
- sceneVersion: '1.0.0',
563
- objectiveId: 'thickness-50um',
564
- physicsSpec,
565
- providerId: physicsSpec.modelId,
566
- providerVersion: '1.0.0',
567
- providerHash: `sha256:${JSON.stringify(physicsSpec).length}`,
568
- modelName: `流延膜厚双模式闭环模型 ${ctx.sfx}`,
569
- modelDescription: `输入=全部 6 个 DCW 执行器(SP 回读);输出=膜厚 goal(50μm);场景 ${ctx.sceneId}@1.0.0;产线 ${ctx.lineId}/配方 ${ctx.recipeId};数据含探索式闭环真实写入`,
570
- }, ctx.token)
571
- const job = dataOf(jobRes)?.job
572
- if (!job) throw new Error(`作业提交失败: ${JSON.stringify(jobRes.json).slice(0, 300)}`)
573
- ctx.jobId = job.id
574
- log(`✔ 训练作业 ${job.id} 入队(hybrid_residual)`)
575
-
576
- let jobDone = null
577
- for (let i = 0; i < 210; i++) {
578
- await sleep(10_000)
579
- const st = await api('GET', `/api/workshop/aml/jobs/${job.id}`, undefined, ctx.token)
580
- const j = dataOf(st)?.job ?? dataOf(st)
581
- if (!j) continue
582
- log(` [${i * 10}s] ${j.status} ${j.stage} ${j.progress}%`)
583
- if (['done', 'failed', 'cancelled', 'timeout'].includes(j.status)) {
584
- jobDone = j
585
- break
586
- }
587
- }
588
- if (!jobDone || jobDone.status !== 'done') throw new Error(`训练未成功: ${JSON.stringify(jobDone).slice(0, 300)}`)
589
- const gates = (() => {
590
- try {
591
- return JSON.parse(jobDone.gatesJson || '{}')
592
- }
593
- catch {
594
- return {}
595
- }
596
- })()
597
- ctx.platformGates = gates
598
- log(`✔ 训练完成 · 平台门禁: ${gates.passed === true ? '全部通过' : `未过(${JSON.stringify(gates).slice(0, 160)})`}`)
599
- })
600
-
601
- /* ════════ S7 · 模型校验 + 晋升 shadow ════════ */
602
- await stage('S7', '模型注册校验 + 晋升 shadow', async () => {
603
- const modelsRes = await api('GET', '/api/workshop/aml/models', undefined, ctx.token)
604
- const model = (dataOf(modelsRes)?.models ?? []).find(m => m.datasetId === ctx.datasetId)
605
- if (!model) throw new Error('模型未登记')
606
- ctx.modelId = model.id
607
- const m = model.metrics ?? {}
608
- log(`✔ 模型 ${model.id} [${model.stage}] label=${model.label}`)
609
- log(` G1 单步 NRMSE=${m.oneStepTest?.nrmse} · G2 滚动=${m.rolloutTest?.nrmse}`)
610
- log(` hybrid=${JSON.stringify(m.hybrid ?? {}).slice(0, 200)}`)
611
- log(` uncertainty=${JSON.stringify(m.uncertainty ?? {}).slice(0, 200)}`)
612
- const promo = await api('POST', `/api/workshop/aml/models/${model.id}/promote`, { toStage: 'shadow' }, ctx.token)
613
- log(`✔ 晋升 shadow → HTTP ${promo.status}`)
614
- if (promo.status >= 400) throw new Error(`晋升失败: ${JSON.stringify(promo.json).slice(0, 200)}`)
615
- })
616
-
617
- /* ════════ S8 · 候选试验(必传 model_id)→ Twin Gate ════════ */
618
- await stage('S8', '候选试验 ×10(模型驱动 rollout)+ twin_gate_evaluate', async () => {
619
- await ensureDaqRunning()
620
- await api('POST', `/api/workshop/dcw/lines/${ctx.lineId}/start`, { recipeId: ctx.recipeId }, ctx.token)
621
- log(' 产线重启(真实工况采快照)')
622
- await sleep(25_000)
623
-
624
- const snap = await invoke('twin_snapshot_create', { auto_daq: true, channel_id: ctx.channelA, phase: 'exploration' }, ctx.workerA, ctx.token)
625
- if (snap.isError) throw new Error(`快照失败: ${snap.text.slice(0, 240)}`)
626
- ctx.snapshotA = (snap.text.match(/snapshot_id:\s*([^\n]+)/) || [])[1]?.trim()
627
- log(`✔ 快照 ${ctx.snapshotA}`)
628
-
629
- const frozenPath = join(AML_ROOT, 'twins', 'scenes', `${ctx.sceneId}-1.0.0-frozen`, 'scenes.json')
630
- const frozenArtifact = JSON.parse(readFileSync(frozenPath, 'utf8'))
631
- const frozenScene = frozenArtifact.scene ?? frozenArtifact
632
- ctx.sceneControls = frozenScene.controls ?? []
633
- const speedCtl = ctx.sceneControls.find(c => (c.nodeId ?? '').includes('linespeed')) ?? ctx.sceneControls[0]
634
- const speedStep = speedCtl?.maxStep ?? 2
635
- let uqAllPass = true
636
- for (let k = 0; k < 10; k++) {
637
- const delta = (k % 2 === 0 ? 1 : -0.5) * speedStep * (0.3 + 0.07 * k)
638
- const cand = 95 + delta
639
- const t = await invoke('twin_trial_run', {
640
- snapshot_id: ctx.snapshotA,
641
- model_id: ctx.modelId,
642
- baseline_controls: { [speedCtl.id]: 95 },
643
- candidate_controls: [
644
- { [speedCtl.id]: cand }, { [speedCtl.id]: cand }, { [speedCtl.id]: cand }, { [speedCtl.id]: cand },
645
- ],
646
- }, ctx.workerA, ctx.token)
647
- const uqOk = t.text.includes('ood=accepted')
648
- if (!uqOk) uqAllPass = false
649
- log(` trial#${k + 1} Δ=${delta.toFixed(2)} uq/ood=${uqOk ? '√' : '✘'} ${t.text.split('\n').find(x => x.includes('improvement'))?.trim().slice(0, 80) ?? ''}`)
650
- }
651
- if (!uqAllPass) log(' ⚠ 存在 UQ/OOD 未通过的候选(会影响 G7)')
652
-
653
- const gate = await invoke('twin_gate_evaluate', { model_id: ctx.modelId, scene_id: ctx.sceneId }, ctx.workerA, ctx.token)
654
- writeFileSync(join(OUT_DIR, 'twin-gate.txt'), gate.text)
655
- // 顶层 passed 解析:不能 text.includes('"passed": true') —— checks[] 每个子项也有
656
- // passed 字段,任意子项为 true 都会误判整门通过(实测 G7 false 仍被放行)。
657
- const gateTop = gate.text.match(/^\{[\s\S]*?"passed":\s*(true|false)/)
658
- const gatePassed = gateTop?.[1] === 'true'
659
- ctx.gatePassed = gatePassed
660
- for (const line of gate.text.split('\n').filter(x => x.includes('"id"') || x.includes('"passed"')).slice(0, 32)) log(' ' + line.trim())
661
- log(`${gatePassed ? '✔' : '✘'} Twin Gate(回写 twinEligibility + shadowEvidence)`)
662
- if (!gatePassed) throw new Error('Twin Gate 未全过 —— 绑定会被 fail-closed 拒绝')
663
-
664
- await api('POST', `/api/workshop/dcw/lines/${ctx.lineId}/stop`, {}, ctx.token)
665
- })
666
-
667
- /* ════════ S9 · 绑定模型到优化通道 B(fail-closed) ════════ */
668
- await stage('S9', '绑定模型到优化通道 B(谱系+门禁 fail-closed 校验;自动切 aml 模式)', async () => {
669
- const patch = await api('PATCH', `/api/workshop/channels/${ctx.channelB}/twin-profile`, { boundModelId: ctx.modelId }, ctx.token)
670
- if (patch.status >= 400) throw new Error(`绑定失败: ${JSON.stringify(patch.json).slice(0, 300)}`)
671
- const prof = dataOf(patch)
672
- ctx.profileAfterBind = prof
673
- log(`✔ 绑定 ${ctx.modelId} → profile=${prof?.profile} mode=${prof?.mode}(探索期被拒的孪生工具现已放行)`)
674
-
675
- // 交叉校验:同一工具,aml 模式下不再被拒(快照不存在报错≠门控拒绝)
676
- const probeRun = await invoke('twin_trial_run', { snapshot_id: 'probe-nonexist', model_id: ctx.modelId }, ctx.workerB, ctx.token)
677
- const gateGone = !probeRun.text.includes('EXPLORATION_MODE_NO_MODEL')
678
- log(` aml 模式孪生工具放行 = ${gateGone ? '√' : '✘'}(返回:${probeRun.text.split('\n')[0].slice(0, 100)})`)
679
- if (!gateGone) throw new Error('aml 模式下孪生工具仍被拒')
680
- })
681
-
682
- /* ════════ S10 · 第二轮:模型驱动参数优化(precise_search + 治理投用) ════════ */
683
- await stage('S10', '第二轮·模型式优化:回到探索终点 → mpc_optimize(model_id) → precise_search → 治理投用 → 复测', async () => {
684
- await ensureDaqRunning()
685
- await api('POST', `/api/workshop/dcw/lines/${ctx.lineId}/start`, { recipeId: ctx.recipeId }, ctx.token)
686
- log(' 产线重启(批次4;配方下发回到起始工况)')
687
- // 等 60s 治理写间隔 + 工艺稳定
688
- await sleep(65_000)
689
-
690
- // 回到第一轮探索终点(模型在终点邻域做精确微调 —— 两阶段设计的本意:探索找近,模型收准)。
691
- // 恢复也走治理链:单步 ≤2% 限,多轮逼近(每轮按产线真实当前值算剩余差,通道轮换保 60s 间隔)。
692
- const END = { screw: ctx.exploration?.screwEnd ?? 150, linespeed: ctx.exploration?.linespeedEnd ?? 95, diegap: ctx.exploration?.diegapEnd ?? 1.0 }
693
- const CH2 = {
694
- screw: { node: ctx.dcw['screw-sp'], limit: 3 },
695
- linespeed: { node: ctx.dcw['linespeed-sp'], limit: 2 },
696
- diegap: { node: ctx.dcw['diegap-sp'], limit: 0.03 },
697
- }
698
- const currentVals = async () => {
699
- const d = await api('GET', '/api/workshop/dcw', undefined, ctx.token)
700
- const map = {}
701
- for (const n of (dataOf(d)?.nodes ?? [])) map[n.id] = Number(n.value ?? 0)
702
- return map
703
- }
704
- for (let round = 0; round < 5; round++) {
705
- const vals = await currentVals()
706
- const pending = Object.entries(CH2).filter(([k, c]) => Math.abs(END[k] - (vals[c.node] ?? 0)) > c.limit * 0.3)
707
- if (pending.length === 0) break
708
- let moved = false
709
- for (const [k, c] of pending) {
710
- const cur = vals[c.node] ?? 0
711
- const delta = END[k] - cur
712
- if (moved) await sleep(30_000)
713
- const r = await invoke('optimization_explore', {
714
- control_node_id: c.node, target_node_id: ctx.daq['film-thickness'],
715
- direction: delta >= 0 ? 'up' : 'down', step: Math.min(c.limit, Math.abs(delta)), settle_seconds: 15,
716
- hypothesis: `恢复第一轮探索终点(${k}): ${cur.toFixed(2)}→${END[k]}(模型微调起点)`,
717
- }, ctx.workerB, ctx.token)
718
- log(` 恢复 ${k} ${cur.toFixed(2)}${delta >= 0 ? '+' : '-'}${Math.min(c.limit, Math.abs(delta)).toFixed(2)}: ${r.isError ? '被拒 ' + r.text.split('\n').slice(0, 2).join(' ').slice(0, 110) : '√'}`)
719
- if (!r.isError) moved = true
720
- }
721
- if (!moved) break
722
- await sleep(30_000)
723
- }
724
- await sleep(15_000)
725
-
726
- const snapB = await invoke('twin_snapshot_create', { auto_daq: true, channel_id: ctx.channelB, phase: 'exploration' }, ctx.workerB, ctx.token)
727
- if (snapB.isError) throw new Error(`B 快照失败: ${snapB.text.slice(0, 240)}`)
728
- ctx.snapshotB = (snapB.text.match(/snapshot_id:\s*([^\n]+)/) || [])[1]?.trim()
729
- log(`✔ 优化通道快照 ${ctx.snapshotB}(冻结场景按 sceneId 解析 = 训练通道冻结的同一契约)`)
730
-
731
- // 基线 = 当前真实设定(优化通道节点值)
732
- const dcwRes = await api('GET', '/api/workshop/dcw', undefined, ctx.token)
733
- const nodes = dataOf(dcwRes)?.nodes ?? []
734
- const valOf = nodeId => Number(nodes.find(n => n.id === nodeId)?.value ?? 0)
735
- const baseline = {}
736
- for (const c of ctx.sceneControls) baseline[c.id] = valOf(c.nodeId)
737
- log(` 基线(当前设定): ${JSON.stringify(baseline)}`)
738
- const hBefore = await thicknessMean(ctx.token, ctx.daq['film-thickness'], 30)
739
- log(` 投用前膜厚(30s 均值): ${hBefore?.toFixed(2) ?? '?'}μm`)
740
-
741
- const mpc = await invoke('mpc_optimize', {
742
- snapshot_id: ctx.snapshotB,
743
- model_id: ctx.modelId,
744
- baseline_controls: baseline,
745
- horizon_steps: 4,
746
- }, ctx.workerB, ctx.token)
747
- writeFileSync(join(OUT_DIR, 'mpc-recommendation.txt'), mpc.text)
748
- const mode = (mpc.text.match(/"mode":\s*"([^"]+)"/) || [])[1]
749
- const bestRaw = (mpc.text.match(/"bestCandidate":\s*\{([^}]*)\}/) || [])[1] ?? ''
750
- const best = {}
751
- for (const mm of bestRaw.matchAll(/"([^"]+)":\s*(-?[\d.]+(?:e[+-]?\d+)?)/gi)) best[mm[1]] = Number(mm[2])
752
- ctx.mpc = { mode, best, hBefore }
753
- log(`${mode === 'precise_search' ? '✔' : '▲'} MPC mode=${mode}(modelReady 升档判定)bestCandidate=${JSON.stringify(best)}`)
754
- if (mode !== 'precise_search' || Object.keys(best).length === 0) throw new Error(`MPC 未进入 precise_search 或无推荐: ${mpc.text.slice(0, 240)}`)
755
-
756
- // 推荐投用:经 optimization_explore 治理链(优化通道无 dcw 直写工具面 —— 设计如此)
757
- const idToNode = Object.fromEntries(ctx.sceneControls.map(c => [c.id, c.nodeId]))
758
- ctx.applied = []
759
- for (const [specId, target] of Object.entries(best)) {
760
- const nodeId = idToNode[specId]
761
- if (!nodeId || !Number.isFinite(target)) continue
762
- const cur = baseline[specId] ?? 0
763
- const delta = target - cur
764
- if (Math.abs(delta) < 1e-6) continue
765
- const r = await invoke('optimization_explore', {
766
- control_node_id: nodeId, target_node_id: ctx.daq['film-thickness'],
767
- direction: delta >= 0 ? 'up' : 'down', step: Math.abs(delta), settle_seconds: 15,
768
- hypothesis: `AML 模型推荐投用(precise_search, cost 最优候选): ${specId} ${cur.toFixed(2)}→${Number(target).toFixed(2)}`,
769
- }, ctx.workerB, ctx.token)
770
- ctx.applied.push({ specId, nodeId, from: cur, to: target, ok: !r.isError })
771
- log(` 投用 ${specId}: ${cur.toFixed(2)} → ${Number(target).toFixed(2)} ${r.isError ? '被拒 ' + r.text.split('\n')[0].slice(0, 100) : '√(治理链直写)'}`)
772
- }
773
- if (ctx.applied.length === 0) {
774
- // 推荐与基线一致 = 模型判定当前设定点即最优(探索终点已落在模型最优点上)。
775
- // 这是 precise_search 的合法输出 —— 投用为空操作,后续复测验证膜厚保持在带内。
776
- log(' 模型判定: 当前设定点即最优(推荐=基线),无需变更 —— 由复测确认带内保持')
777
- }
778
-
779
- log(' 等待 90s 工艺响应(settling)…')
780
- await sleep(90_000)
781
- const hAfter = await thicknessMean(ctx.token, ctx.daq['film-thickness'], 45)
782
- ctx.round2 = { hBefore, hAfter, inBand: hAfter != null && Math.abs(hAfter - 50) <= 2 }
783
- log(`${ctx.round2.inBand ? '✔' : '▲'} 模型式投用后膜厚: ${hBefore?.toFixed(2)} → ${hAfter?.toFixed(2)}μm(目标 50μm,带 [48,52])`)
784
- })
785
-
786
- /* ════════ S11 · 贝叶斯寻优(模型 surrogate + UCB) ════════ */
787
- await stage('S11', 'twin_bayes_optimize:模型 surrogate + UCB 多轮收敛寻优', async () => {
788
- // 新鲜快照(S10 投用 + 90s settling 已使上一快照过期)
789
- await ensureDaqRunning()
790
- const snapC = await invoke('twin_snapshot_create', { auto_daq: true, channel_id: ctx.channelB, phase: 'exploration' }, ctx.workerB, ctx.token)
791
- if (snapC.isError) throw new Error(`快照失败: ${snapC.text.slice(0, 240)}`)
792
- const snapshotC = (snapC.text.match(/snapshot_id:\s*([^\n]+)/) || [])[1]?.trim()
793
- const dcwRes = await api('GET', '/api/workshop/dcw', undefined, ctx.token)
794
- const nodes = dataOf(dcwRes)?.nodes ?? []
795
- const valOf = nodeId => Number(nodes.find(n => n.id === nodeId)?.value ?? 0)
796
- const baseline = {}
797
- for (const c of ctx.sceneControls) baseline[c.id] = valOf(c.nodeId)
798
- const bayes = await invoke('twin_bayes_optimize', {
799
- snapshot_id: snapshotC,
800
- baseline_controls: baseline,
801
- rounds: 3,
802
- candidates_per_round: 4,
803
- horizon_steps: 4,
804
- }, ctx.workerB, ctx.token)
805
- writeFileSync(join(OUT_DIR, 'bayes-run.txt'), bayes.text)
806
- const rounds = (bayes.text.match(/"rounds":\s*(\d+)/) || [])[1]
807
- const evalCount = (bayes.text.match(/"candidatesEvaluated":\s*(\d+)/) || [])[1]
808
- ctx.bayes = { rounds: Number(rounds), evaluated: Number(evalCount), ok: !bayes.isError }
809
- log(`${bayes.isError ? '✘' : '✔'} 贝叶斯寻优: ${rounds} 轮 / 评估 ${evalCount} 候选 → ${OUT_DIR.replace(REPO + '/', '')}/bayes-run.txt`)
810
- })
811
-
812
- /* ════════ S12 · 透明度文档 ════════ */
813
- await stage('S12', '生成透明度文档', async () => {
814
- const okR1 = ctx.exploration?.inBand ? '✔ 入带' : '▲ 未入带'
815
- const okR2 = ctx.round2?.inBand ? '✔ 入带' : '▲ 未入带'
816
- const doc = [
817
- `# 双模式闭环优化 · 实机透明度记录(探索式 → AML 模型式)`,
818
- '',
819
- `- 运行: ${RUN_ID} · 平台 ${AW_BASE}(home 隔离实例) · 模拟器 cast-film 预设(${process.env.SIM_BASE} 影子)`,
820
- `- 产线 ${ctx.lineId} · 配方 ${ctx.recipeId} · 优化通道 \`${ctx.channelB}\`(aml_optimization) · 训练通道 \`${ctx.channelA}\`(hybrid_twin)`,
821
- `- 模型 \`${ctx.modelId}\` · Twin Gate ${ctx.gatePassed ? '全过' : '未过'} · MPC mode=${ctx.mpc?.mode}`,
822
- '',
823
- `## 第一轮 · 探索式(optimization_explore 治理写入)`,
824
- '',
825
- `- 起点 ${ctx.exploration?.hStart?.toFixed?.(2)}μm → 终点 ${ctx.exploration?.hEnd?.toFixed?.(2)}μm ${okR1}(screw 150→${ctx.exploration?.screwEnd})`,
826
- '- 每步 = 真实 DCW 写入(绑定鉴权/四层限界/60s 间隔/优化记录)+ settle + 目标均值回读 + 学习摘要;',
827
- ' 探索记录落 optimization_explorations,写控动作全量入册 ops.log。',
828
- '',
829
- '```json',
830
- JSON.stringify(ctx.exploration?.traj ?? [], null, 2).slice(0, 2600),
831
- '```',
832
- '',
833
- `## 第二轮 · AML 模型式(precise_search + 治理投用)`,
834
- '',
835
- `- 投用前 ${ctx.round2?.hBefore?.toFixed?.(2)}μm → 投用后 ${ctx.round2?.hAfter?.toFixed?.(2)}μm ${okR2}`,
836
- `- MPC 推荐: \`${JSON.stringify(ctx.mpc?.best)}\` → 投用 ${JSON.stringify(ctx.applied)}`,
837
- `- 贝叶斯寻优: ${ctx.bayes?.rounds} 轮 / ${ctx.bayes?.evaluated} 候选(surrogate+UCB,recommendation-only)`,
838
- '',
839
- '## 门禁与治理链',
840
- '',
841
- '- 探索模式:孪生工具 fail-closed(EXPLORATION_MODE_NO_MODEL,已负向校验);',
842
- '- 绑定:谱系一致 + Twin Gate 全过(12 判据)+ stage=shadow 才可 PATCH boundModelId;',
843
- '- 模式切换:绑定即 optimizationMode exploration→aml,mpc_optimize 由 safe_small_step 升档 precise_search;',
844
- '- 投用:推荐经 optimization_explore(dcw_control 全治理链)真实写入,VirtualTrial/MPC 恒 candidateExecuted=false。',
845
- '',
846
- '## 全程事件日志',
847
- '',
848
- '```text',
849
- L.join('\n').slice(-60_000),
850
- '```',
851
- ].join('\n')
852
- writeFileSync(DOC_PATH, doc)
853
- log(`✔ 透明度文档: ${DOC_PATH}`)
854
- })
855
-
856
- log('')
857
- log('ALL STAGES DONE ✔ 双模式闭环(探索式 + AML 模型式)全链路完成')
1
+ /**
2
+ * LIVE 双模式闭环优化全链路:探索式(optimization_explore)→ AML 模型式(trial/MPC/bayes)。
3
+ *
4
+ * 与 live-aml-optloop.mjs(单通道 hybrid、REST 激励)的分工:本脚本按 2026-09-26 解耦
5
+ * 架构跑**两个 Channel** —— 工艺优化通道(aml_optimization,探索/AML 双模式)与
6
+ * 训练通道(hybrid_twin,场景冻结/训练/门禁),全部产线写入走 Agent 治理链:
7
+ *
8
+ * 隔离平台(home 模式,AW_BASE:3061) + 专用模拟器(SIM_BASE:4012 影子,cast-film 预设)
9
+ * → admin 注册(首注册即 admin) → provisionTwinLine(6 DCW + 5 DAQ + 6 SP 回读)
10
+ * → 【优化通道 B】实例化(chtpl-aml-optimization-default, exploration) + worker 绑定
11
+ * → 负向校验:探索模式下 twin_trial_run 被 dispatch 拒绝(EXPLORATION_MODE_NO_MODEL)
12
+ * → 【第一轮·探索式】批次1 内 optimization_explore ×N(割线策略收敛膜厚 50μm,
13
+ * 真实写入走 dcw_control 全治理链:绑定鉴权/四层限界/60s 间隔/优化记录)
14
+ * → 激励采样:批次 2-3 阶跃(线速/模口间隙,为模型可辨识性;manual REST 写入,同样限频)
15
+ * → 【训练通道 A】实例化 + worker 绑定 → 场景发现/编译/冻结(用户确认令牌)
16
+ * → 骨架 PhysicsSpec → 数据集(控制=SP 回读,目标=膜厚) → hybrid_residual 训练
17
+ * → 晋升 shadow → snapshot → twin_trial_run×10(必传 model_id,UQ 才有效)
18
+ * → twin_gate_evaluate(12 判据) → 绑定模型到优化通道 B(fail-closed 校验)
19
+ * → 【第二轮·模型式】B 自动进入 aml 模式:mpc_optimize(model_id) → precise_search
20
+ * → 推荐经 optimization_explore 治理投用 → 复测膜厚;twin_bayes_optimize 收敛寻优
21
+ * → 透明度文档 bench/results/<rid>/OPTIMIZATION-LOG.md + state.json(可断点续跑)
22
+ *
23
+ * 运行: node scripts/live-optloop-two-modes.mjs [--run-id <rid>]
24
+ * 断点续跑: 同 --run-id 重跑,已完成 Stage 自动跳过(state.json)。
25
+ */
26
+ import { mkdirSync, writeFileSync, appendFileSync, existsSync, readFileSync } from 'node:fs'
27
+ import { spawn } from 'node:child_process'
28
+ import { join, resolve, dirname } from 'node:path'
29
+ import { fileURLToPath } from 'node:url'
30
+
31
+ const REPO = resolve(dirname(fileURLToPath(import.meta.url)), '..')
32
+ const arg = (k, d) => {
33
+ const i = process.argv.indexOf(k)
34
+ return i >= 0 ? process.argv[i + 1] : d
35
+ }
36
+ const AW_BASE = process.env.AW_BASE ?? 'http://127.0.0.1:3061'
37
+ const AW_PORT = Number(new URL(AW_BASE).port)
38
+ const RUN_ID = arg('--run-id', new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19))
39
+ const OUT_DIR = join(REPO, 'bench', 'results', `${RUN_ID}-optloop-two-modes`)
40
+ mkdirSync(OUT_DIR, { recursive: true })
41
+ const LOG_PATH = join(OUT_DIR, 'live-run.log')
42
+ const STATE_PATH = join(OUT_DIR, 'state.json')
43
+ const DOC_PATH = join(OUT_DIR, 'OPTIMIZATION-LOG.md')
44
+ const AML_ROOT = process.env.AW_AML_DIR_LIVE ?? join(REPO, 'aml')
45
+ const HOME_DIR = process.env.AW_HOME_DIR ?? join(REPO, '.e2e-optloop-home')
46
+
47
+ // 模拟器端口/影子目录必须在 import sim.mjs 之前定死(模块级常量)
48
+ process.env.SIM_BASE = process.env.SIM_BASE ?? 'http://127.0.0.1:4012'
49
+ process.env.SIM_SHADOW_DIR = process.env.SIM_SHADOW_DIR ?? resolve(REPO, '..', 'plc-node-simulator-bench-4012')
50
+ process.env.NO_PROXY = '127.0.0.1,localhost'
51
+ process.env.no_proxy = '127.0.0.1,localhost'
52
+
53
+ const L = []
54
+ function log(line) {
55
+ const text = typeof line === 'string' ? line : JSON.stringify(line)
56
+ const stamped = `[${new Date().toISOString()}] ${text}`
57
+ console.log(stamped)
58
+ L.push(text)
59
+ appendFileSync(LOG_PATH, stamped + '\n')
60
+ }
61
+ function section(title) {
62
+ log('')
63
+ log('════════════════════════════════════════════════════════')
64
+ log(` ${title}`)
65
+ log('════════════════════════════════════════════════════════')
66
+ }
67
+ const sleep = ms => new Promise(r => setTimeout(r, ms))
68
+
69
+ async function api(method, path, body, token) {
70
+ const r = await fetch(AW_BASE + path, {
71
+ method,
72
+ headers: { 'content-type': 'application/json', ...(token ? { authorization: `Bearer ${token}` } : {}) },
73
+ body: body === undefined ? undefined : JSON.stringify(body),
74
+ signal: AbortSignal.timeout(120_000),
75
+ })
76
+ const json = await r.json().catch(() => null)
77
+ return { status: r.status, json }
78
+ }
79
+ const dataOf = r => r.json?.data ?? r.json
80
+
81
+ async function invoke(tool, args, agentId, token) {
82
+ const r = await api('POST', '/api/workshop/agent-tools/invoke', { agentId, tool, args }, token)
83
+ const text = r.json?.data?.result?.text ?? r.json?.result?.text ?? JSON.stringify(r.json ?? {}).slice(0, 600)
84
+ log(` [invoke:${agentId.slice(-6)}] ${tool} → ${r.status}`)
85
+ return { status: r.status, text, isError: Boolean(r.json?.data?.result?.isError ?? r.json?.result?.isError) }
86
+ }
87
+
88
+ async function waitFor(predicate, { timeoutMs, everyMs = 4000, what }) {
89
+ const t0 = Date.now()
90
+ while (Date.now() - t0 < timeoutMs) {
91
+ const v = await predicate()
92
+ if (v) return v
93
+ await sleep(everyMs)
94
+ }
95
+ throw new Error(`等待超时: ${what}(${timeoutMs}ms)`)
96
+ }
97
+
98
+ /* ── 断点续跑状态 ── */
99
+ const ctx = {
100
+ stages: {},
101
+ ...(existsSync(STATE_PATH) ? JSON.parse(readFileSync(STATE_PATH, 'utf8')) : {}),
102
+ }
103
+ function saveState() {
104
+ writeFileSync(STATE_PATH, JSON.stringify(ctx, null, 2))
105
+ }
106
+ async function stage(id, title, fn) {
107
+ if (ctx.stages[id]?.done) {
108
+ log(`↷ 跳过 Stage ${id} · ${title}(已于 ${ctx.stages[id].at} 完成)`)
109
+ return
110
+ }
111
+ section(`Stage ${id} · ${title}`)
112
+ await fn()
113
+ ctx.stages[id] = { done: true, at: new Date().toISOString() }
114
+ saveState()
115
+ }
116
+
117
+ /** 膜厚最近窗口均值(平台数采 = 闭环真实观测路径;samples 新→旧,须按 at 排序) */
118
+ async function thicknessMean(token, nodeId, windowS = 30) {
119
+ const r = await api('GET', `/api/workshop/daq/${nodeId}/samples?bucketMs=1000&limit=${Math.max(60, windowS)}`, undefined, token)
120
+ const pts = (dataOf(r)?.points ?? [])
121
+ .map(p => ({ at: Number(p.at ?? 0), v: Number(p.avg ?? p.value) }))
122
+ .filter(p => Number.isFinite(p.v))
123
+ .sort((a, b) => a.at - b.at)
124
+ .slice(-windowS)
125
+ if (!pts.length) return null
126
+ return pts.reduce((a, b) => a + b.v, 0) / pts.length
127
+ }
128
+
129
+ /** 平台重启后 DAQ 控制器为内存态不会自启 —— 快照/采样前必须显式拉起(幂等) */
130
+ async function ensureDaqRunning() {
131
+ const r = await api('POST', '/api/workshop/daq/controller', { action: 'start' }, ctx.token)
132
+ log(` daq controller start → HTTP ${r.status}`)
133
+ await sleep(4000)
134
+ }
135
+
136
+ /* ════════ S0 · 隔离平台 + 专用模拟器 ════════ */
137
+ await stage('S0', '隔离平台 + 专用模拟器(cast-film 预设)', async () => {
138
+ const platformUp = async () => {
139
+ try {
140
+ const r = await fetch(`${AW_BASE}/api/users/setup-status`, { signal: AbortSignal.timeout(5000) })
141
+ const j = await r.json().catch(() => null)
142
+ return r.status === 200 && j?.data != null
143
+ }
144
+ catch { return false }
145
+ }
146
+ if (!(await platformUp())) {
147
+ const out = appendFileSync === undefined ? 'ignore' : 'ignore'
148
+ const child = spawn(process.execPath, [join(REPO, 'bin', 'aw.mjs'), 'start', '--port', String(AW_PORT)], {
149
+ cwd: REPO,
150
+ env: {
151
+ ...process.env,
152
+ AW_MODE: 'home',
153
+ AW_HOME: HOME_DIR,
154
+ AW_AML_DIR: AML_ROOT,
155
+ NUXT_SESSION_PASSWORD: process.env.NUXT_SESSION_PASSWORD ?? 'e2e-session-password-0123456789abcdef',
156
+ PORT: String(AW_PORT),
157
+ },
158
+ detached: true,
159
+ stdio: 'ignore',
160
+ })
161
+ child.unref()
162
+ log(`平台冷启: port=${AW_PORT} pid=${child.pid}(home 模式,AW_HOME=${HOME_DIR})`)
163
+ log(` AW_AML_DIR=${AML_ROOT}(复用真实训练 venv;模型工件落 repo ./aml)`)
164
+ void out
165
+ }
166
+ await waitFor(platformUp, { timeoutMs: 180_000, what: '平台就绪' })
167
+ log(`✔ 平台在线 ${AW_BASE}(home 模式,数据与生产实例零交集)`)
168
+
169
+ const { ensureSimulator, applyPreset, simNodes } = await import('../bench/lib/sim.mjs')
170
+ const sim = await ensureSimulator({ log: m => log(`[sim] ${m}`) })
171
+ log(`✔ 模拟器在线: ${JSON.stringify(sim).slice(0, 140)}`)
172
+ await applyPreset('cast-film-physics')
173
+ ctx.simDevices = await simNodes()
174
+ log(`✔ cast-film 预设应用,设备 ${ctx.simDevices.length} 台: ${ctx.simDevices.map(d => `${d.id}(${d.protocol})`).join(', ')}`)
175
+ })
176
+
177
+ /* ════════ S1 · admin 注册 + 产线 provisioning ════════ */
178
+ await stage('S1', 'admin 注册 + 产线 provisioning(6 DCW + 5 DAQ + 6 SP 回读)', async () => {
179
+ const reg = await api('POST', '/api/workshop/users/register', { name: `optloop-${RUN_ID}` })
180
+ ctx.token = reg.json?.data?.token
181
+ const who = dataOf(reg)?.user ?? reg.json?.data
182
+ if (!ctx.token) throw new Error(`注册失败: ${JSON.stringify(reg.json).slice(0, 200)}`)
183
+ log(`✔ token 就绪(user=${who?.name ?? who?.email ?? '?'} role=${who?.role ?? '?'};home 模式首注册即 admin)`)
184
+
185
+ const { provisionTwinLine, startTwinBatch } = await import('../bench/lib/closedloop.mjs')
186
+ const { simExport } = await import('../bench/lib/sim.mjs')
187
+ const call = async (m, p, b) => {
188
+ const r = await api(m, p, b, ctx.token)
189
+ return { status: r.status, ...(r.json ?? {}) }
190
+ }
191
+ const sfx = RUN_ID.slice(5, 16).replace(/-/g, '')
192
+ ctx.sfx = sfx
193
+ const twin = await provisionTwinLine({ call }, { simDevices: ctx.simDevices, sfx })
194
+ for (const e of twin.ev) log(' ' + e)
195
+ if (!twin.ok) throw new Error(`provision 失败: ${(twin.errors ?? []).join('; ')}`)
196
+ ctx.lineId = twin.lineId
197
+ ctx.productId = twin.productId
198
+ ctx.dcw = twin.dcw
199
+ ctx.daq = twin.daq
200
+ log(`✔ lineId=${ctx.lineId} productId=${ctx.productId}`)
201
+ log(` DCW: ${JSON.stringify(ctx.dcw)}`)
202
+ log(` DAQ: ${JSON.stringify(ctx.daq)}`)
203
+
204
+ // 控制器显式启动(采样节拍入口)
205
+ const ctl = await api('POST', '/api/workshop/daq/controller', { action: 'start' }, ctx.token)
206
+ log(`✔ daq controller start → HTTP ${ctl.status}`)
207
+
208
+ // 膜厚语义补『厚度』(scene compile 的 target 词表推断依据)
209
+ await api('PATCH', `/api/workshop/daq/${ctx.daq['film-thickness']}`, { semantics: '流延膜厚度测量(优化目标 goal,单位 μm;厚度质量输出)' }, ctx.token)
210
+
211
+ // SP 设定点回读 DAQ 节点:AML 数据集的 control 输入取自数采时序库,执行器设定点必须有回读节点
212
+ ctx.spReadback = {}
213
+ for (const dev of ctx.simDevices) {
214
+ const exp = await simExport(dev.id)
215
+ const items = exp?.items ?? []
216
+ for (const spId of Object.keys(ctx.dcw)) {
217
+ if (ctx.spReadback[spId]) continue
218
+ const sig = (dev.signals ?? []).find(s => s.id === spId)
219
+ if (!sig) continue
220
+ const item = items.find(i => i.signal === sig.name)
221
+ if (!item?.driverConfig) continue
222
+ const cfg = { ...item.driverConfig }
223
+ if (cfg.jsonKey !== undefined && cfg.jsonPath === undefined) {
224
+ cfg.jsonPath = cfg.jsonKey
225
+ delete cfg.jsonKey
226
+ }
227
+ const r = await api('POST', '/api/workshop/daq', {
228
+ name: `${sig.name} 回读 ${sfx}`, templateRef: 'daq-temp-tc', driver: dev.protocol, driverConfig: cfg,
229
+ unit: sig.unit, min: sig.min, max: sig.max, lineId: ctx.lineId, intervalMs: 1000, publishIntervalMs: 0,
230
+ semantics: `执行器设定点回读(AML control 输入) ${item.signal}`,
231
+ }, ctx.token)
232
+ if (dataOf(r)?.node?.id) ctx.spReadback[spId] = dataOf(r).node.id
233
+ }
234
+ }
235
+ log(`✔ SP 回读 DAQ 节点 ${Object.keys(ctx.spReadback).length}/6: ${JSON.stringify(ctx.spReadback)}`)
236
+
237
+ const batch = await startTwinBatch({ call }, { lineId: ctx.lineId, productId: ctx.productId, dcw: ctx.dcw, sfx })
238
+ if (!batch.ok) throw new Error(`开跑失败: ${batch.errors?.join('; ')}`)
239
+ ctx.recipeId = batch.recipeId
240
+ log(`✔ 配方开跑 recipeId=${ctx.recipeId}`)
241
+ })
242
+
243
+ /* ════════ S2 · 优化通道 B(exploration)+ worker 绑定 + 门控负向校验 ════════ */
244
+ await stage('S2', '工艺优化通道 B 实例化(exploration)+ worker 绑定 + 探索期门控负向校验', async () => {
245
+ const scene = { sceneId: `castfilm-hold-opt-${ctx.sfx}`, sceneVersion: '1.0.0', lineId: ctx.lineId, productId: ctx.productId, recipeId: ctx.recipeId }
246
+ const inst = await api('POST', '/api/workshop/channel-templates/chtpl-aml-optimization-default/instantiate', {
247
+ name: `双模式闭环优化 ${RUN_ID}`,
248
+ toolProfile: 'aml_optimization',
249
+ scene,
250
+ objective: { objectiveId: 'thickness-50um', targets: { film_thickness: 50 }, weights: { film_thickness: 1 } },
251
+ controlPolicy: 'recommendation_only',
252
+ optimizationMode: 'exploration',
253
+ }, ctx.token)
254
+ const d = dataOf(inst)
255
+ ctx.channelB = d?.channelId
256
+ const worker = (d?.agents ?? []).find(a => a.role === 'worker' && a.name === '优化执行器') ?? (d?.agents ?? []).find(a => a.role === 'worker')
257
+ ctx.workerB = worker?.id
258
+ if (!ctx.channelB || !ctx.workerB) throw new Error(`优化通道实例化失败: ${JSON.stringify(inst.json).slice(0, 300)}`)
259
+ log(`✔ 优化通道 B=${ctx.channelB} worker(优化执行器)=${ctx.workerB}`)
260
+
261
+ for (const nodeId of Object.values(ctx.dcw)) await api('POST', '/api/workshop/agent-tools/bindings', { agentId: ctx.workerB, nodeId, kind: 'dcw', mode: 'auto' }, ctx.token)
262
+ for (const nodeId of Object.values(ctx.daq)) await api('POST', '/api/workshop/agent-tools/bindings', { agentId: ctx.workerB, nodeId, kind: 'daq', mode: 'auto' }, ctx.token)
263
+ log(`✔ workerB 绑定 ${Object.keys(ctx.dcw).length} DCW + ${Object.keys(ctx.daq).length} DAQ(auto 模式)`)
264
+
265
+ // 注入面校验:工具清单应含 optimization_explore;探索模式下孪生工具被 dispatch 拒绝
266
+ const list = await api('GET', `/api/workshop/agent-tools/list?agentId=${ctx.workerB}`, undefined, ctx.token)
267
+ const names = (dataOf(list)?.tools ?? dataOf(list) ?? []).map(t => t.name ?? t)
268
+ const hasExplore = names.includes('optimization_explore')
269
+ const hasDcwDirect = names.includes('dcw_control')
270
+ log(`✔ 工具面: optimization_explore=${hasExplore ? '√' : '✘'} dcw 直写(应为 false)=${hasDcwDirect ? '✘ 泄漏' : '√ 已收敛到探索治理链'}`)
271
+ if (!hasExplore) throw new Error('优化通道工具面缺 optimization_explore')
272
+
273
+ const neg = await invoke('twin_trial_run', { snapshot_id: 'fake-snap' }, ctx.workerB, ctx.token)
274
+ const blocked = neg.isError && (neg.text.includes('探索') || neg.text.includes('EXPLORATION_MODE_NO_MODEL'))
275
+ log(`✔ 负向校验: 探索模式 twin_trial_run 被拒 = ${blocked ? '√(EXPLORATION_MODE_NO_MODEL)' : `✘ ${neg.text.slice(0, 120)}`}`)
276
+ if (!blocked) throw new Error('探索模式下孪生工具未被拒绝 —— 门控失效')
277
+ })
278
+
279
+ /* ════════ S3 · 第一轮:探索式闭环(批次1 内,optimization_explore 贪心多通道) ════════ */
280
+ await stage('S3', '第一轮·探索式闭环(optimization_explore 真实写入,贪心多通道收敛膜厚 50μm)', async () => {
281
+ const film = ctx.daq['film-thickness']
282
+ const TARGET = 50
283
+ // 单步限制 = 参数基准限界层的 2% 量程(screw 3rpm / linespeed 2 / diegap 0.03,实测 6rpm 被拒 400)
284
+ const CH = {
285
+ screw: { node: ctx.dcw['screw-sp'], limit: 3, gain: 0.144, value: 150, unit: 'rpm' },
286
+ linespeed: { node: ctx.dcw['linespeed-sp'], limit: 2, gain: -0.568, value: 95, unit: 'm/min' },
287
+ diegap: { node: ctx.dcw['diegap-sp'], limit: 0.03, gain: 54, value: 1.0, unit: 'mm' },
288
+ }
289
+ let h = await thicknessMean(ctx.token, film, 20)
290
+ log(` 探索起点: 膜厚≈${h?.toFixed(2) ?? '?'}μm(screw=150, v=95, diegap=1.0;目标 ${TARGET}μm)`)
291
+ const traj = [{ step: 0, h }]
292
+ // 首个写入前等过 60s 治理间隔(全新跑时 S1 配方下发刚写完各节点)
293
+ await sleep(45_000)
294
+
295
+ // 贪心策略:每步选「预计移动量 = |增益×限步| 最大」的通道,按残差在线修正增益;
296
+ // 同通道两次写入 ≥60s(在线探索硬卡控)→ 相邻步强制换通道 + 步间 25s。
297
+ let lastKey = ''
298
+ let lastH = h
299
+ for (let i = 1; i <= 9; i++) {
300
+ if (h != null && Math.abs(h - TARGET) <= 1.2) {
301
+ log(` ✔ 第 ${i - 1} 步已入带: 膜厚 ${h.toFixed(2)}μm ∈ [${TARGET - 2},${TARGET + 2}],提前收敛`)
302
+ break
303
+ }
304
+ await sleep(25_000)
305
+ const err = TARGET - (h ?? TARGET)
306
+ const candidates = Object.entries(CH)
307
+ .filter(([k, c]) => k !== lastKey && Math.abs(c.gain) * c.limit > 0.05)
308
+ .map(([k, c]) => ({ k, c, move: Math.abs(c.gain) * c.limit, dir: Math.sign(err) * Math.sign(c.gain) >= 0 ? 'up' : 'down' }))
309
+ if (!candidates.length) break
310
+ candidates.sort((a, b) => b.move - a.move)
311
+ const pick = candidates[0]
312
+ const c = pick.c
313
+ const before = c.value
314
+ const r = await invoke('optimization_explore', {
315
+ control_node_id: c.node, target_node_id: film,
316
+ direction: pick.dir, step: c.limit, settle_seconds: 15,
317
+ hypothesis: `贪心探索(${pick.k}): h=${h?.toFixed(2)}μm → 目标 ${TARGET}μm,预计 ${pick.dir === 'up' ? '+' : '-'}${(Math.abs(c.gain) * c.limit).toFixed(2)}μm(增益 ${c.gain.toFixed(3)}μm/${c.unit}×限步${c.limit})`,
318
+ }, ctx.workerB, ctx.token)
319
+ if (r.isError) {
320
+ log(` ⚠ [${pick.k}#${i}] 被拒: ${r.text.split('\n').slice(0, 2).join(' ').slice(0, 150)}`)
321
+ CH[pick.k].gain *= 0.3 // 降权避免反复撞墙
322
+ continue
323
+ }
324
+ c.value = Math.round((before + (pick.dir === 'up' ? c.limit : -c.limit)) * 1000) / 1000
325
+ lastKey = pick.k
326
+ const hNow = await thicknessMean(ctx.token, film, 12)
327
+ // 残差归因:实际响应与预计之差修正该通道增益(在线辨识)
328
+ if (hNow != null && lastH != null) {
329
+ const predicted = Math.abs(c.gain) * c.limit * (pick.dir === 'up' ? Math.sign(c.gain) : -Math.sign(c.gain))
330
+ const observed = hNow - (h ?? hNow)
331
+ if (Number.isFinite(observed)) c.gain = c.gain * 0.5 + (observed / (pick.dir === 'up' ? c.limit : -c.limit)) * 0.5
332
+ log(` [${pick.k}#${i}] ${pick.dir} ${c.limit} → ${pick.k}=${c.value} · h ${h?.toFixed(2)}→${hNow.toFixed(2)}μm(预计 ${predicted.toFixed(2)},实批 ${observed.toFixed(2)})`)
333
+ }
334
+ else log(` [${pick.k}#${i}] ${pick.dir} ${c.limit} → ${pick.k}=${c.value} · 读数 n/a`)
335
+ h = hNow
336
+ lastH = h
337
+ traj.push({ step: i, channel: pick.k, dir: pick.dir, value: c.value, h })
338
+ }
339
+
340
+ const hEnd = await thicknessMean(ctx.token, film, 30)
341
+ const inBand = hEnd != null && Math.abs(hEnd - TARGET) <= 2
342
+ ctx.exploration = {
343
+ traj, hStart: traj[0]?.h ?? null, hEnd, inBand,
344
+ screwEnd: CH.screw.value, linespeedEnd: CH.linespeed.value, diegapEnd: CH.diegap.value,
345
+ }
346
+ log(`${inBand ? '✔' : '▲'} 探索收敛: ${traj[0]?.h?.toFixed(2)} → ${hEnd?.toFixed(2)}μm(目标带 [48,52];screw=${CH.screw.value} v=${CH.linespeed.value} diegap=${CH.diegap.value})`)
347
+
348
+ // 调控闭环判定收口:最近一条 open 优化记录落 keep(收敛)——真实 ledger 闭环
349
+ const opts = await api('GET', `/api/workshop/dcw/optimizations?lineId=${ctx.lineId}&limit=10`, undefined, ctx.token)
350
+ const openRec = (dataOf(opts)?.records ?? []).find(x => x.status === 'open')
351
+ if (openRec && inBand) {
352
+ const j = await invoke('dcw_judge', { record_id: openRec.id, verdict: 'keep', reason: `探索收敛: 膜厚 ${hEnd.toFixed(2)}μm 入带 [48,52]` }, ctx.workerB, ctx.token)
353
+ log(` dcw_judge keep(${openRec.nodeId.slice(-6)}) → ${j.isError ? j.text.slice(0, 120) : '已入册'}`)
354
+ }
355
+
356
+ // 批次1 保持至 ~450s(与批次2/3 同量级,保证样本量)
357
+ await sleep(150_000)
358
+ await api('POST', `/api/workshop/dcw/lines/${ctx.lineId}/stop`, {}, ctx.token)
359
+ log(' 批次1 停止(探索期数据已全部落 TSDB)')
360
+ })
361
+
362
+ /* ════════ S4 · 激励采样(批次2-3,阶跃辨识) ════════ */
363
+ await stage('S4', '激励采样:批次2-3 阶跃(线速/模口间隙;manual 写入,同受治理限频与 2% 单步限)', async () => {
364
+ const BASE_SP = { 'linespeed-sp': 95, 'diegap-sp': 1.0 }
365
+ // 阶跃幅度受参数单步限制(2% 量程:v ±2, diegap ±0.03,按**当前值**起算),越限写入会被 400 拒绝
366
+ const EXCITE_RUNS = [
367
+ [{ dls: 2.0, ddg: 0.03 }, { dls: -2.0, ddg: -0.03 }],
368
+ [{ dls: -2.0, ddg: 0.03 }, { dls: 1.5, ddg: -0.03 }],
369
+ ]
370
+ const writeOrThrow = async (nodeId, value, tag) => {
371
+ const w = await api('POST', `/api/workshop/dcw/${nodeId}/write`, { value }, ctx.token)
372
+ if (w.status >= 400) throw new Error(`激励写入被拒(${tag} ← ${value}): ${JSON.stringify(w.json?.message ?? w.json).slice(0, 160)}`)
373
+ log(` ${tag} ← ${value} √`)
374
+ }
375
+ // 续跑安全:上一进程可能留下在跑批次,先停(未跑时忽略 409)
376
+ await api('POST', `/api/workshop/dcw/lines/${ctx.lineId}/stop`, {}, ctx.token).catch(() => {})
377
+ await sleep(3000)
378
+ for (let run = 0; run < 2; run++) {
379
+ // stop→start 竞态防护:stop 后等 8s;start 失败重试一次(409 常为状态机未落定)
380
+ await api('POST', `/api/workshop/dcw/lines/${ctx.lineId}/stop`, {}, ctx.token).catch(() => {})
381
+ await sleep(8000)
382
+ let st = await api('POST', `/api/workshop/dcw/lines/${ctx.lineId}/start`, { recipeId: ctx.recipeId }, ctx.token)
383
+ if (st.status !== 200) {
384
+ log(` 批次 ${run + 2} 首次开跑 HTTP ${st.status}: ${JSON.stringify(st.json?.message ?? st.json).slice(0, 120)} → 8s 后重试`)
385
+ await sleep(8000)
386
+ st = await api('POST', `/api/workshop/dcw/lines/${ctx.lineId}/start`, { recipeId: ctx.recipeId }, ctx.token)
387
+ }
388
+ if (st.status !== 200) throw new Error(`批次 ${run + 2} 开跑失败: ${JSON.stringify(st.json).slice(0, 200)}`)
389
+ log(` 批次 ${run + 2} 开跑(同配方 ${ctx.recipeId})`)
390
+ await sleep(65_000)
391
+ const [e1, e2] = EXCITE_RUNS[run]
392
+ let curLs = BASE_SP['linespeed-sp']
393
+ let curDg = BASE_SP['diegap-sp']
394
+ curLs = Math.round((curLs + e1.dls) * 1000) / 1000
395
+ await writeOrThrow(ctx.dcw['linespeed-sp'], curLs, `批次${run + 2} linespeed 阶跃1`)
396
+ curDg = Math.round((curDg + e1.ddg) * 1000) / 1000
397
+ await writeOrThrow(ctx.dcw['diegap-sp'], curDg, `批次${run + 2} diegap 阶跃1`)
398
+ await sleep(150_000)
399
+ curLs = Math.round((curLs + e2.dls) * 1000) / 1000
400
+ await writeOrThrow(ctx.dcw['linespeed-sp'], curLs, `批次${run + 2} linespeed 阶跃2`)
401
+ curDg = Math.round((curDg + e2.ddg) * 1000) / 1000
402
+ await writeOrThrow(ctx.dcw['diegap-sp'], curDg, `批次${run + 2} diegap 阶跃2`)
403
+ await sleep(290_000)
404
+ const latest = await thicknessMean(ctx.token, ctx.daq['film-thickness'], 10)
405
+ log(` 批次${run + 2} 完成(500s) · 膜厚当前≈${latest?.toFixed(2) ?? '?'} μm`)
406
+ }
407
+ await api('POST', `/api/workshop/dcw/lines/${ctx.lineId}/stop`, {}, ctx.token)
408
+ log('✔ 采样完成(批次1 探索 + 批次2/3 各 500s),产线停止')
409
+ })
410
+
411
+ /* ════════ S4B · 补充扫描激励(扩大目标方差,提升可辨识性) ════════ */
412
+ await stage('S4B', '补充激励:模口间隙/线速宽扫描(2 批次;扩大 y 方差 → NRMSE 分母)', async () => {
413
+ const writeOrThrow = async (nodeId, value, tag) => {
414
+ const w = await api('POST', `/api/workshop/dcw/${nodeId}/write`, { value }, ctx.token)
415
+ if (w.status >= 400) throw new Error(`扫描写入被拒(${tag} ← ${value}): ${JSON.stringify(w.json?.message ?? w.json).slice(0, 160)}`)
416
+ log(` ${tag} ← ${value} √`)
417
+ }
418
+ // 单步 ≤2% 限(dg ±0.03 / v ±2),按当前值起算;步间 80s(>60s 治理间隔)
419
+ const SWEEPS = [
420
+ { dg: [1.0, 0.97, 0.94, 0.97, 1.0], ls: null },
421
+ { dg: [1.0, 1.03, 1.06, 1.03, 1.0], ls: [95, 97, 99, 97, 95] },
422
+ ]
423
+ for (let run = 0; run < SWEEPS.length; run++) {
424
+ const sw = SWEEPS[run]
425
+ // stop→start 竞态防护(同 S4):循环头先停+等 8s,start 失败重试一次
426
+ await api('POST', `/api/workshop/dcw/lines/${ctx.lineId}/stop`, {}, ctx.token).catch(() => {})
427
+ await sleep(8000)
428
+ let st = await api('POST', `/api/workshop/dcw/lines/${ctx.lineId}/start`, { recipeId: ctx.recipeId }, ctx.token)
429
+ if (st.status !== 200) {
430
+ log(` 扫描批次 ${run + 1} 首次开跑 HTTP ${st.status} → 8s 后重试`)
431
+ await sleep(8000)
432
+ st = await api('POST', `/api/workshop/dcw/lines/${ctx.lineId}/start`, { recipeId: ctx.recipeId }, ctx.token)
433
+ }
434
+ if (st.status !== 200) throw new Error(`扫描批次 ${run + 1} 开跑失败: ${JSON.stringify(st.json).slice(0, 200)}`)
435
+ log(` 扫描批次 ${run + 1} 开跑`)
436
+ await sleep(65_000)
437
+ for (let i = 1; i < sw.dg.length; i++) {
438
+ await writeOrThrow(ctx.dcw['diegap-sp'], sw.dg[i], `扫描${run + 1} diegap#${i}`)
439
+ if (sw.ls) await writeOrThrow(ctx.dcw['linespeed-sp'], sw.ls[i], `扫描${run + 1} linespeed#${i}`)
440
+ await sleep(80_000)
441
+ }
442
+ await sleep(60_000)
443
+ const latest = await thicknessMean(ctx.token, ctx.daq['film-thickness'], 10)
444
+ log(` 扫描批次 ${run + 1} 完成 · 膜厚当前≈${latest?.toFixed(2) ?? '?'} μm`)
445
+ }
446
+ await api('POST', `/api/workshop/dcw/lines/${ctx.lineId}/stop`, {}, ctx.token)
447
+ log('✔ 扫描激励完成(dg 0.94~1.06 / v 95~99 全覆盖)')
448
+ })
449
+
450
+ /* ════════ S5 · 训练通道 A:实例化 + 场景冻结 + PhysicsSpec ════════ */
451
+ await stage('S5', '训练通道 A 实例化 + worker 绑定 + 场景发现/编译/冻结 + 骨架 PhysicsSpec', async () => {
452
+ const scene = { sceneId: `castfilm-hold-opt-${ctx.sfx}`, sceneVersion: '1.0.0', lineId: ctx.lineId, productId: ctx.productId, recipeId: ctx.recipeId }
453
+ const inst = await api('POST', '/api/workshop/channel-templates/chtpl-hybrid-twin-mpc-default/instantiate', {
454
+ name: `孪生训练 ${RUN_ID}`,
455
+ toolProfile: 'hybrid_twin',
456
+ scene,
457
+ objective: { objectiveId: 'thickness-50um', targets: { film_thickness: 50 } },
458
+ controlPolicy: 'recommendation_only',
459
+ }, ctx.token)
460
+ const d = dataOf(inst)
461
+ ctx.channelA = d?.channelId
462
+ const worker = (d?.agents ?? []).find(a => a.role === 'worker')
463
+ ctx.workerA = worker?.id
464
+ if (!ctx.channelA || !ctx.workerA) throw new Error(`训练通道实例化失败: ${JSON.stringify(inst.json).slice(0, 300)}`)
465
+ log(`✔ 训练通道 A=${ctx.channelA} worker=${ctx.workerA}`)
466
+ for (const nodeId of Object.values(ctx.dcw)) await api('POST', '/api/workshop/agent-tools/bindings', { agentId: ctx.workerA, nodeId, kind: 'dcw', mode: 'auto' }, ctx.token)
467
+ for (const nodeId of Object.values(ctx.daq)) await api('POST', '/api/workshop/agent-tools/bindings', { agentId: ctx.workerA, nodeId, kind: 'daq', mode: 'auto' }, ctx.token)
468
+ log(`✔ workerA 绑定 ${Object.keys(ctx.dcw).length} DCW + ${Object.keys(ctx.daq).length} DAQ`)
469
+
470
+ const SCENE_ID = scene.sceneId
471
+ ctx.sceneId = SCENE_ID
472
+ const disco = await invoke('twin_scene_discover', {}, ctx.workerA, ctx.token)
473
+ const targetOk = disco.text.includes('"target": 1') || disco.text.includes('"target":1')
474
+ log(` 场景发现: target=1 ${targetOk ? '√' : '✘(检查膜厚语义)'}`)
475
+ const compiled = await invoke('twin_scene_compile', {
476
+ scene_id: SCENE_ID, scene_version: '1.0.0', line_id: ctx.lineId, product_id: ctx.productId, recipe_id: ctx.recipeId,
477
+ prompt: '流延膜厚度闭环优化:目标膜厚 50μm。控制=6 个执行器设定点,观测=膜厚(目标)/熔温/熔压。约束:熔温 195~225℃,熔压 ≤22MPa。膜厚为目标输出。',
478
+ }, ctx.workerA, ctx.token)
479
+ if (compiled.isError) throw new Error(`场景编译失败: ${compiled.text.slice(0, 200)}`)
480
+ const frozen = await invoke('twin_scene_freeze', {
481
+ scene_id: SCENE_ID, scene_version: '1.0.0', confirmation: 'USER_CONFIRMED_SCENE_CONTRACT', approved_by: 'live-admin',
482
+ }, ctx.workerA, ctx.token)
483
+ if (frozen.isError) throw new Error(`场景冻结失败: ${frozen.text.slice(0, 200)}`)
484
+ log(`✔ 场景已冻结 ${SCENE_ID}@1.0.0(用户确认令牌)`)
485
+
486
+ const draft = await invoke('twin_physics_spec_draft', { dt_sec: 1 }, ctx.workerA, ctx.token)
487
+ if (draft.isError) throw new Error(`骨架生成失败: ${draft.text.slice(0, 200)}`)
488
+ const draftArtifactPath = (draft.text.match(/artifact:\s*([^\n]+)/) || [])[1]?.trim()
489
+ if (!draftArtifactPath || !existsSync(draftArtifactPath)) throw new Error(`骨架 spec 工件缺失: ${draftArtifactPath}`)
490
+ const physicsSpec = JSON.parse(readFileSync(draftArtifactPath, 'utf8'))
491
+ log(`✔ 骨架 PhysicsSpec: model=${physicsSpec.modelId} 状态 ${physicsSpec.states.length} 观测 ${physicsSpec.observations.length}`)
492
+
493
+ // 训练前对齐在 S6 数据集构建后做(spec 变量改绑回读节点 + 剔除数据集外变量)
494
+ const dwToDn = {}
495
+ for (const [sig, dn] of Object.entries(ctx.spReadback)) dwToDn[ctx.dcw[sig]] = dn
496
+ ctx.physicsSpec = physicsSpec
497
+ ctx.dwToDn = dwToDn
498
+ writeFileSync(join(OUT_DIR, 'physics-spec-draft.json'), JSON.stringify(physicsSpec, null, 2))
499
+ })
500
+
501
+ /* ════════ S6 · 数据集构建 + hybrid_residual 训练 ════════ */
502
+ await stage('S6', 'AML 数据集构建 + hybrid_residual 训练(平台参考训练器)', async () => {
503
+ const sampledControls = []
504
+ for (const [sig, nodeId] of Object.entries(ctx.spReadback)) {
505
+ const r = await api('GET', `/api/workshop/daq/${nodeId}/samples?bucketMs=60000&limit=1`, undefined, ctx.token)
506
+ const has = (dataOf(r)?.points ?? []).length > 0
507
+ log(` 回读采样检查 ${sig}: ${has ? '√' : '✘ 剔除'}`)
508
+ if (has) sampledControls.push({ nodeId, role: 'control' })
509
+ }
510
+ if (sampledControls.length < 4) throw new Error(`可用 control 回读不足: ${sampledControls.length}`)
511
+ const dsBody = {
512
+ lineId: ctx.lineId, productId: ctx.productId, recipeId: ctx.recipeId,
513
+ nodes: [
514
+ ...sampledControls,
515
+ { nodeId: ctx.daq['film-thickness'], role: 'target' },
516
+ { nodeId: ctx.daq['melt-temp'], role: 'feature' },
517
+ { nodeId: ctx.daq['melt-pressure'], role: 'feature' },
518
+ ],
519
+ beatMs: 1000, window: { historySteps: 8, horizonSteps: 4 },
520
+ split: { valRatio: 0.34, testRatio: 0.33, seed: Number(process.env.OPTLOOP_SPLIT_SEED ?? 11) },
521
+ purpose: 'mpc_surrogate',
522
+ note: `双模式闭环数据集(探索+激励) ${RUN_ID}`,
523
+ }
524
+ const ds = await api('POST', '/api/workshop/aml/datasets', dsBody, ctx.token)
525
+ const dataset = dataOf(ds)?.dataset
526
+ if (!dataset) throw new Error(`数据集构建失败: ${JSON.stringify(ds.json).slice(0, 300)}`)
527
+ ctx.datasetId = dataset.id
528
+ log(`✔ 数据集 ${dataset.id}: ${dataset.rowCount} 窗 / ${dataset.runIds.length} 批`)
529
+
530
+ // 训练前对齐(spec 变量改绑回读节点 + 剔除数据集外变量)
531
+ const manifest = JSON.parse(readFileSync(join(AML_ROOT, 'datasets', dataset.id, 'manifest.json'), 'utf8'))
532
+ const datasetNodes = new Set(manifest.allNodes)
533
+ const physicsSpec = ctx.physicsSpec
534
+ let remapped = 0
535
+ for (const v of physicsSpec.variables) {
536
+ if (v.nodeId && !datasetNodes.has(v.nodeId) && ctx.dwToDn[v.nodeId]) {
537
+ v.nodeId = ctx.dwToDn[v.nodeId]
538
+ remapped++
539
+ }
540
+ }
541
+ const keptVars = physicsSpec.variables.filter(v => !v.nodeId || datasetNodes.has(v.nodeId))
542
+ const keptIds = new Set(keptVars.map(v => v.id))
543
+ physicsSpec.variables = keptVars
544
+ physicsSpec.states = physicsSpec.states.filter((e) => {
545
+ const base = e.lhs.endsWith('_next') ? e.lhs.slice(0, -5) : e.lhs
546
+ return keptIds.has(base)
547
+ })
548
+ physicsSpec.observations = physicsSpec.observations.filter(e => keptIds.has(e.lhs))
549
+ physicsSpec.guards = (physicsSpec.guards ?? []).filter(e => keptIds.has(e.lhs))
550
+ physicsSpec.constraints = physicsSpec.constraints.filter(c => keptIds.has(c.id))
551
+ writeFileSync(join(OUT_DIR, 'physics-spec-remapped.json'), JSON.stringify(physicsSpec, null, 2))
552
+ log(`✔ 训练对齐: 控制改绑 ${remapped};保留变量 ${keptVars.length}`)
553
+
554
+ const jobRes = await api('POST', '/api/workshop/aml/jobs', {
555
+ datasetId: dataset.id,
556
+ purpose: 'mpc_surrogate',
557
+ changeNote: '双模式闭环:骨架物理+数据残差(全部 DCW → 膜厚 goal)',
558
+ params: { epochs: Number(process.env.OPTLOOP_EPOCHS ?? 600), hidden: Number(process.env.OPTLOOP_HIDDEN ?? 128), lr: 0.0015, residual_scale: Number(process.env.OPTLOOP_RESIDUAL ?? 2.0), ensemble: 3 },
559
+ seed: Number(process.env.OPTLOOP_SEED ?? 11),
560
+ jobKind: 'hybrid_residual',
561
+ sceneId: ctx.sceneId,
562
+ sceneVersion: '1.0.0',
563
+ objectiveId: 'thickness-50um',
564
+ physicsSpec,
565
+ providerId: physicsSpec.modelId,
566
+ providerVersion: '1.0.0',
567
+ providerHash: `sha256:${JSON.stringify(physicsSpec).length}`,
568
+ modelName: `流延膜厚双模式闭环模型 ${ctx.sfx}`,
569
+ modelDescription: `输入=全部 6 个 DCW 执行器(SP 回读);输出=膜厚 goal(50μm);场景 ${ctx.sceneId}@1.0.0;产线 ${ctx.lineId}/配方 ${ctx.recipeId};数据含探索式闭环真实写入`,
570
+ }, ctx.token)
571
+ const job = dataOf(jobRes)?.job
572
+ if (!job) throw new Error(`作业提交失败: ${JSON.stringify(jobRes.json).slice(0, 300)}`)
573
+ ctx.jobId = job.id
574
+ log(`✔ 训练作业 ${job.id} 入队(hybrid_residual)`)
575
+
576
+ let jobDone = null
577
+ for (let i = 0; i < 210; i++) {
578
+ await sleep(10_000)
579
+ const st = await api('GET', `/api/workshop/aml/jobs/${job.id}`, undefined, ctx.token)
580
+ const j = dataOf(st)?.job ?? dataOf(st)
581
+ if (!j) continue
582
+ log(` [${i * 10}s] ${j.status} ${j.stage} ${j.progress}%`)
583
+ if (['done', 'failed', 'cancelled', 'timeout'].includes(j.status)) {
584
+ jobDone = j
585
+ break
586
+ }
587
+ }
588
+ if (!jobDone || jobDone.status !== 'done') throw new Error(`训练未成功: ${JSON.stringify(jobDone).slice(0, 300)}`)
589
+ const gates = (() => {
590
+ try {
591
+ return JSON.parse(jobDone.gatesJson || '{}')
592
+ }
593
+ catch {
594
+ return {}
595
+ }
596
+ })()
597
+ ctx.platformGates = gates
598
+ log(`✔ 训练完成 · 平台门禁: ${gates.passed === true ? '全部通过' : `未过(${JSON.stringify(gates).slice(0, 160)})`}`)
599
+ })
600
+
601
+ /* ════════ S7 · 模型校验 + 晋升 shadow ════════ */
602
+ await stage('S7', '模型注册校验 + 晋升 shadow', async () => {
603
+ const modelsRes = await api('GET', '/api/workshop/aml/models', undefined, ctx.token)
604
+ const model = (dataOf(modelsRes)?.models ?? []).find(m => m.datasetId === ctx.datasetId)
605
+ if (!model) throw new Error('模型未登记')
606
+ ctx.modelId = model.id
607
+ const m = model.metrics ?? {}
608
+ log(`✔ 模型 ${model.id} [${model.stage}] label=${model.label}`)
609
+ log(` G1 单步 NRMSE=${m.oneStepTest?.nrmse} · G2 滚动=${m.rolloutTest?.nrmse}`)
610
+ log(` hybrid=${JSON.stringify(m.hybrid ?? {}).slice(0, 200)}`)
611
+ log(` uncertainty=${JSON.stringify(m.uncertainty ?? {}).slice(0, 200)}`)
612
+ const promo = await api('POST', `/api/workshop/aml/models/${model.id}/promote`, { toStage: 'shadow' }, ctx.token)
613
+ log(`✔ 晋升 shadow → HTTP ${promo.status}`)
614
+ if (promo.status >= 400) throw new Error(`晋升失败: ${JSON.stringify(promo.json).slice(0, 200)}`)
615
+ })
616
+
617
+ /* ════════ S8 · 候选试验(必传 model_id)→ Twin Gate ════════ */
618
+ await stage('S8', '候选试验 ×10(模型驱动 rollout)+ twin_gate_evaluate', async () => {
619
+ await ensureDaqRunning()
620
+ await api('POST', `/api/workshop/dcw/lines/${ctx.lineId}/start`, { recipeId: ctx.recipeId }, ctx.token)
621
+ log(' 产线重启(真实工况采快照)')
622
+ await sleep(25_000)
623
+
624
+ const snap = await invoke('twin_snapshot_create', { auto_daq: true, channel_id: ctx.channelA, phase: 'exploration' }, ctx.workerA, ctx.token)
625
+ if (snap.isError) throw new Error(`快照失败: ${snap.text.slice(0, 240)}`)
626
+ ctx.snapshotA = (snap.text.match(/snapshot_id:\s*([^\n]+)/) || [])[1]?.trim()
627
+ log(`✔ 快照 ${ctx.snapshotA}`)
628
+
629
+ const frozenPath = join(AML_ROOT, 'twins', 'scenes', `${ctx.sceneId}-1.0.0-frozen`, 'scenes.json')
630
+ const frozenArtifact = JSON.parse(readFileSync(frozenPath, 'utf8'))
631
+ const frozenScene = frozenArtifact.scene ?? frozenArtifact
632
+ ctx.sceneControls = frozenScene.controls ?? []
633
+ const speedCtl = ctx.sceneControls.find(c => (c.nodeId ?? '').includes('linespeed')) ?? ctx.sceneControls[0]
634
+ const speedStep = speedCtl?.maxStep ?? 2
635
+ let uqAllPass = true
636
+ for (let k = 0; k < 10; k++) {
637
+ const delta = (k % 2 === 0 ? 1 : -0.5) * speedStep * (0.3 + 0.07 * k)
638
+ const cand = 95 + delta
639
+ const t = await invoke('twin_trial_run', {
640
+ snapshot_id: ctx.snapshotA,
641
+ model_id: ctx.modelId,
642
+ baseline_controls: { [speedCtl.id]: 95 },
643
+ candidate_controls: [
644
+ { [speedCtl.id]: cand }, { [speedCtl.id]: cand }, { [speedCtl.id]: cand }, { [speedCtl.id]: cand },
645
+ ],
646
+ }, ctx.workerA, ctx.token)
647
+ const uqOk = t.text.includes('ood=accepted')
648
+ if (!uqOk) uqAllPass = false
649
+ log(` trial#${k + 1} Δ=${delta.toFixed(2)} uq/ood=${uqOk ? '√' : '✘'} ${t.text.split('\n').find(x => x.includes('improvement'))?.trim().slice(0, 80) ?? ''}`)
650
+ }
651
+ if (!uqAllPass) log(' ⚠ 存在 UQ/OOD 未通过的候选(会影响 G7)')
652
+
653
+ const gate = await invoke('twin_gate_evaluate', { model_id: ctx.modelId, scene_id: ctx.sceneId }, ctx.workerA, ctx.token)
654
+ writeFileSync(join(OUT_DIR, 'twin-gate.txt'), gate.text)
655
+ // 顶层 passed 解析:不能 text.includes('"passed": true') —— checks[] 每个子项也有
656
+ // passed 字段,任意子项为 true 都会误判整门通过(实测 G7 false 仍被放行)。
657
+ const gateTop = gate.text.match(/^\{[\s\S]*?"passed":\s*(true|false)/)
658
+ const gatePassed = gateTop?.[1] === 'true'
659
+ ctx.gatePassed = gatePassed
660
+ for (const line of gate.text.split('\n').filter(x => x.includes('"id"') || x.includes('"passed"')).slice(0, 32)) log(' ' + line.trim())
661
+ log(`${gatePassed ? '✔' : '✘'} Twin Gate(回写 twinEligibility + shadowEvidence)`)
662
+ if (!gatePassed) throw new Error('Twin Gate 未全过 —— 绑定会被 fail-closed 拒绝')
663
+
664
+ await api('POST', `/api/workshop/dcw/lines/${ctx.lineId}/stop`, {}, ctx.token)
665
+ })
666
+
667
+ /* ════════ S9 · 绑定模型到优化通道 B(fail-closed) ════════ */
668
+ await stage('S9', '绑定模型到优化通道 B(谱系+门禁 fail-closed 校验;自动切 aml 模式)', async () => {
669
+ const patch = await api('PATCH', `/api/workshop/channels/${ctx.channelB}/twin-profile`, { boundModelId: ctx.modelId }, ctx.token)
670
+ if (patch.status >= 400) throw new Error(`绑定失败: ${JSON.stringify(patch.json).slice(0, 300)}`)
671
+ const prof = dataOf(patch)
672
+ ctx.profileAfterBind = prof
673
+ log(`✔ 绑定 ${ctx.modelId} → profile=${prof?.profile} mode=${prof?.mode}(探索期被拒的孪生工具现已放行)`)
674
+
675
+ // 交叉校验:同一工具,aml 模式下不再被拒(快照不存在报错≠门控拒绝)
676
+ const probeRun = await invoke('twin_trial_run', { snapshot_id: 'probe-nonexist', model_id: ctx.modelId }, ctx.workerB, ctx.token)
677
+ const gateGone = !probeRun.text.includes('EXPLORATION_MODE_NO_MODEL')
678
+ log(` aml 模式孪生工具放行 = ${gateGone ? '√' : '✘'}(返回:${probeRun.text.split('\n')[0].slice(0, 100)})`)
679
+ if (!gateGone) throw new Error('aml 模式下孪生工具仍被拒')
680
+ })
681
+
682
+ /* ════════ S10 · 第二轮:模型驱动参数优化(precise_search + 治理投用) ════════ */
683
+ await stage('S10', '第二轮·模型式优化:回到探索终点 → mpc_optimize(model_id) → precise_search → 治理投用 → 复测', async () => {
684
+ await ensureDaqRunning()
685
+ await api('POST', `/api/workshop/dcw/lines/${ctx.lineId}/start`, { recipeId: ctx.recipeId }, ctx.token)
686
+ log(' 产线重启(批次4;配方下发回到起始工况)')
687
+ // 等 60s 治理写间隔 + 工艺稳定
688
+ await sleep(65_000)
689
+
690
+ // 回到第一轮探索终点(模型在终点邻域做精确微调 —— 两阶段设计的本意:探索找近,模型收准)。
691
+ // 恢复也走治理链:单步 ≤2% 限,多轮逼近(每轮按产线真实当前值算剩余差,通道轮换保 60s 间隔)。
692
+ const END = { screw: ctx.exploration?.screwEnd ?? 150, linespeed: ctx.exploration?.linespeedEnd ?? 95, diegap: ctx.exploration?.diegapEnd ?? 1.0 }
693
+ const CH2 = {
694
+ screw: { node: ctx.dcw['screw-sp'], limit: 3 },
695
+ linespeed: { node: ctx.dcw['linespeed-sp'], limit: 2 },
696
+ diegap: { node: ctx.dcw['diegap-sp'], limit: 0.03 },
697
+ }
698
+ const currentVals = async () => {
699
+ const d = await api('GET', '/api/workshop/dcw', undefined, ctx.token)
700
+ const map = {}
701
+ for (const n of (dataOf(d)?.nodes ?? [])) map[n.id] = Number(n.value ?? 0)
702
+ return map
703
+ }
704
+ for (let round = 0; round < 5; round++) {
705
+ const vals = await currentVals()
706
+ const pending = Object.entries(CH2).filter(([k, c]) => Math.abs(END[k] - (vals[c.node] ?? 0)) > c.limit * 0.3)
707
+ if (pending.length === 0) break
708
+ let moved = false
709
+ for (const [k, c] of pending) {
710
+ const cur = vals[c.node] ?? 0
711
+ const delta = END[k] - cur
712
+ if (moved) await sleep(30_000)
713
+ const r = await invoke('optimization_explore', {
714
+ control_node_id: c.node, target_node_id: ctx.daq['film-thickness'],
715
+ direction: delta >= 0 ? 'up' : 'down', step: Math.min(c.limit, Math.abs(delta)), settle_seconds: 15,
716
+ hypothesis: `恢复第一轮探索终点(${k}): ${cur.toFixed(2)}→${END[k]}(模型微调起点)`,
717
+ }, ctx.workerB, ctx.token)
718
+ log(` 恢复 ${k} ${cur.toFixed(2)}${delta >= 0 ? '+' : '-'}${Math.min(c.limit, Math.abs(delta)).toFixed(2)}: ${r.isError ? '被拒 ' + r.text.split('\n').slice(0, 2).join(' ').slice(0, 110) : '√'}`)
719
+ if (!r.isError) moved = true
720
+ }
721
+ if (!moved) break
722
+ await sleep(30_000)
723
+ }
724
+ await sleep(15_000)
725
+
726
+ const snapB = await invoke('twin_snapshot_create', { auto_daq: true, channel_id: ctx.channelB, phase: 'exploration' }, ctx.workerB, ctx.token)
727
+ if (snapB.isError) throw new Error(`B 快照失败: ${snapB.text.slice(0, 240)}`)
728
+ ctx.snapshotB = (snapB.text.match(/snapshot_id:\s*([^\n]+)/) || [])[1]?.trim()
729
+ log(`✔ 优化通道快照 ${ctx.snapshotB}(冻结场景按 sceneId 解析 = 训练通道冻结的同一契约)`)
730
+
731
+ // 基线 = 当前真实设定(优化通道节点值)
732
+ const dcwRes = await api('GET', '/api/workshop/dcw', undefined, ctx.token)
733
+ const nodes = dataOf(dcwRes)?.nodes ?? []
734
+ const valOf = nodeId => Number(nodes.find(n => n.id === nodeId)?.value ?? 0)
735
+ const baseline = {}
736
+ for (const c of ctx.sceneControls) baseline[c.id] = valOf(c.nodeId)
737
+ log(` 基线(当前设定): ${JSON.stringify(baseline)}`)
738
+ const hBefore = await thicknessMean(ctx.token, ctx.daq['film-thickness'], 30)
739
+ log(` 投用前膜厚(30s 均值): ${hBefore?.toFixed(2) ?? '?'}μm`)
740
+
741
+ const mpc = await invoke('mpc_optimize', {
742
+ snapshot_id: ctx.snapshotB,
743
+ model_id: ctx.modelId,
744
+ baseline_controls: baseline,
745
+ horizon_steps: 4,
746
+ }, ctx.workerB, ctx.token)
747
+ writeFileSync(join(OUT_DIR, 'mpc-recommendation.txt'), mpc.text)
748
+ const mode = (mpc.text.match(/"mode":\s*"([^"]+)"/) || [])[1]
749
+ const bestRaw = (mpc.text.match(/"bestCandidate":\s*\{([^}]*)\}/) || [])[1] ?? ''
750
+ const best = {}
751
+ for (const mm of bestRaw.matchAll(/"([^"]+)":\s*(-?[\d.]+(?:e[+-]?\d+)?)/gi)) best[mm[1]] = Number(mm[2])
752
+ ctx.mpc = { mode, best, hBefore }
753
+ log(`${mode === 'precise_search' ? '✔' : '▲'} MPC mode=${mode}(modelReady 升档判定)bestCandidate=${JSON.stringify(best)}`)
754
+ if (mode !== 'precise_search' || Object.keys(best).length === 0) throw new Error(`MPC 未进入 precise_search 或无推荐: ${mpc.text.slice(0, 240)}`)
755
+
756
+ // 推荐投用:经 optimization_explore 治理链(优化通道无 dcw 直写工具面 —— 设计如此)
757
+ const idToNode = Object.fromEntries(ctx.sceneControls.map(c => [c.id, c.nodeId]))
758
+ ctx.applied = []
759
+ for (const [specId, target] of Object.entries(best)) {
760
+ const nodeId = idToNode[specId]
761
+ if (!nodeId || !Number.isFinite(target)) continue
762
+ const cur = baseline[specId] ?? 0
763
+ const delta = target - cur
764
+ if (Math.abs(delta) < 1e-6) continue
765
+ const r = await invoke('optimization_explore', {
766
+ control_node_id: nodeId, target_node_id: ctx.daq['film-thickness'],
767
+ direction: delta >= 0 ? 'up' : 'down', step: Math.abs(delta), settle_seconds: 15,
768
+ hypothesis: `AML 模型推荐投用(precise_search, cost 最优候选): ${specId} ${cur.toFixed(2)}→${Number(target).toFixed(2)}`,
769
+ }, ctx.workerB, ctx.token)
770
+ ctx.applied.push({ specId, nodeId, from: cur, to: target, ok: !r.isError })
771
+ log(` 投用 ${specId}: ${cur.toFixed(2)} → ${Number(target).toFixed(2)} ${r.isError ? '被拒 ' + r.text.split('\n')[0].slice(0, 100) : '√(治理链直写)'}`)
772
+ }
773
+ if (ctx.applied.length === 0) {
774
+ // 推荐与基线一致 = 模型判定当前设定点即最优(探索终点已落在模型最优点上)。
775
+ // 这是 precise_search 的合法输出 —— 投用为空操作,后续复测验证膜厚保持在带内。
776
+ log(' 模型判定: 当前设定点即最优(推荐=基线),无需变更 —— 由复测确认带内保持')
777
+ }
778
+
779
+ log(' 等待 90s 工艺响应(settling)…')
780
+ await sleep(90_000)
781
+ const hAfter = await thicknessMean(ctx.token, ctx.daq['film-thickness'], 45)
782
+ ctx.round2 = { hBefore, hAfter, inBand: hAfter != null && Math.abs(hAfter - 50) <= 2 }
783
+ log(`${ctx.round2.inBand ? '✔' : '▲'} 模型式投用后膜厚: ${hBefore?.toFixed(2)} → ${hAfter?.toFixed(2)}μm(目标 50μm,带 [48,52])`)
784
+ })
785
+
786
+ /* ════════ S11 · 贝叶斯寻优(模型 surrogate + UCB) ════════ */
787
+ await stage('S11', 'twin_bayes_optimize:模型 surrogate + UCB 多轮收敛寻优', async () => {
788
+ // 新鲜快照(S10 投用 + 90s settling 已使上一快照过期)
789
+ await ensureDaqRunning()
790
+ const snapC = await invoke('twin_snapshot_create', { auto_daq: true, channel_id: ctx.channelB, phase: 'exploration' }, ctx.workerB, ctx.token)
791
+ if (snapC.isError) throw new Error(`快照失败: ${snapC.text.slice(0, 240)}`)
792
+ const snapshotC = (snapC.text.match(/snapshot_id:\s*([^\n]+)/) || [])[1]?.trim()
793
+ const dcwRes = await api('GET', '/api/workshop/dcw', undefined, ctx.token)
794
+ const nodes = dataOf(dcwRes)?.nodes ?? []
795
+ const valOf = nodeId => Number(nodes.find(n => n.id === nodeId)?.value ?? 0)
796
+ const baseline = {}
797
+ for (const c of ctx.sceneControls) baseline[c.id] = valOf(c.nodeId)
798
+ const bayes = await invoke('twin_bayes_optimize', {
799
+ snapshot_id: snapshotC,
800
+ baseline_controls: baseline,
801
+ rounds: 3,
802
+ candidates_per_round: 4,
803
+ horizon_steps: 4,
804
+ }, ctx.workerB, ctx.token)
805
+ writeFileSync(join(OUT_DIR, 'bayes-run.txt'), bayes.text)
806
+ const rounds = (bayes.text.match(/"rounds":\s*(\d+)/) || [])[1]
807
+ const evalCount = (bayes.text.match(/"candidatesEvaluated":\s*(\d+)/) || [])[1]
808
+ ctx.bayes = { rounds: Number(rounds), evaluated: Number(evalCount), ok: !bayes.isError }
809
+ log(`${bayes.isError ? '✘' : '✔'} 贝叶斯寻优: ${rounds} 轮 / 评估 ${evalCount} 候选 → ${OUT_DIR.replace(REPO + '/', '')}/bayes-run.txt`)
810
+ })
811
+
812
+ /* ════════ S12 · 透明度文档 ════════ */
813
+ await stage('S12', '生成透明度文档', async () => {
814
+ const okR1 = ctx.exploration?.inBand ? '✔ 入带' : '▲ 未入带'
815
+ const okR2 = ctx.round2?.inBand ? '✔ 入带' : '▲ 未入带'
816
+ const doc = [
817
+ `# 双模式闭环优化 · 实机透明度记录(探索式 → AML 模型式)`,
818
+ '',
819
+ `- 运行: ${RUN_ID} · 平台 ${AW_BASE}(home 隔离实例) · 模拟器 cast-film 预设(${process.env.SIM_BASE} 影子)`,
820
+ `- 产线 ${ctx.lineId} · 配方 ${ctx.recipeId} · 优化通道 \`${ctx.channelB}\`(aml_optimization) · 训练通道 \`${ctx.channelA}\`(hybrid_twin)`,
821
+ `- 模型 \`${ctx.modelId}\` · Twin Gate ${ctx.gatePassed ? '全过' : '未过'} · MPC mode=${ctx.mpc?.mode}`,
822
+ '',
823
+ `## 第一轮 · 探索式(optimization_explore 治理写入)`,
824
+ '',
825
+ `- 起点 ${ctx.exploration?.hStart?.toFixed?.(2)}μm → 终点 ${ctx.exploration?.hEnd?.toFixed?.(2)}μm ${okR1}(screw 150→${ctx.exploration?.screwEnd})`,
826
+ '- 每步 = 真实 DCW 写入(绑定鉴权/四层限界/60s 间隔/优化记录)+ settle + 目标均值回读 + 学习摘要;',
827
+ ' 探索记录落 optimization_explorations,写控动作全量入册 ops.log。',
828
+ '',
829
+ '```json',
830
+ JSON.stringify(ctx.exploration?.traj ?? [], null, 2).slice(0, 2600),
831
+ '```',
832
+ '',
833
+ `## 第二轮 · AML 模型式(precise_search + 治理投用)`,
834
+ '',
835
+ `- 投用前 ${ctx.round2?.hBefore?.toFixed?.(2)}μm → 投用后 ${ctx.round2?.hAfter?.toFixed?.(2)}μm ${okR2}`,
836
+ `- MPC 推荐: \`${JSON.stringify(ctx.mpc?.best)}\` → 投用 ${JSON.stringify(ctx.applied)}`,
837
+ `- 贝叶斯寻优: ${ctx.bayes?.rounds} 轮 / ${ctx.bayes?.evaluated} 候选(surrogate+UCB,recommendation-only)`,
838
+ '',
839
+ '## 门禁与治理链',
840
+ '',
841
+ '- 探索模式:孪生工具 fail-closed(EXPLORATION_MODE_NO_MODEL,已负向校验);',
842
+ '- 绑定:谱系一致 + Twin Gate 全过(12 判据)+ stage=shadow 才可 PATCH boundModelId;',
843
+ '- 模式切换:绑定即 optimizationMode exploration→aml,mpc_optimize 由 safe_small_step 升档 precise_search;',
844
+ '- 投用:推荐经 optimization_explore(dcw_control 全治理链)真实写入,VirtualTrial/MPC 恒 candidateExecuted=false。',
845
+ '',
846
+ '## 全程事件日志',
847
+ '',
848
+ '```text',
849
+ L.join('\n').slice(-60_000),
850
+ '```',
851
+ ].join('\n')
852
+ writeFileSync(DOC_PATH, doc)
853
+ log(`✔ 透明度文档: ${DOC_PATH}`)
854
+ })
855
+
856
+ log('')
857
+ log('ALL STAGES DONE ✔ 双模式闭环(探索式 + AML 模型式)全链路完成')