agentworkshop 0.7.40 → 0.7.44

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 (327) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/_nuxt/B8uy9iRW.js +1 -0
  3. package/.output/public/_nuxt/BGTYYQH-.js +1 -0
  4. package/.output/public/_nuxt/BUmHEJ77.js +2 -0
  5. package/.output/public/_nuxt/BY7YrV_D.js +1 -0
  6. package/.output/public/_nuxt/Bqcgz95s.js +18 -0
  7. package/.output/public/_nuxt/C7UlqPeD.js +1 -0
  8. package/.output/public/_nuxt/CTmDn-YP.js +1 -0
  9. package/.output/public/_nuxt/Cs8pVeVG.js +1 -0
  10. package/.output/public/_nuxt/{DcsCcxp4.js → D98NH8kG.js} +1 -1
  11. package/.output/public/_nuxt/DKySmNPI.js +14 -0
  12. package/.output/public/_nuxt/Di0NY_ht.js +1 -0
  13. package/.output/public/_nuxt/Du9v6qGB.js +1 -0
  14. package/.output/public/_nuxt/{C_iYD-EB.js → EHlEMRii.js} +1 -1
  15. package/.output/public/_nuxt/Eke1fs-U.js +1 -0
  16. package/.output/public/_nuxt/{DeJykBFf.js → H0BcqZtT.js} +1 -1
  17. package/.output/public/_nuxt/{C4oW1HsE.js → HSYEkkce.js} +1 -1
  18. package/.output/public/_nuxt/{DZshyNLa.js → IREZ1eC2.js} +1 -1
  19. package/.output/public/_nuxt/{D_OTvQza.js → J9oU00D1.js} +1 -1
  20. package/.output/public/_nuxt/OmpTerminalPanel.BxR5-lvi.css +1 -0
  21. package/.output/public/_nuxt/SSyAPaHc.js +1 -0
  22. package/.output/public/_nuxt/TownView.li4EMQxK.css +1 -0
  23. package/.output/public/_nuxt/VdLk4jLE2.js +1 -0
  24. package/.output/public/_nuxt/_id_.BhsXoEuk.css +1 -0
  25. package/.output/public/_nuxt/_id_.DQyj-WKN.css +1 -0
  26. package/.output/public/_nuxt/{_wsId_.B4WiqkIS.css → _wsId_.CTx-BlfF.css} +1 -1
  27. package/.output/public/_nuxt/aShsv_rG.js +19 -0
  28. package/.output/public/_nuxt/{yF0aYMF1.js → aesgXKSr.js} +3 -3
  29. package/.output/public/_nuxt/agents.B21nUEUX.css +1 -0
  30. package/.output/public/_nuxt/aml.ekTjxFkf.css +1 -0
  31. package/.output/public/_nuxt/builds/latest.json +1 -1
  32. package/.output/public/_nuxt/builds/meta/b5506ef0-f48e-4f14-a6c0-d65e505d0b09.json +1 -0
  33. package/.output/public/_nuxt/ca4TJ3Op.js +1 -0
  34. package/.output/public/_nuxt/channel-templates.DplM1pJ3.css +1 -0
  35. package/.output/public/_nuxt/daq.BdVmoIfe.css +1 -0
  36. package/.output/public/_nuxt/dcw.DCgyzpWV.css +1 -0
  37. package/.output/public/_nuxt/{default.J32SgqFY.css → default.Bh3L2HU8.css} +1 -1
  38. package/.output/public/_nuxt/lHAxdSsj.js +1 -0
  39. package/.output/public/_nuxt/pages.j9rzRocr.css +1 -0
  40. package/.output/public/_nuxt/plugins.DhiZbHU8.css +1 -0
  41. package/.output/public/_nuxt/settings.BRx9rIDg.css +1 -0
  42. package/.output/public/_nuxt/teams.BLlOPB_Z.css +1 -0
  43. package/.output/public/_nuxt/tokens.De8xzszn.css +1 -0
  44. package/.output/public/_nuxt/workshop.D1jFNkrn.css +1 -0
  45. package/.output/server/chunks/_/nitro.mjs +1058 -830
  46. package/.output/server/chunks/_/nitro.mjs.map +1 -1
  47. package/.output/server/chunks/build/{OmpTerminalPanel-Cu_s4i0A.mjs → OmpTerminalPanel-CVvxpsF7.mjs} +15 -15
  48. package/.output/server/chunks/build/{OmpTerminalPanel-Cu_s4i0A.mjs.map → OmpTerminalPanel-CVvxpsF7.mjs.map} +1 -1
  49. package/.output/server/chunks/build/{TownView-BuLAsmpR.mjs → TownView-CJ6IsDCc.mjs} +229 -228
  50. package/.output/server/chunks/build/{TownView-BuLAsmpR.mjs.map → TownView-CJ6IsDCc.mjs.map} +1 -1
  51. package/.output/server/chunks/build/{_id_-BU1wfOID.mjs → _id_-CVD_H0ir.mjs} +149 -147
  52. package/.output/server/chunks/build/_id_-CVD_H0ir.mjs.map +1 -0
  53. package/.output/server/chunks/build/{_id_-BYsEua57.mjs → _id_-CtxMb3qp.mjs} +47 -46
  54. package/.output/server/chunks/build/_id_-CtxMb3qp.mjs.map +1 -0
  55. package/.output/server/chunks/build/{_wsId_-BxlDcJHg.mjs → _wsId_-DpY3T-md.mjs} +516 -446
  56. package/.output/server/chunks/build/{_wsId_-BxlDcJHg.mjs.map → _wsId_-DpY3T-md.mjs.map} +1 -1
  57. package/.output/server/chunks/build/{agents-CLQqJF2y.mjs → agents-DsCkuXDV.mjs} +49 -46
  58. package/.output/server/chunks/build/agents-DsCkuXDV.mjs.map +1 -0
  59. package/.output/server/chunks/build/{aml-_7FdFL2p.mjs → aml-CT0xKGKI.mjs} +122 -105
  60. package/.output/server/chunks/build/aml-CT0xKGKI.mjs.map +1 -0
  61. package/.output/server/chunks/build/builtin-catalog-edpDcgfL.mjs +117 -0
  62. package/.output/server/chunks/build/builtin-catalog-edpDcgfL.mjs.map +1 -0
  63. package/.output/server/chunks/build/{channel-templates-p6SZNjlM.mjs → channel-templates-Dla9FbYa.mjs} +49 -37
  64. package/.output/server/chunks/build/channel-templates-Dla9FbYa.mjs.map +1 -0
  65. package/.output/server/chunks/build/{daq-cgyjKmJu.mjs → daq-DWWSKGAV.mjs} +95 -93
  66. package/.output/server/chunks/build/daq-DWWSKGAV.mjs.map +1 -0
  67. package/.output/server/chunks/build/{dcw-CoTxBlAZ.mjs → dcw-CT8k17_E.mjs} +46 -45
  68. package/.output/server/chunks/build/dcw-CT8k17_E.mjs.map +1 -0
  69. package/.output/server/chunks/build/{default-BE4r0FZN.mjs → default-D3525UFX.mjs} +16 -15
  70. package/.output/server/chunks/build/{default-BE4r0FZN.mjs.map → default-D3525UFX.mjs.map} +1 -1
  71. package/.output/server/chunks/build/{logs-BSOeZwwI.mjs → logs--dByNyhw.mjs} +2 -2
  72. package/.output/server/chunks/build/{logs-BSOeZwwI.mjs.map → logs--dByNyhw.mjs.map} +1 -1
  73. package/.output/server/chunks/build/{monitor-C0okQaXz.mjs → monitor-Dh2Kvaq5.mjs} +2 -2
  74. package/.output/server/chunks/build/{monitor-C0okQaXz.mjs.map → monitor-Dh2Kvaq5.mjs.map} +1 -1
  75. package/.output/server/chunks/build/{pages-DFxjn9Xa.mjs → pages-BHcSBM2D.mjs} +26 -20
  76. package/.output/server/chunks/build/pages-BHcSBM2D.mjs.map +1 -0
  77. package/.output/server/chunks/build/{plugins-lGlUr1lj.mjs → plugins-BNgIi61W.mjs} +23 -17
  78. package/.output/server/chunks/build/plugins-BNgIi61W.mjs.map +1 -0
  79. package/.output/server/chunks/build/{settings-Ddd1qx2Z.mjs → settings-ipYBDWdn.mjs} +45 -44
  80. package/.output/server/chunks/build/settings-ipYBDWdn.mjs.map +1 -0
  81. package/.output/server/chunks/build/{teams-MEDLZdMn.mjs → teams-5lx-CwFa.mjs} +47 -44
  82. package/.output/server/chunks/build/teams-5lx-CwFa.mjs.map +1 -0
  83. package/.output/server/chunks/build/{tokens-C7fTM5C2.mjs → tokens-q-IDT8Io.mjs} +73 -53
  84. package/.output/server/chunks/build/tokens-q-IDT8Io.mjs.map +1 -0
  85. package/.output/server/chunks/build/{town-qMPql9Se.mjs → town-QJWB5wng.mjs} +5 -4
  86. package/.output/server/chunks/build/town-QJWB5wng.mjs.map +1 -0
  87. package/.output/server/chunks/build/{useDaqStream-CIBaiGAl.mjs → useDaqStream-DfCFpb3p.mjs} +9 -3
  88. package/.output/server/chunks/build/useDaqStream-DfCFpb3p.mjs.map +1 -0
  89. package/.output/server/chunks/build/{useDcwStream-CBbiYnWe.mjs → useDcwStream-UPiX-3iO.mjs} +11 -2
  90. package/.output/server/chunks/build/useDcwStream-UPiX-3iO.mjs.map +1 -0
  91. package/.output/server/chunks/build/{workshop-BL5bhfs0.mjs → workshop-BIlCj_ZP.mjs} +45 -45
  92. package/.output/server/chunks/build/workshop-BIlCj_ZP.mjs.map +1 -0
  93. package/.output/server/chunks/routes/api/workshop/channel-templates/_id/instantiate.post.mjs +1 -1
  94. package/.output/server/chunks/routes/api/workshop/channels.post.mjs +3 -3
  95. package/.output/server/chunks/routes/api/workshop/dcw/index5.post.mjs +1 -1
  96. package/.output/server/chunks/routes/api/workshop/dcw/lines/_id/start.post.mjs +1 -1
  97. package/.output/server/chunks/routes/api/workshop/dcw/lines/_id/stop.post.mjs +1 -1
  98. package/.output/server/chunks/routes/api/workshop/dcw/params/_id_.delete.mjs +1 -1
  99. package/.output/server/chunks/routes/api/workshop/dcw/params/_id_.patch.mjs +1 -1
  100. package/.output/server/chunks/routes/api/workshop/dcw/templates/_key_.delete.mjs +1 -1
  101. package/.output/server/chunks/routes/api/workshop/dcw/templates/_key_.patch.mjs +1 -1
  102. package/.output/server/chunks/routes/api/workshop/harnesses/_id/providers.get.mjs +1 -1
  103. package/.output/server/chunks/routes/api/workshop/harnesses.get.mjs +1 -1
  104. package/.output/server/chunks/routes/api/workshop/hitl/pending.get.mjs +1 -1
  105. package/.output/server/chunks/routes/api/workshop/hitl/respond.post.mjs +1 -1
  106. package/.output/server/chunks/routes/api/workshop/index.put.mjs +1 -1
  107. package/.output/server/chunks/routes/api/workshop/index5.get.mjs +3 -1
  108. package/.output/server/chunks/routes/api/workshop/index5.get.mjs.map +1 -1
  109. package/.output/server/chunks/routes/api/workshop/index6.get.mjs +3 -1
  110. package/.output/server/chunks/routes/api/workshop/index6.get.mjs.map +1 -1
  111. package/.output/server/chunks/routes/api/workshop/plugins/_name/disable.post.mjs +1 -1
  112. package/.output/server/chunks/routes/api/workshop/plugins/_name/enable.post.mjs +1 -1
  113. package/.output/server/chunks/routes/api/workshop/scene/layouts/_channelId_.delete.mjs +1 -1
  114. package/.output/server/chunks/routes/api/workshop/scene/layouts/_channelId_.put.mjs +1 -1
  115. package/.output/server/chunks/routes/api/workshop/workspaces/_id/channel-templates/_tplId_.post.mjs +1 -1
  116. package/.output/server/chunks/routes/renderer.mjs +2 -2
  117. package/.output/server/chunks/virtual/entry.mjs +639 -88
  118. package/.output/server/chunks/virtual/entry.mjs.map +1 -1
  119. package/.output/server/chunks/virtual/precomputed.mjs +1 -1
  120. package/.output/server/package.json +1 -1
  121. package/README-zh.md +16 -6
  122. package/README.md +17 -7
  123. package/app/components/AppHeader.vue +961 -959
  124. package/app/components/workshop/A2aRpcDebugger.vue +237 -237
  125. package/app/components/workshop/AgentInspectorDrawer.vue +424 -424
  126. package/app/components/workshop/AgentLanesView.vue +998 -998
  127. package/app/components/workshop/ArtifactCard.vue +120 -120
  128. package/app/components/workshop/AssetLibrary.vue +452 -452
  129. package/app/components/workshop/ChannelSessionList.vue +812 -804
  130. package/app/components/workshop/CommandPalette.vue +269 -269
  131. package/app/components/workshop/Composer.vue +827 -827
  132. package/app/components/workshop/DeviceTwinPanel.vue +643 -643
  133. package/app/components/workshop/EventBlock.vue +602 -602
  134. package/app/components/workshop/FileSelectorModal.vue +188 -188
  135. package/app/components/workshop/InspectorPanel.vue +301 -301
  136. package/app/components/workshop/MemoryPanel.vue +364 -364
  137. package/app/components/workshop/MultiChannelView.vue +189 -189
  138. package/app/components/workshop/TaskBoardView.vue +686 -686
  139. package/app/components/workshop/TaskInspectorDrawer.vue +390 -390
  140. package/app/components/workshop/TranscriptTimeline.vue +601 -601
  141. package/app/components/workshop/blocks/ClusterArtifact.vue +61 -61
  142. package/app/components/workshop/blocks/ClusterError.vue +85 -85
  143. package/app/components/workshop/blocks/ClusterLife.vue +87 -87
  144. package/app/components/workshop/blocks/ClusterMember.vue +95 -93
  145. package/app/components/workshop/blocks/ClusterMemory.vue +84 -84
  146. package/app/components/workshop/blocks/ClusterOther.vue +67 -67
  147. package/app/components/workshop/blocks/ClusterStatus.vue +149 -147
  148. package/app/components/workshop/blocks/ClusterTool.vue +158 -158
  149. package/app/components/workshop/terminal/OmpTerminalPanel.vue +1011 -1011
  150. package/app/components/workshop/town/TownView.vue +56 -56
  151. package/app/composables/workshop/useDaqStream.ts +7 -4
  152. package/app/composables/workshop/useDcwStream.ts +8 -2
  153. package/app/middleware/locale-cookie.global.ts +22 -0
  154. package/app/pages/aml/index.vue +24 -2
  155. package/app/pages/daq/[id].vue +20 -16
  156. package/app/pages/daq/index.vue +2310 -2307
  157. package/app/pages/dcw/[id].vue +26 -23
  158. package/app/pages/dcw/index.vue +3 -3
  159. package/app/pages/index.vue +987 -981
  160. package/app/pages/plugins/index.vue +317 -311
  161. package/app/pages/settings.vue +1564 -1562
  162. package/app/pages/tokens.vue +15 -15
  163. package/app/pages/workshop/agents.vue +612 -609
  164. package/app/pages/workshop/channel-templates.vue +18 -11
  165. package/app/pages/workshop/index.vue +668 -668
  166. package/app/pages/workshop/teams.vue +743 -740
  167. package/app/pages/workshop/w/[wsId].vue +704 -704
  168. package/app/plugins/locale-restore.client.ts +16 -1
  169. package/app/utils/builtin-catalog.ts +104 -0
  170. package/config.yml +170 -170
  171. package/docs/cli.en.md +2 -2
  172. package/docs/cli.md +2 -2
  173. package/docs/full-test-plan.md +2 -3
  174. package/docs/plugins.en.md +33 -1
  175. package/docs/plugins.md +29 -1
  176. package/docs/sdk.en.md +1 -1
  177. package/docs/sdk.md +1 -1
  178. package/i18n/locales/en.ts +293 -35
  179. package/i18n/locales/zh-CN.ts +265 -7
  180. package/package.json +4 -3
  181. package/scripts/_dbg-perms-e2e.mjs +132 -109
  182. package/scripts/_demo-agentteam-capture.mjs +278 -0
  183. package/scripts/_e2e-ui-functional.mjs +371 -0
  184. package/scripts/_i18n-en-cjk-scan.mjs +28 -0
  185. package/scripts/_i18n-en-verify.mjs +107 -0
  186. package/scripts/_i18n-extra-checks.mjs +53 -0
  187. package/scripts/_i18n-scan-hardcoded.mjs +180 -0
  188. package/scripts/_i18n-verify-keys.mjs +50 -0
  189. package/scripts/_loop-biax-campaign.mjs +130 -0
  190. package/scripts/_sweep-button-contrast.mjs +87 -0
  191. package/scripts/test-serial-bridge.mjs +418 -0
  192. package/scripts/ui/e2e-interactive.mjs +328 -0
  193. package/scripts/ui/record-demo.mjs +557 -0
  194. package/scripts/ui/seed-industrial-demo.mjs +171 -0
  195. package/server/api/workshop/daq/index.get.ts +3 -1
  196. package/server/api/workshop/dcw/index.get.ts +3 -0
  197. package/server/plugins/aw-plugins.ts +9 -7
  198. package/server/plugins-builtin/diag-bridge/index.mjs +608 -661
  199. package/server/plugins-builtin/rag-bridge/index.mjs +57 -133
  200. package/server/plugins-builtin/serial-bridge/client.mjs +210 -0
  201. package/server/plugins-builtin/serial-bridge/drivers.mjs +409 -0
  202. package/server/plugins-builtin/serial-bridge/i18n.json +62 -0
  203. package/server/plugins-builtin/serial-bridge/index.mjs +247 -0
  204. package/server/plugins-builtin/serial-bridge/lib.mjs +208 -0
  205. package/server/plugins-builtin/serial-bridge/rtu.mjs +168 -0
  206. package/server/services/workshop/daq/daq-controller.ts +7 -2
  207. package/server/services/workshop/daq/drivers.ts +89 -3
  208. package/server/services/workshop/dcw/dcw-controller.ts +5 -1
  209. package/server/services/workshop/dcw/drivers.ts +85 -2
  210. package/server/services/workshop/dcw/plugin-bridge.ts +45 -0
  211. package/server/services/workshop/plugins/host.mjs +30 -0
  212. package/shared/daq-protocol.ts +15 -0
  213. package/.output/public/_nuxt/88GOowgO2.js +0 -1
  214. package/.output/public/_nuxt/BOt2SP4z.js +0 -1
  215. package/.output/public/_nuxt/BP-NyKVG.js +0 -18
  216. package/.output/public/_nuxt/BXxH0UQE.js +0 -1
  217. package/.output/public/_nuxt/BsROmY89.js +0 -1
  218. package/.output/public/_nuxt/ClILjvWH.js +0 -1
  219. package/.output/public/_nuxt/CzOCSGLe.js +0 -1
  220. package/.output/public/_nuxt/D8qvkfyY.js +0 -1
  221. package/.output/public/_nuxt/DCn7QZ5N.js +0 -2
  222. package/.output/public/_nuxt/DS8qj8EL.js +0 -1
  223. package/.output/public/_nuxt/DUjW5Yq5.js +0 -1
  224. package/.output/public/_nuxt/Dihnimlk.js +0 -19
  225. package/.output/public/_nuxt/Dqw1lpr-.js +0 -1
  226. package/.output/public/_nuxt/Dr9v6C0f.js +0 -14
  227. package/.output/public/_nuxt/Du9ZJtnj.js +0 -1
  228. package/.output/public/_nuxt/OmpTerminalPanel.B_Pl5Ynm.css +0 -1
  229. package/.output/public/_nuxt/TownView.f-YOdXRs.css +0 -1
  230. package/.output/public/_nuxt/_id_.CM4bIgKY.css +0 -1
  231. package/.output/public/_nuxt/_id_.bNV69Dtf.css +0 -1
  232. package/.output/public/_nuxt/agents.ZD0rVdHE.css +0 -1
  233. package/.output/public/_nuxt/aml.BN8ZEW4h.css +0 -1
  234. package/.output/public/_nuxt/builds/meta/f4707884-7cf4-4a31-80d2-e3d72b73745f.json +0 -1
  235. package/.output/public/_nuxt/channel-templates.BOtahzPi.css +0 -1
  236. package/.output/public/_nuxt/daq.B0D3dPAc.css +0 -1
  237. package/.output/public/_nuxt/dcw.8Y7FqCVN.css +0 -1
  238. package/.output/public/_nuxt/pages.D7aSDlUI.css +0 -1
  239. package/.output/public/_nuxt/plugins.sb4nDGqr.css +0 -1
  240. package/.output/public/_nuxt/qr6R6Ha1.js +0 -1
  241. package/.output/public/_nuxt/settings.BTgR-NiE.css +0 -1
  242. package/.output/public/_nuxt/teams.CxnxKVVs.css +0 -1
  243. package/.output/public/_nuxt/tokens.BFY7qv4f.css +0 -1
  244. package/.output/public/_nuxt/workshop.CR_QzeAN.css +0 -1
  245. package/.output/server/chunks/build/_id_-BU1wfOID.mjs.map +0 -1
  246. package/.output/server/chunks/build/_id_-BYsEua57.mjs.map +0 -1
  247. package/.output/server/chunks/build/agents-CLQqJF2y.mjs.map +0 -1
  248. package/.output/server/chunks/build/aml-_7FdFL2p.mjs.map +0 -1
  249. package/.output/server/chunks/build/channel-templates-p6SZNjlM.mjs.map +0 -1
  250. package/.output/server/chunks/build/daq-cgyjKmJu.mjs.map +0 -1
  251. package/.output/server/chunks/build/dcw-CoTxBlAZ.mjs.map +0 -1
  252. package/.output/server/chunks/build/pages-DFxjn9Xa.mjs.map +0 -1
  253. package/.output/server/chunks/build/plugins-lGlUr1lj.mjs.map +0 -1
  254. package/.output/server/chunks/build/settings-Ddd1qx2Z.mjs.map +0 -1
  255. package/.output/server/chunks/build/teams-MEDLZdMn.mjs.map +0 -1
  256. package/.output/server/chunks/build/tokens-C7fTM5C2.mjs.map +0 -1
  257. package/.output/server/chunks/build/town-qMPql9Se.mjs.map +0 -1
  258. package/.output/server/chunks/build/useDaqStream-CIBaiGAl.mjs.map +0 -1
  259. package/.output/server/chunks/build/useDcwStream-CBbiYnWe.mjs.map +0 -1
  260. package/.output/server/chunks/build/workshop-BL5bhfs0.mjs.map +0 -1
  261. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.continue.json +0 -1
  262. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.json +0 -1
  263. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/054bb4bc4e4217a2ab0b0c6b663747214a9af464f5568ea60e784704e340bb0f.source +0 -153
  264. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/0554197c3d2bac203a1f5c48a5d52495d1336db1bd7aa4f4c19875810363e684.source +0 -153
  265. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/05c203d12a954fffba942e1d626e3f5fec05b18a5aef2bac003b7884a4b77406.source +0 -431
  266. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/145a6e6ba811af35aed31e0cc3211f53706a14980fa069ee9e3c1591139f96f0.source +0 -180
  267. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/1ae0fb281f97899c025e368ca73f41349b01fb5f85b19e08d7ebccff49095ed5.source +0 -112
  268. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/20ee9967aa0541c516db7575bdd4a1a745939bc7016bd10d7635903113edb8ec.source +0 -227
  269. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/233751843aeba9d4c5263f275b8102de00443c06f286918cbd23e0b6729e01aa.source +0 -131
  270. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/263c2e05b425e5c322e60c6475279f963bab3a873eb521b21df7fec935a46597.source +0 -160
  271. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/2ac5eaac28eaaee2178c4b32014df8e732f9dd432a285a872f5b7f31c1395fa4.source +0 -157
  272. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/33a0db0d2d95d2c11d0720090458e5fba1425376f5ceb5b422d1d3471be3226b.source +0 -348
  273. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/359e474ae83db35e4615d3728de6bf694b64d4dce9b536730a3b6518f9c0494a.source +0 -296
  274. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/37a4c3c31c4b70f6b719c53d1e9c4fcba603f31adfdd11bb6ef9f0d094923c56.source +0 -285
  275. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/461feca1c14a695eb8b0f17a6f95fe97eeceabc0510faaea4ba6d25bde147d8d.source +0 -217
  276. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/4cfadbda8591f29d5e1e230dc000e701b756e850441b3900fb596a4d2f6e98c2.source +0 -301
  277. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/50ca2810cf0b248c96948994c0c404531bbad6e553166b6816b3b03bfa0f75d2.source +0 -151
  278. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/52d9e8cb591a9ae86e238c3620a610cd386717bee222c0f37b25b2ac7e523dc4.source +0 -135
  279. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/6c87daafa4c006560a954636a97333f6123153c9d34d96203f7ee3a14e556357.source +0 -156
  280. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/77bc47854b577900621cacf1697f81fa2bc005af129d37614a97a3441c08f99f.source +0 -72
  281. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/7bbb789d3a527817118cf8399ed1861d6a962ade10878fd07223435d333a7089.source +0 -469
  282. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/86b7c1daafc8b60ba9982dde5bf1bcc74265709483c176e71f23ec6fc267451f.source +0 -259
  283. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/8df66d62bd41984d0970e8236882080c5085ac937d07a29779463d6a03b37c76.source +0 -97
  284. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/9962f2d1b3a85137bd40cc835725600b39f89ee02a27c06b2e0402e1eafde115.source +0 -277
  285. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/a1090ea066b792cb201739f4994e37bf7c12f52e805239a1eab87f18a537f266.source +0 -171
  286. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/a5241091650134d0919897e086a606a3846c8b2b54f8b4c84a8696c145ac3e9e.source +0 -425
  287. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/af19fa4c6e34d5540028be4b17600161283af3a2a2dfc61a3fdc0834436a0c14.source +0 -99
  288. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/b3713d78e2b2f93905ff6be8d58a8d0a2f42dea322eb67c987fda22ff6a084d5.source +0 -325
  289. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/b3849943c3aff102d1af815631fc843a2a52c17646a4b04696ece323e483bbec.source +0 -332
  290. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/bac735a3803a6650b7f1eb8f587e6dc5c68ea055000c3c99a11789438b78e837.source +0 -43
  291. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/d32c24d61eb8b33c73e5a8fc7e4dc7ef437aed238ee4371c2b00617e6104090a.source +0 -154
  292. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/d5170dc9a9879fda04fdf91d8a110d4efb6787ee38dda596d4da899883d36a72.source +0 -531
  293. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/dc59bcd7bb397be63ba2f2c3fec23f3782dcb17d2d75a9981eeced761f33eb32.source +0 -439
  294. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/eb5ff8cf66b92aec7bf6726781d8df74faa2b030c3aaac17d6b00c1fc04c9b32.source +0 -323
  295. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/f10615a6fae18436e70d1201b2d44fdae3174a3aa7bb4db97dea1b3ed291d721.source +0 -433
  296. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/f36d3e271668bc1260c2823542d22dbf1d0f7041ff16b1ac175bce2256e582ca.source +0 -280
  297. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/f94449380af09f31ac352152007146a75cc80bae8d6411ffe57b2c56f933b0ff.source +0 -117
  298. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/fe4dfd81178fd6b648335f6405d9ede71319aebde796008e50db21f8adf44c99.source +0 -160
  299. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/ffb4e3aa548cfdadabaa44ab599f9b6a3ca6288176a2cc7a4b2fc2a12b5fb848.source +0 -101
  300. package/scripts/.mimosa/hook-status/sess_aeaecb58-8833-4b83-b93c-050467d21e03-d944d71bb3.json +0 -14
  301. package/scripts/_dbg-audit-all-pages.mjs +0 -43
  302. package/scripts/_dbg-daq-frames-e2e.mjs +0 -118
  303. package/scripts/_dbg-daq-rowstyle-verify.mjs +0 -112
  304. package/scripts/_dbg-hitl-timeout-e2e.mjs +0 -93
  305. package/scripts/_dbg-live-line-e2e.mjs +0 -279
  306. package/scripts/_dbg-minimal-omp.mjs +0 -77
  307. package/scripts/_dbg-mode-nav.mjs +0 -173
  308. package/scripts/_dbg-real-scenario-timeline.log +0 -55
  309. package/scripts/_dbg-team-repro.mjs +0 -76
  310. package/scripts/_dbg-town-agents-probe.mjs +0 -60
  311. package/scripts/_dbg-visual-acceptance.mjs +0 -63
  312. package/scripts/_townview_style.css +0 -1185
  313. package/scripts/_townview_template.html +0 -1215
  314. package/server/data/agent-node-bindings.json +0 -554
  315. package/server/data/daq-templates.json +0 -16
  316. package/server/data/daqs.json +0 -7464
  317. package/server/data/dcw-lines.json +0 -1787
  318. package/server/data/dcw-products.json +0 -1626
  319. package/server/data/dcw-recipes.json +0 -4672
  320. package/server/data/dcw-rollback.json +0 -20754
  321. package/server/data/dcw-runs.json +0 -6354
  322. package/server/data/dcw-templates.json +0 -146
  323. package/server/data/dcw-writes.json +0 -15650
  324. package/server/data/dcws.json +0 -9033
  325. package/server/data/device-twins.json +0 -133
  326. package/server/data/line-runs.json +0 -322
  327. package/server/data/scene-layouts.json +0 -277
@@ -0,0 +1,180 @@
1
+ // Scan .vue/.ts files for hardcoded Chinese text that renders in UI (not comments).
2
+ // v3: single-pass state machine masks comments (// /* */ <!-- -->) while preserving strings.
3
+ import { readFileSync, readdirSync, statSync } from 'node:fs'
4
+ import { join, relative } from 'node:path'
5
+
6
+ const ROOTS = [join(process.cwd(), 'app')]
7
+ const CJK = /[\u4e00-\u9fff\u3400-\u4dbf]/
8
+
9
+ function walk(dir, out = []) {
10
+ for (const name of readdirSync(dir)) {
11
+ const p = join(dir, name)
12
+ const st = statSync(p)
13
+ if (st.isDirectory()) walk(p, out)
14
+ else if (name.endsWith('.vue') || name.endsWith('.ts')) out.push(p)
15
+ }
16
+ return out
17
+ }
18
+
19
+ // Mask comments with spaces, keep newlines, keep string literals intact.
20
+ function maskComments(src) {
21
+ const out = src.split('')
22
+ let i = 0
23
+ const n = src.length
24
+ let state = 'code' // code | line | block | html | squote | dquote | backtick
25
+ const set = (from, to) => {
26
+ for (let k = from; k < to; k++) {
27
+ if (src[k] !== '\n') out[k] = ' '
28
+ }
29
+ }
30
+ const skipLineComment = () => {
31
+ const j = src.indexOf('\n', i)
32
+ const e = j === -1 ? n : j
33
+ set(i, e)
34
+ i = e
35
+ }
36
+ const skipTo = (needle, from, pad) => {
37
+ const j = src.indexOf(needle, from)
38
+ const e = j === -1 ? n : j + pad
39
+ set(i, e)
40
+ i = e
41
+ }
42
+ while (i < n) {
43
+ const c = src[i]
44
+ const d = src[i + 1]
45
+ if (state === 'code') {
46
+ if (c === '/' && d === '/') {
47
+ skipLineComment()
48
+ continue
49
+ }
50
+ if (c === '/' && d === '*') {
51
+ skipTo('*/', i + 2, 2)
52
+ state = 'code'
53
+ continue
54
+ }
55
+ if (c === '<' && d === '!' && src.slice(i, i + 4) === '<!--') {
56
+ skipTo('-->', i + 4, 3)
57
+ continue
58
+ }
59
+ if (c === '\'') {
60
+ state = 'squote'
61
+ i++
62
+ continue
63
+ }
64
+ if (c === '"') {
65
+ state = 'dquote'
66
+ i++
67
+ continue
68
+ }
69
+ if (c === '`') {
70
+ state = 'backtick'
71
+ i++
72
+ continue
73
+ }
74
+ i++
75
+ continue
76
+ }
77
+ if (state === 'line') {
78
+ i = src.indexOf('\n', i)
79
+ if (i === -1) i = n
80
+ state = 'code'
81
+ continue
82
+ }
83
+ if (state === 'block') {
84
+ const j = src.indexOf('*/', i)
85
+ if (j === -1) {
86
+ i = n
87
+ }
88
+ else {
89
+ i = j + 2
90
+ state = 'code'
91
+ }
92
+ continue
93
+ }
94
+ if (state === 'html') {
95
+ const j = src.indexOf('-->', i)
96
+ if (j === -1) {
97
+ i = n
98
+ }
99
+ else {
100
+ i = j + 3
101
+ state = 'code'
102
+ }
103
+ continue
104
+ }
105
+ // strings: skip escaped chars, exit on close quote (no comment masking inside strings)
106
+ if (state === 'squote' || state === 'dquote') {
107
+ if (c === '\\') {
108
+ i += 2
109
+ continue
110
+ }
111
+ if ((state === 'squote' && c === '\'') || (state === 'dquote' && c === '"')) state = 'code'
112
+ i++
113
+ continue
114
+ }
115
+ if (state === 'backtick') {
116
+ if (c === '\\') {
117
+ i += 2
118
+ continue
119
+ }
120
+ if (c === '`') state = 'code'
121
+ i++
122
+ continue
123
+ }
124
+ }
125
+ return out.join('')
126
+ }
127
+
128
+ const results = []
129
+ for (const ROOT of ROOTS) {
130
+ for (const file of walk(ROOT)) {
131
+ const src = readFileSync(file, 'utf8')
132
+ const masked = maskComments(src)
133
+ const lines = masked.split('\n')
134
+ const origLines = src.split('\n')
135
+ const rel = relative(process.cwd(), file).replace(/\\/g, '/')
136
+
137
+ const templateStart = masked.indexOf('<template')
138
+ const templateEnd = masked.lastIndexOf('</template>')
139
+ const scriptMatch = /<script[^>]*>/.exec(masked)
140
+ const scriptStart = scriptMatch ? scriptMatch.index : -1
141
+ const scriptEnd = masked.lastIndexOf('</script>')
142
+
143
+ const charStartOf = (lineIdx0) => {
144
+ let acc = 0
145
+ for (let i = 0; i < lineIdx0; i++) acc += lines[i].length + 1
146
+ return acc
147
+ }
148
+
149
+ const findings = []
150
+ lines.forEach((line, i) => {
151
+ if (!CJK.test(line)) return
152
+ const charStart = charStartOf(i)
153
+ let cat
154
+ if (templateStart >= 0 && charStart >= templateStart && charStart <= templateEnd + 11) {
155
+ const withoutT = line.replace(/\{\{\s*[^{}]*?\}\}/g, m => (/\$?t\s*\(/.test(m) && !CJK.test(m.replace(/\$?t\s*\([^)]*\)/g, '')) ? '' : m))
156
+ if (!CJK.test(withoutT)) return
157
+ cat = /[a-zA-Z-]+\s*=\s*"[^"]*[\u4e00-\u9fff]/.test(line) ? 'template-attr' : 'template-text'
158
+ }
159
+ else if (scriptStart >= 0 && charStart >= scriptStart && charStart <= scriptEnd + 9) {
160
+ const withoutT = line.replace(/\b(?:t|tt|\$t|i18n\.t)\(\s*['"`][^'"`]*['"`][^)]*\)/g, '')
161
+ if (!CJK.test(withoutT)) return
162
+ cat = 'script-literal'
163
+ }
164
+ else {
165
+ return
166
+ }
167
+ findings.push({ line: i + 1, cat, text: origLines[i].trim().slice(0, 200) })
168
+ })
169
+
170
+ if (findings.length) results.push({ file: rel, findings })
171
+ }
172
+ }
173
+
174
+ let total = 0
175
+ for (const r of results) {
176
+ total += r.findings.length
177
+ console.log(`\n=== ${r.file} (${r.findings.length}) ===`)
178
+ for (const f of r.findings) console.log(` L${f.line} [${f.cat}] ${f.text}`)
179
+ }
180
+ console.log(`\n\nTOTAL suspect lines: ${total} in ${results.length} files`)
@@ -0,0 +1,50 @@
1
+ // Verify locale files: parse, key parity, and every used t() key resolves in both locales.
2
+ import { readFileSync, readdirSync, statSync, copyFileSync, mkdtempSync } from 'node:fs'
3
+ import { join } from 'node:path'
4
+ import { tmpdir } from 'node:os'
5
+ import { pathToFileURL } from 'node:url'
6
+
7
+ // 1. Parse both locale files as ESM by copying to temp .mjs
8
+ const tmp = mkdtempSync(join(tmpdir(), 'aw-i18n-'))
9
+ const zhPath = join(tmp, 'zh.mjs')
10
+ const enPath = join(tmp, 'en.mjs')
11
+ copyFileSync('i18n/locales/zh-CN.ts', zhPath)
12
+ copyFileSync('i18n/locales/en.ts', enPath)
13
+
14
+ const zh = (await import(pathToFileURL(zhPath).href)).default
15
+ const en = (await import(pathToFileURL(enPath).href)).default
16
+
17
+ const flat = (o, p = '') => Object.entries(o).flatMap(([k, v]) => (typeof v === 'object' && v !== null ? flat(v, p + k + '.') : [p + k]))
18
+ const zhKeys = new Set(flat(zh))
19
+ const enKeys = new Set(flat(en))
20
+ console.log('zh keys:', zhKeys.size, '/ en keys:', enKeys.size)
21
+ const missEn = [...zhKeys].filter(k => !enKeys.has(k))
22
+ const missZh = [...enKeys].filter(k => !zhKeys.has(k))
23
+ if (missEn.length) console.log('IN ZH MISSING EN:', missEn)
24
+ if (missZh.length) console.log('IN EN MISSING ZH:', missZh)
25
+
26
+ // 2. Every used t()/$t() key in app/ must exist in both
27
+ function walk(dir, out = []) {
28
+ for (const name of readdirSync(dir)) {
29
+ const p = join(dir, name)
30
+ const st = statSync(p)
31
+ if (st.isDirectory()) walk(p, out)
32
+ else if (/\.(vue|ts)$/.test(name)) out.push(p)
33
+ }
34
+ return out
35
+ }
36
+ const used = new Set()
37
+ const useRe = /(?:[.$]t|\bt)\(\s*['"]([a-zA-Z0-9_.]+)['"]/g
38
+ for (const f of walk('app')) {
39
+ const src = readFileSync(f, 'utf8')
40
+ for (const m of src.matchAll(useRe)) used.add(m[1])
41
+ }
42
+ const missing = [...used].filter(k => !zhKeys.has(k) || !enKeys.has(k))
43
+ console.log('used keys:', used.size, '/ unresolved:', missing.length)
44
+ if (missing.length) {
45
+ console.log(missing.map((k) => {
46
+ const inZh = zhKeys.has(k), inEn = enKeys.has(k)
47
+ return ` ${k} zh:${inZh ? 'Y' : 'N'} en:${inEn ? 'Y' : 'N'}`
48
+ }).join('\n'))
49
+ }
50
+ console.log(missEn.length + missZh.length + missing.length === 0 ? 'PARITY OK' : 'PARITY FAIL')
@@ -0,0 +1,130 @@
1
+ /**
2
+ * 双拉任务确定性 campaign —— R11 Major-1 的实验落地:
3
+ * 固定模拟器状态(plantReset warm)+ 固定 commit + 固定配方,连续执行 N=30 次
4
+ * AgentTeam 双拉闭环任务,记录每次入带结果,给出入带率的 Wilson 95% CI。
5
+ * 预注册判据:入带 = |最终厚度 − 25.0| ≤ 0.7 µm;每次写后等待 ≥12s 运输滞后。
6
+ * 运行: AW_BASE=http://127.0.0.1:3005 NO_PROXY=127.0.0.1,localhost node scripts/_loop-biax-campaign.mjs [N]
7
+ */
8
+ import { writeFileSync, mkdirSync } from 'node:fs'
9
+ import { join, resolve, dirname } from 'node:path'
10
+ import { fileURLToPath, pathToFileURL } from 'node:url'
11
+
12
+ const HERE = dirname(fileURLToPath(import.meta.url))
13
+ const REPO = resolve(HERE, '..')
14
+ const N = Number(process.argv[2] ?? 30)
15
+ const BASE = process.env.AW_BASE ?? 'http://127.0.0.1:3005'
16
+ const OUT = join(REPO, 'bench', 'results', 'biax-campaign')
17
+ const SIM = process.env.E2E_SIM_API ?? 'http://127.0.0.1:4010'
18
+ const fetchRetry = async (url, opts = {}, tries = 8) => {
19
+ let lastErr
20
+ for (let i = 1; i <= tries; i++) {
21
+ try {
22
+ return await fetch(url, { ...opts, signal: AbortSignal.timeout(20000) })
23
+ }
24
+ catch (e) {
25
+ lastErr = e
26
+ await new Promise(r => setTimeout(r, Math.min(500 * 2 ** (i - 1), 6000)))
27
+ }
28
+ }
29
+ throw lastErr
30
+ }
31
+
32
+ mkdirSync(OUT, { recursive: true })
33
+
34
+ const sleep = ms => new Promise(r => setTimeout(r, ms))
35
+
36
+ const login = await (await fetch(BASE + '/api/users/login', {
37
+ method: 'POST', headers: { 'content-type': 'application/json' },
38
+ body: JSON.stringify({ email: 'admin@awshop.local', password: 'admin123' }),
39
+ })).json()
40
+ const H = { 'authorization': `Bearer ${login.data.token}`, 'content-type': 'application/json' }
41
+ const api = {
42
+ call: async (method, u, b) => (await fetch(BASE + u, { method, headers: H, body: b ? JSON.stringify(b) : undefined })).json(),
43
+ }
44
+
45
+ const { ensureSimulator, simUp, simNodes, plantReset } = await import(pathToFileURL(join(REPO, 'bench', 'lib', 'sim.mjs')).href)
46
+ const { provisionBiaxLine, runBiaxMission, ensureBiaxLine } = await import(pathToFileURL(join(REPO, 'bench', 'lib', 'biax.mjs')).href)
47
+
48
+ if (!(await simUp())) {
49
+ console.error('模拟器不可达:请先启动 plc-node-simulator (:4010)')
50
+ process.exit(1)
51
+ }
52
+ await ensureSimulator().catch(() => {})
53
+
54
+ const sfx = 'camp' + Date.now().toString(36).slice(-4)
55
+ // 平台夹具:channel + mock lead/worker(任务板剧本)+ opencode 绑定执行体
56
+ const ch = await api.call('POST', '/api/workshop/channels', { name: `biax-campaign-${sfx}`, leadAgent: { name: `clead-${sfx}`, harness: 'mock', config: { delayMs: 40 } } })
57
+ const channelId = ch.data?.channelId ?? ch.data?.channel?.id ?? ch.data?.id
58
+ const worker = await api.call('POST', '/api/workshop/agents', { name: `cworker-${sfx}`, harness: 'mock', config: { delayMs: 60 } })
59
+ await api.call('POST', `/api/workshop/channels/${channelId}/agents`, { agentId: worker.data?.id, role: 'worker' })
60
+ const agent = await api.call('POST', '/api/workshop/agents', { name: `cexec-${sfx}`, harness: 'opencode', config: {} })
61
+ const joinResp = await api.call('POST', `/api/workshop/channels/${channelId}/agents`, { agentId: agent.data?.id, role: 'worker' })
62
+ const instId = joinResp.data?.id ?? joinResp.data?.agentId
63
+ if (!instId) {
64
+ console.error('执行体创建失败')
65
+ process.exit(1)
66
+ }
67
+
68
+ const runs = []
69
+ const stateFile = join(OUT, 'campaign-state.json')
70
+ const save = () => writeFileSync(stateFile, JSON.stringify({ sfx, startedAt: new Date().toISOString(), runs }, null, 1))
71
+
72
+ console.log(`campaign start: N=${N} base=${BASE} sim=:4010`)
73
+ for (let k = 1; k <= N; k++) {
74
+ const t0 = Date.now()
75
+ // ① 固定模拟器状态(确定性根修:零随机漂移 + warm 标称)
76
+ await plantReset({ warm: true, disturbances: { heaterDecay: 1, feedDriftPerMin: 0 } })
77
+ await sleep(1500)
78
+ // ②.5 SP 归一化:崩塌任务会把 SP 写到量程外(实测 pump-sp=0 残留),起跑前统一设回
79
+ // 量程内 35% 位(确定性起点;任务只写铸速/快辊/轨宽三旋钮,其余 SP 仅作配方合法值)
80
+ {
81
+ const nodes = (await simNodes()).filter(n => n.id.startsWith('biax-'))
82
+ for (const dev of nodes) {
83
+ for (const sig of dev.signals ?? []) {
84
+ if (!/SP/i.test(sig.id) && !/SP/i.test(sig.name ?? '')) continue
85
+ const lo = sig.min ?? 0, hi = sig.max ?? 100
86
+ const v = Number(sig.value)
87
+ if (!Number.isFinite(v) || v < lo + 0.05 * (hi - lo)) {
88
+ const target = +(lo + 0.35 * (hi - lo)).toFixed(sig.decimals ?? 1)
89
+ await fetchRetry(SIM + '/api/nodes/' + dev.id + '/signals/' + encodeURIComponent(sig.id) + '/manual', { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ value: target }) }).catch(() => {})
90
+ }
91
+ }
92
+ }
93
+ await sleep(1200)
94
+ }
95
+
96
+ // ② 每轮独立布线(探测补建幂等;节点随 purge 回收)
97
+ const ensured = await ensureBiaxLine()
98
+ if (!ensured?.verified) throw new Error('ensureBiaxLine 失败')
99
+ const provisioned = await provisionBiaxLine(api, { sfx: sfx + k })
100
+ const line = provisioned
101
+ // ③ 绑定执行体到三个执行节点的 DCW
102
+ for (const nodeId of Object.values(line.dcw)) {
103
+ await api.call('POST', '/api/workshop/agent-tools/bindings', { agentId: instId, nodeId, kind: 'dcw', mode: 'auto' })
104
+ }
105
+ await sleep(2000)
106
+ // ④ 任务(含治理写与判定)
107
+ const mission = await runBiaxMission(api, { instId, line, simDevices: (await simNodes()).filter(n => n.id.startsWith('biax')), sfx: sfx + k, maxRounds: 6 })
108
+ if (k === 1 || !mission.attained) console.log('DIAG provErrors:', JSON.stringify(provisioned.errors ?? []), '| dcw:', Object.keys(line.dcw ?? {}).length, '| daq:', Object.keys(line.daq ?? {}).length, '| ids:', JSON.stringify(line.ids ?? {}))
109
+ const run = {
110
+ k, attained: mission.attained, thickness: mission.thickness,
111
+ writes: mission.writes, knobs: mission.distinctNodes.size, wallS: Math.round((Date.now() - t0) / 1000),
112
+ }
113
+ runs.push(run)
114
+ save()
115
+ console.log(`[${k}/${N}] attained=${run.attained} h=${run.thickness?.toFixed(2)}µm writes=${run.writes} wall=${run.wallS}s`)
116
+ // ⑤ 收尾:停线防批次泄漏
117
+ await api.call('POST', `/api/workshop/dcw/lines/${line.ids.line}/stop`, {}).catch(() => {})
118
+ await api.call('DELETE', `/api/workshop/dcw/lines/${line.ids.line}?purge=1`, {}).catch(() => {})
119
+ await sleep(2000)
120
+ }
121
+
122
+ const ok = runs.filter(r => r.attained).length
123
+ const n = runs.length
124
+ const p = ok / n
125
+ const z = 1.96
126
+ const ci = n ? [p - z * Math.sqrt((p * (1 - p)) / n), p + z * Math.sqrt((p * (1 - p)) / n)] : [0, 0]
127
+ const summary = { n, ok, rate: +p.toFixed(3), wilson95: ci.map(c => +c.toFixed(3)), runs }
128
+ writeFileSync(join(OUT, 'campaign-summary.json'), JSON.stringify(summary, null, 1))
129
+ console.log(`\n结果: ${ok}/${n} 入带,rate=${(p * 100).toFixed(1)}%,Wilson95=[${ci[0].toFixed(3)},${ci[1].toFixed(3)}]`)
130
+ console.log(`产物: ${OUT}`)
@@ -0,0 +1,87 @@
1
+ /** 全站按钮渲染扫描:双主题 × 全页面,检测 (a) 文字色≈背景色(隐形文本) (b) 无文字无图标的空按钮。 */
2
+ import { ensureVisualUser, launch, openPage, gotoReady, sleep, ROUTES } from './ui/lib.mjs'
3
+
4
+ const token = await ensureVisualUser()
5
+ const browser = await launch({ width: 1440, height: 900 })
6
+
7
+ const problems = []
8
+ for (const dark of [false, true]) {
9
+ const page = await openPage(browser, { token, dark, width: 1440, height: 900 })
10
+ await page.evaluateOnNewDocument(() => {
11
+ try {
12
+ localStorage.setItem('aw.locale', 'zh-CN')
13
+ }
14
+ catch { /* 忽略 */ }
15
+ })
16
+ for (const r of ROUTES) {
17
+ try {
18
+ await gotoReady(page, r.path, { wait: 2200 })
19
+ await sleep(600)
20
+ const found = await page.evaluate(() => {
21
+ const out = []
22
+ const parse = (c) => {
23
+ const m = c.match(/rgba?\(([\d.]+),\s*([\d.]+),\s*([\d.]+)(?:,\s*([\d.]+))?\)/)
24
+ if (!m) return null
25
+ return { c: [+m[1], +m[2], +m[3]], a: m[4] === undefined ? 1 : +m[4] }
26
+ }
27
+ const lum = (c) => {
28
+ const f = (v) => {
29
+ v /= 255
30
+ return v <= 0.03928 ? v / 12.92 : ((v + 0.055) / 1.055) ** 2.4
31
+ }
32
+ return 0.2126 * f(c[0]) + 0.7152 * f(c[1]) + 0.0722 * f(c[2])
33
+ }
34
+ const ratio = (a, b) => {
35
+ const l1 = lum(a), l2 = lum(b)
36
+ return (Math.max(l1, l2) + 0.05) / (Math.min(l1, l2) + 0.05)
37
+ }
38
+ const over = (fg, alpha, base) => fg.map((v, i) => Math.round(v * alpha + base[i] * (1 - alpha)))
39
+ const pageBg = getComputedStyle(document.body).backgroundColor
40
+ const pbNums = pageBg.match(/\d+/g)
41
+ const pb = pbNums?.map(Number) ?? [255, 255, 255]
42
+ for (const btn of document.querySelectorAll('button, .pill-btn, .ghost-btn, .mini-btn, a.pill-btn')) {
43
+ const r = btn.getBoundingClientRect()
44
+ if (r.width < 4 || r.height < 4) continue
45
+ if (btn.offsetParent === null && getComputedStyle(btn).position !== 'fixed') continue
46
+ const cs = getComputedStyle(btn)
47
+ const fg = parse(cs.color)
48
+ let bg = parse(cs.backgroundColor)
49
+ if (!fg) continue
50
+ // 逐层向上找不透明背景
51
+ let eff = bg && bg.a >= 0.95 ? bg.c : null
52
+ if (!eff) {
53
+ let el = btn
54
+ while (el && el !== document.documentElement) {
55
+ const c = parse(getComputedStyle(el).backgroundColor)
56
+ if (c && c.a >= 0.95) {
57
+ eff = c.c
58
+ break
59
+ }
60
+ el = el.parentElement
61
+ }
62
+ if (!eff) eff = pb
63
+ }
64
+ if (bg && bg.a < 0.95 && bg.a > 0) eff = over(bg.c, bg.a, eff)
65
+ const cr = ratio(fg.c, eff)
66
+ const label = (btn.innerText ?? '').replace(/\s+/g, ' ').trim()
67
+
68
+ const hasIcon = btn.querySelector('span[class*="i-"], svg') !== null
69
+ const isSwitch = /switch/i.test(btn.className) || btn.getAttribute('role') === 'switch'
70
+ if (isSwitch) continue
71
+ if (cr < 1.35) out.push({ kind: 'low-contrast', cr: cr.toFixed(2), label: label.slice(0, 30), cls: btn.className.slice(0, 50), color: cs.color, bg: cs.backgroundColor })
72
+ else if (!label && !hasIcon && !btn.getAttribute('aria-label') && !btn.getAttribute('title')) out.push({ kind: 'empty-button', label: '(no text)', cls: btn.className.slice(0, 50) })
73
+ }
74
+ return out
75
+ })
76
+ for (const p of found) problems.push({ theme: dark ? 'dark' : 'light', route: r.path, ...p })
77
+ if (found.length) console.log(`[${dark ? 'dark' : 'light'}] ${r.path}: ${found.length} 个可疑`)
78
+ }
79
+ catch (e) {
80
+ console.log(`[ERR] ${r.path}: ${String(e).slice(0, 100)}`)
81
+ }
82
+ }
83
+ await page.close()
84
+ }
85
+ await browser.close()
86
+ console.log(`\n===== 扫描完成:${problems.length} 个可疑点 =====`)
87
+ for (const p of problems) console.log(`[${p.theme}] ${p.route} ${p.kind} cr=${p.cr ?? ''} "${p.label}" cls=${p.cls}`)