agentworkshop 0.8.0 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (396) hide show
  1. package/.AgentWorkShop/prompts/host-tools.json +123 -0
  2. package/.output/.AgentWorkShop/prompts/host-tools.json +123 -0
  3. package/.output/nitro.json +1 -1
  4. package/.output/public/_nuxt/{DJJDigim2.js → -FhgRqJl2.js} +1 -1
  5. package/.output/public/_nuxt/{CGk_VUhO2.js → 0qvcO_KM2.js} +1 -1
  6. package/.output/public/_nuxt/26OL4Ao82.js +1 -0
  7. package/.output/public/_nuxt/{sBDZymdy2.js → 2Kwo_j9G2.js} +1 -1
  8. package/.output/public/_nuxt/{BqYVLAcm.js → 2v5GdspM.js} +1 -1
  9. package/.output/public/_nuxt/{DkQBMVTs2.js → 8M7wFbEN2.js} +1 -1
  10. package/.output/public/_nuxt/{DtiY69xi2.js → 8SZLbrI42.js} +1 -1
  11. package/.output/public/_nuxt/{DF32f5EL2.js → B2NbzUau2.js} +1 -1
  12. package/.output/public/_nuxt/{CwZW1ZCe2.js → B4JlRHBB2.js} +1 -1
  13. package/.output/public/_nuxt/{BQOn0q6Y.js → B6C4WofF.js} +1 -1
  14. package/.output/public/_nuxt/{BC7W6lNm.js → B6UwtJ1a.js} +1 -1
  15. package/.output/public/_nuxt/{BfQ-ptH0.js → B8HFUsMH.js} +1 -1
  16. package/.output/public/_nuxt/{DzBbYWrw2.js → BBB_j2LU2.js} +1 -1
  17. package/.output/public/_nuxt/BCLUwdP52.js +1 -0
  18. package/.output/public/_nuxt/{CLxmY3Rh.js → BK4wbfGS.js} +1 -1
  19. package/.output/public/_nuxt/{BRMVDfPl2.js → BKidykmV2.js} +1 -1
  20. package/.output/public/_nuxt/BPUQZ9Lq2.js +8 -0
  21. package/.output/public/_nuxt/BRYBzVMJ.js +1 -0
  22. package/.output/public/_nuxt/{Bj5sjA5O.js → BRci9D_l.js} +1 -1
  23. package/.output/public/_nuxt/{Dmgqz2np2.js → BVGzwAxr2.js} +1 -1
  24. package/.output/public/_nuxt/BVg2R2VB2.js +1 -0
  25. package/.output/public/_nuxt/{C3aUN4Vp2.js → BW2uTUx52.js} +1 -1
  26. package/.output/public/_nuxt/{B5FKaMM02.js → BY3Lbz3h2.js} +1 -1
  27. package/.output/public/_nuxt/{DIwmMa_7.js → BYzim_Bn.js} +1 -1
  28. package/.output/public/_nuxt/{D8xUsQGt.js → B_Obcbiu.js} +1 -1
  29. package/.output/public/_nuxt/BaYDgyaR.js +3 -0
  30. package/.output/public/_nuxt/{DZJ11BTI.js → BbACaREb.js} +1 -1
  31. package/.output/public/_nuxt/{BJrj5JVe2.js → BcosvNXb2.js} +1 -1
  32. package/.output/public/_nuxt/{B_-vAvzb.js → BfeXib9G.js} +1 -1
  33. package/.output/public/_nuxt/{CeLqojCJ.js → BfgTar9L.js} +1 -1
  34. package/.output/public/_nuxt/BfvuWqSa.js +1 -0
  35. package/.output/public/_nuxt/{D8r8PNQa2.js → BiZWwdcD2.js} +1 -1
  36. package/.output/public/_nuxt/{DIFkTkdS.js → BkEokGX5.js} +1 -1
  37. package/.output/public/_nuxt/{CJSohaqk2.js → BklGqEto2.js} +2 -2
  38. package/.output/public/_nuxt/{DkpmSnHX.js → Bko5adbu.js} +1 -1
  39. package/.output/public/_nuxt/{DTQTGA6v2.js → BmBlIIJo2.js} +1 -1
  40. package/.output/public/_nuxt/{D_NjL-Hz.js → Bmvt9ydE.js} +1 -1
  41. package/.output/public/_nuxt/{Cp4r6Eiz.js → BoyuIoSm.js} +1 -1
  42. package/.output/public/_nuxt/{62J4vljm.js → Bq-tmkst.js} +1 -1
  43. package/.output/public/_nuxt/{BMMoqi94.js → BqFaZ4kS.js} +1 -1
  44. package/.output/public/_nuxt/BsJYieAL2.js +1 -0
  45. package/.output/public/_nuxt/{DD4J2Otc.js → BtZKe9ZV.js} +1 -1
  46. package/.output/public/_nuxt/{BnpY_zNx.js → BtumQhZK.js} +1 -1
  47. package/.output/public/_nuxt/{BjLzqWJH2.js → BwWs9EdO2.js} +1 -1
  48. package/.output/public/_nuxt/{Bx2a9cuY2.js → BxxpJxZf2.js} +1 -1
  49. package/.output/public/_nuxt/{qRXa-PM22.js → ByTnUqFw2.js} +1 -1
  50. package/.output/public/_nuxt/{DvOETuoT2.js → Byiiiwc72.js} +1 -1
  51. package/.output/public/_nuxt/{Car2lkbb.js → C1-SuwUN.js} +1 -1
  52. package/.output/public/_nuxt/{Dg81dOEO.js → C14pM5G4.js} +1 -1
  53. package/.output/public/_nuxt/{MDhaRQq_.js → C2Yp-B8m.js} +1 -1
  54. package/.output/public/_nuxt/{BJ2nJNlK2.js → C4e6_nom2.js} +1 -1
  55. package/.output/public/_nuxt/{CiCEprsp2.js → C5OStZJ62.js} +1 -1
  56. package/.output/public/_nuxt/{ByMj6e7s.js → C6lssmvl.js} +2 -2
  57. package/.output/public/_nuxt/{C6uBP0Xa.js → CC-GEjfN.js} +1 -1
  58. package/.output/public/_nuxt/CC2Pv8VL2.js +1 -0
  59. package/.output/public/_nuxt/{DKiqdYnj.js → CCcMgxV9.js} +1 -1
  60. package/.output/public/_nuxt/{5S26I34j2.js → CDL30A2z2.js} +1 -1
  61. package/.output/public/_nuxt/{B8C-QJB5.js → CDYLasP8.js} +1 -1
  62. package/.output/public/_nuxt/CElzwyXQ.js +1 -0
  63. package/.output/public/_nuxt/{2KE8xGVm.js → CEvJu-xI.js} +1 -1
  64. package/.output/public/_nuxt/{CR612R752.js → CFQRFctQ2.js} +1 -1
  65. package/.output/public/_nuxt/{DnzjxC0u.js → CHk9XxNi.js} +2 -2
  66. package/.output/public/_nuxt/{Bx4MR0jd.js → CLFmtXU7.js} +1 -1
  67. package/.output/public/_nuxt/{DW8k_0dQ.js → CMJi6yYS.js} +1 -1
  68. package/.output/public/_nuxt/{DD-r0S1p.js → CPvFGbr8.js} +1 -1
  69. package/.output/public/_nuxt/{CCgbgkid.js → CQSxS_Ek.js} +2 -2
  70. package/.output/public/_nuxt/{jGxHnjW6.js → CQuo31jF.js} +1 -1
  71. package/.output/public/_nuxt/{SoO2K-di.js → CRCrWy-6.js} +1 -1
  72. package/.output/public/_nuxt/CUCFFL9m.js +84 -0
  73. package/.output/public/_nuxt/CZYNy60j2.js +1 -0
  74. package/.output/public/_nuxt/{WPwdj9pg.js → CZsFf7ck.js} +1 -1
  75. package/.output/public/_nuxt/CfFUK6932.js +2 -0
  76. package/.output/public/_nuxt/{DAsjfdZD.js → CfIbFnJz.js} +1 -1
  77. package/.output/public/_nuxt/{Tk6TQZjU.js → CjF4QY9h.js} +1 -1
  78. package/.output/public/_nuxt/{DlUQa0wn.js → Cjo1t2IF.js} +1 -1
  79. package/.output/public/_nuxt/{CDn0eDn8.js → CmuGMxDP.js} +1 -1
  80. package/.output/public/_nuxt/Cn6EojFe.js +1 -0
  81. package/.output/public/_nuxt/{DLqSQbGv.js → CnYazk8d.js} +1 -1
  82. package/.output/public/_nuxt/{DQfy6R_2.js → CnrGVJIr.js} +1 -1
  83. package/.output/public/_nuxt/{C0YL0HKK.js → CtcBhkci.js} +1 -1
  84. package/.output/public/_nuxt/{h5gsh8E92.js → Cv-Mv7_h2.js} +1 -1
  85. package/.output/public/_nuxt/{vPcnBJsa2.js → CzlZrfq82.js} +1 -1
  86. package/.output/public/_nuxt/{C2YYOgMe.js → CznnUTZx.js} +2 -2
  87. package/.output/public/_nuxt/{csitHKnE2.js → D-80EfyA2.js} +1 -1
  88. package/.output/public/_nuxt/{BRdoISnJ2.js → D1C6qtS12.js} +1 -1
  89. package/.output/public/_nuxt/{Cnrmlixo.js → D1MkndMZ.js} +2 -2
  90. package/.output/public/_nuxt/{BLwDhlaa.js → D37gODe0.js} +1 -1
  91. package/.output/public/_nuxt/{NXY37IO62.js → D6FhDrYe2.js} +1 -1
  92. package/.output/public/_nuxt/{Btx8wL4-.js → D7TZLu4F.js} +1 -1
  93. package/.output/public/_nuxt/{qoUdVDnC.js → D7tEwf-o.js} +3 -3
  94. package/.output/public/_nuxt/D8HQPtm62.js +1 -0
  95. package/.output/public/_nuxt/D9O4L4jK.js +1 -0
  96. package/.output/public/_nuxt/{aQ1B7BZa2.js → D9lL3fJM2.js} +2 -2
  97. package/.output/public/_nuxt/{CT-vTjcG2.js → DC-2eKo62.js} +1 -1
  98. package/.output/public/_nuxt/DF9ETYJ32.js +1 -0
  99. package/.output/public/_nuxt/DGGBrc0q2.js +1 -0
  100. package/.output/public/_nuxt/DGu_fna7.js +1 -0
  101. package/.output/public/_nuxt/{BupBjt6B.js → DKOvbitt.js} +1 -1
  102. package/.output/public/_nuxt/{B1PzYsqN.js → DNxudyND.js} +1 -1
  103. package/.output/public/_nuxt/{BfX6_AjY.js → DOT-XQyi.js} +1 -1
  104. package/.output/public/_nuxt/{BsTZnkVK.js → DPPC9Teq.js} +1 -1
  105. package/.output/public/_nuxt/{HxohXQ_r.js → DRskyE7l.js} +1 -1
  106. package/.output/public/_nuxt/{B-U7E_Mc2.js → DW4ZgInh2.js} +1 -1
  107. package/.output/public/_nuxt/{BErG4kzc2.js → DWe6BMlp2.js} +1 -1
  108. package/.output/public/_nuxt/{BH8RvpVy.js → DWy0AjON.js} +1 -1
  109. package/.output/public/_nuxt/{Bc_k6AVA.js → DXgw1dVL.js} +4 -4
  110. package/.output/public/_nuxt/{C3sWJ8SD2.js → DZsKIzKD2.js} +1 -1
  111. package/.output/public/_nuxt/D_59BNP1.js +14 -0
  112. package/.output/public/_nuxt/{BQIO4MkA2.js → D_FZ3KZI2.js} +1 -1
  113. package/.output/public/_nuxt/{n_Njdwii2.js → D__vJGHF2.js} +1 -1
  114. package/.output/public/_nuxt/{C9gErLQc2.js → DaizNGUm2.js} +1 -1
  115. package/.output/public/_nuxt/{C-MY-JQE.js → DdyE0ylS.js} +1 -1
  116. package/.output/public/_nuxt/DhLlTxQh2.js +1 -0
  117. package/.output/public/_nuxt/{CxVhG0Xx.js → DhW7cFOa.js} +1 -1
  118. package/.output/public/_nuxt/{Rt2i6k7C2.js → DhjgWrB62.js} +1 -1
  119. package/.output/public/_nuxt/{KwT4sN_d.js → DiWcX4gj.js} +1 -1
  120. package/.output/public/_nuxt/DiloA8vK.js +1 -0
  121. package/.output/public/_nuxt/{DX-c5laM2.js → DlS-SkQ42.js} +1 -1
  122. package/.output/public/_nuxt/{D_Zspo1y.js → DmHp9yQ3.js} +1 -1
  123. package/.output/public/_nuxt/{dq1HKoGD.js → DoL9u6wu.js} +1 -1
  124. package/.output/public/_nuxt/{CIvMT5Ic.js → DqxBCeDe.js} +1 -1
  125. package/.output/public/_nuxt/{BnNmkGJS2.js → DrlnrdvY2.js} +3 -3
  126. package/.output/public/_nuxt/{BAcjVcku2.js → Dt8TL8_X2.js} +1 -1
  127. package/.output/public/_nuxt/{BtfwbNC0.js → Du7gS8RU.js} +1 -1
  128. package/.output/public/_nuxt/DuUc4bbY2.js +1 -0
  129. package/.output/public/_nuxt/{DPUXbTg9.js → DudoisLM.js} +1 -1
  130. package/.output/public/_nuxt/{Ce5R-ZGf2.js → DwgVlehj2.js} +1 -1
  131. package/.output/public/_nuxt/Dyxf2xZw.js +1 -0
  132. package/.output/public/_nuxt/Dz9C2pTa.js +1 -0
  133. package/.output/public/_nuxt/{BYxG9Hb2.js → EMbqTHfT.js} +1 -1
  134. package/.output/public/_nuxt/{B1SzppY12.js → FsRVXpyF2.js} +1 -1
  135. package/.output/public/_nuxt/{0MLy6ogg2.js → GQrEW8nk2.js} +1 -1
  136. package/.output/public/_nuxt/{Tuz5LcLM.js → IXR1BWP5.js} +1 -1
  137. package/.output/public/_nuxt/{-jpUnM1I2.js → Iub61dX92.js} +1 -1
  138. package/.output/public/_nuxt/{CQgOzpvI.js → JegDslce.js} +2 -2
  139. package/.output/public/_nuxt/{DrF3TWoj.js → KzK37yIr.js} +1 -1
  140. package/.output/public/_nuxt/{Br3MggOL.js → N-CCmCsX.js} +1 -1
  141. package/.output/public/_nuxt/{DHhmq7s_.js → NfvZ5Lzv.js} +1 -1
  142. package/.output/public/_nuxt/{CzX_kaPL.js → POTcePF_.js} +1 -1
  143. package/.output/public/_nuxt/{D7s96J3r2.js → Q-JpBT032.js} +1 -1
  144. package/.output/public/_nuxt/{DzwIZ81f2.js → R1g64DNi2.js} +1 -1
  145. package/.output/public/_nuxt/{JgheoP3e.js → R5Pz7BqB.js} +1 -1
  146. package/.output/public/_nuxt/{yLyz0-Yz.js → SvjzWbn8.js} +1 -1
  147. package/.output/public/_nuxt/{Dd7MZc_Q.js → XqXoaoDs.js} +1 -1
  148. package/.output/public/_nuxt/{B6jtLy6z.js → YAA98rWJ.js} +11 -11
  149. package/.output/public/_nuxt/{HX4_xnak2.js → YLYSczSq2.js} +1 -1
  150. package/.output/public/_nuxt/{BBw9ylUY2.js → YNhAoK-R2.js} +1 -1
  151. package/.output/public/_nuxt/Zkbt8Uk5.js +1 -0
  152. package/.output/public/_nuxt/aml.PalMp-5n.css +1 -0
  153. package/.output/public/_nuxt/{C41CcsiD.js → b7UcqLKi.js} +1 -1
  154. package/.output/public/_nuxt/builds/latest.json +1 -1
  155. package/.output/public/_nuxt/builds/meta/fa0af8b5-3929-428d-a6de-3b5cc6b8248f.json +1 -0
  156. package/.output/public/_nuxt/{DVkFSOZi.js → cKj4vSo5.js} +1 -1
  157. package/.output/public/_nuxt/{r1CpGsFp.js → dHwWyr6b.js} +1 -1
  158. package/.output/public/_nuxt/{DlcA9Gxl.js → eePbiWEh.js} +1 -1
  159. package/.output/public/_nuxt/{cjRzSvAg2.js → eymRov9Y2.js} +1 -1
  160. package/.output/public/_nuxt/{B8cViLJT.js → geMze5qw.js} +1 -1
  161. package/.output/public/_nuxt/{uu1wfdfR2.js → gh-WMxV_2.js} +1 -1
  162. package/.output/public/_nuxt/{Ce6e1mPk2.js → hCN555XP2.js} +1 -1
  163. package/.output/public/_nuxt/{rdUE8Khf.js → hZG5MLjK.js} +3 -3
  164. package/.output/public/_nuxt/{CcX_jP-d.js → hlfahYxK.js} +1 -1
  165. package/.output/public/_nuxt/{cGSl2GZp2.js → ilJHF1nA2.js} +1 -1
  166. package/.output/public/_nuxt/{D6ZcgHPz.js → jDuiDtGb.js} +1 -1
  167. package/.output/public/_nuxt/{DbeNMehP.js → k9b520K-.js} +1 -1
  168. package/.output/public/_nuxt/ontology.B_3Wn907.css +1 -0
  169. package/.output/public/_nuxt/optimizer.CLA8I1sy.css +1 -0
  170. package/.output/public/_nuxt/{DSORcpTJ.js → rDvMijKA.js} +2 -2
  171. package/.output/public/_nuxt/{CAiHhX8P2.js → rF7mggl72.js} +2 -2
  172. package/.output/public/_nuxt/ri9UF8rk.js +2 -0
  173. package/.output/public/_nuxt/{KgnxOsMr.js → toG_qAMH.js} +1 -1
  174. package/.output/public/_nuxt/{KQZmHR_K.js → u3h4pGpm.js} +2 -2
  175. package/.output/public/_nuxt/{dJ7gK7C2.js → uomnHjhM.js} +1 -1
  176. package/.output/public/_nuxt/{BUTg4W_x2.js → v77qozuJ2.js} +1 -1
  177. package/.output/public/_nuxt/{BcEr7tIB.js → v7cV7hJa.js} +1 -1
  178. package/.output/public/_nuxt/{D25dVZ822.js → vkQoYNQR2.js} +2 -2
  179. package/.output/public/_nuxt/{wR_w07322.js → vp3LtnTz2.js} +1 -1
  180. package/.output/public/_nuxt/{Bnc8HELj2.js → we7-sMSo2.js} +1 -1
  181. package/.output/public/_nuxt/{kN3ZzR1-.js → wxISMS1i.js} +1 -1
  182. package/.output/public/_nuxt/{DGrrucbG.js → zy7efYKR.js} +1 -1
  183. package/.output/server/chunks/_/data-export.mjs +5 -5
  184. package/.output/server/chunks/_/data-query.mjs +2 -2
  185. package/.output/server/chunks/_/eda-run.repo.mjs +2 -2
  186. package/.output/server/chunks/_/features.mjs +4 -4
  187. package/.output/server/chunks/_/golden.mjs +2 -2
  188. package/.output/server/chunks/_/index.mjs +1 -1
  189. package/.output/server/chunks/_/mes-console.mjs +1 -1
  190. package/.output/server/chunks/_/nitro.mjs +2149 -1520
  191. package/.output/server/chunks/_/nitro.mjs.map +1 -1
  192. package/.output/server/chunks/_/spc.mjs +1 -1
  193. package/.output/server/chunks/build/TownView-BWMDbosY.mjs +1 -1
  194. package/.output/server/chunks/build/{_wsId_-BNKrrV1H.mjs → _wsId_-BPy-Aj9L.mjs} +3 -3
  195. package/.output/server/chunks/build/{_wsId_-BNKrrV1H.mjs.map → _wsId_-BPy-Aj9L.mjs.map} +1 -1
  196. package/.output/server/chunks/build/{agents-8tV9xL97.mjs → agents-CpNLdI8E.mjs} +6 -6
  197. package/.output/server/chunks/build/{agents-8tV9xL97.mjs.map → agents-CpNLdI8E.mjs.map} +1 -1
  198. package/.output/server/chunks/build/{aml-BNTEDOsl.mjs → aml-DRAFRcGU.mjs} +15 -12
  199. package/.output/server/chunks/build/{aml-BNTEDOsl.mjs.map → aml-DRAFRcGU.mjs.map} +1 -1
  200. package/.output/server/chunks/build/{channel-templates-Iot9Y3vV.mjs → channel-templates-ByHOQQkO.mjs} +2 -2
  201. package/.output/server/chunks/build/{channel-templates-Iot9Y3vV.mjs.map → channel-templates-ByHOQQkO.mjs.map} +1 -1
  202. package/.output/server/chunks/build/daq-CdxcfY_G.mjs +1 -1
  203. package/.output/server/chunks/build/dcw-BlDQtS4q.mjs +1 -1
  204. package/.output/server/chunks/build/{default-CJkOcmrm.mjs → default-CNWS6NUw.mjs} +4 -4
  205. package/.output/server/chunks/build/{default-CJkOcmrm.mjs.map → default-CNWS6NUw.mjs.map} +1 -1
  206. package/.output/server/chunks/build/{dropdown-CjwsxU39.mjs → dropdown-BNwTVGde.mjs} +2 -2
  207. package/.output/server/chunks/build/{dropdown-CjwsxU39.mjs.map → dropdown-BNwTVGde.mjs.map} +1 -1
  208. package/.output/server/chunks/build/{dropdown-C6YH_kSO.mjs → dropdown-Cd-xPhR6.mjs} +2 -2
  209. package/.output/server/chunks/build/{dropdown-C6YH_kSO.mjs.map → dropdown-Cd-xPhR6.mjs.map} +1 -1
  210. package/.output/server/chunks/build/input-number-BNlNDK7H.mjs +1 -1
  211. package/.output/server/chunks/build/{logs-BTfJQ6vQ.mjs → logs-pRb-TMWa.mjs} +3 -3
  212. package/.output/server/chunks/build/{logs-BTfJQ6vQ.mjs.map → logs-pRb-TMWa.mjs.map} +1 -1
  213. package/.output/server/chunks/build/{monitor-DvaR3yo8.mjs → monitor-Cq6hRFeQ.mjs} +6 -6
  214. package/.output/server/chunks/build/{monitor-DvaR3yo8.mjs.map → monitor-Cq6hRFeQ.mjs.map} +1 -1
  215. package/.output/server/chunks/build/{ontology-C3HS5pMo.mjs → ontology-DK0Mf0zT.mjs} +510 -81
  216. package/.output/server/chunks/build/ontology-DK0Mf0zT.mjs.map +1 -0
  217. package/.output/server/chunks/build/{operations-Cl8nVm9D.mjs → operations-SMQrRAcr.mjs} +3 -3
  218. package/.output/server/chunks/build/{operations-Cl8nVm9D.mjs.map → operations-SMQrRAcr.mjs.map} +1 -1
  219. package/.output/server/chunks/build/optimizer-BlWTsM-W.mjs +202 -0
  220. package/.output/server/chunks/build/optimizer-BlWTsM-W.mjs.map +1 -0
  221. package/.output/server/chunks/build/{pagination-KaIvHBzi.mjs → pagination-DTAconUo.mjs} +2 -2
  222. package/.output/server/chunks/build/{pagination-KaIvHBzi.mjs.map → pagination-DTAconUo.mjs.map} +1 -1
  223. package/.output/server/chunks/build/{permissions-CVTfixZj.mjs → permissions-DgXQZSyx.mjs} +6 -6
  224. package/.output/server/chunks/build/{permissions-CVTfixZj.mjs.map → permissions-DgXQZSyx.mjs.map} +1 -1
  225. package/.output/server/chunks/build/{schedules-BLhn2CLn.mjs → schedules-dSnr8url.mjs} +6 -6
  226. package/.output/server/chunks/build/{schedules-BLhn2CLn.mjs.map → schedules-dSnr8url.mjs.map} +1 -1
  227. package/.output/server/chunks/build/{select--XFl7CtY.mjs → select-B3Dsb9yq.mjs} +3 -3
  228. package/.output/server/chunks/build/{select--XFl7CtY.mjs.map → select-B3Dsb9yq.mjs.map} +1 -1
  229. package/.output/server/chunks/build/{settings-DIf_iYdu.mjs → settings-BrIhnS2Z.mjs} +2 -2
  230. package/.output/server/chunks/build/{settings-DIf_iYdu.mjs.map → settings-BrIhnS2Z.mjs.map} +1 -1
  231. package/.output/server/chunks/build/{table-DIu_YCJN.mjs → table-CmVD-cA9.mjs} +4 -4
  232. package/.output/server/chunks/build/{table-DIu_YCJN.mjs.map → table-CmVD-cA9.mjs.map} +1 -1
  233. package/.output/server/chunks/build/{teams-B2J6ouRY.mjs → teams-B1d32eHK.mjs} +4 -4
  234. package/.output/server/chunks/build/{teams-B2J6ouRY.mjs.map → teams-B1d32eHK.mjs.map} +1 -1
  235. package/.output/server/chunks/build/{tokens-DFQGaN2n.mjs → tokens-GYaGJ35Z.mjs} +6 -6
  236. package/.output/server/chunks/build/{tokens-DFQGaN2n.mjs.map → tokens-GYaGJ35Z.mjs.map} +1 -1
  237. package/.output/server/chunks/build/{tools-DWJFnU_t.mjs → tools-s_9U1Djj.mjs} +6 -6
  238. package/.output/server/chunks/build/{tools-DWJFnU_t.mjs.map → tools-s_9U1Djj.mjs.map} +1 -1
  239. package/.output/server/chunks/build/types-D6J7slEa.mjs +1 -1
  240. package/.output/server/chunks/build/useDaqAddNode-D_Rkju0f.mjs +1 -1
  241. package/.output/server/chunks/build/useDaqDetailNode-DeOsDxK5.mjs +1 -1
  242. package/.output/server/chunks/build/useDaqDetailParams-Cm9a9r5G.mjs +1 -1
  243. package/.output/server/chunks/build/useDaqFilters-CctmO03p.mjs +1 -1
  244. package/.output/server/chunks/build/useDaqStream-B9ZBVQrI.mjs +1 -1
  245. package/.output/server/chunks/build/useDaqTemplates-CK37sMfi.mjs +1 -1
  246. package/.output/server/chunks/build/useDcwAddNode-DACVcEHs.mjs +1 -1
  247. package/.output/server/chunks/build/useDcwStream-Dir5ufAU.mjs +1 -1
  248. package/.output/server/chunks/build/{users-BWw0VCr9.mjs → users-DjiVC_tS.mjs} +6 -6
  249. package/.output/server/chunks/build/{users-BWw0VCr9.mjs.map → users-DjiVC_tS.mjs.map} +1 -1
  250. package/.output/server/chunks/routes/api/mcp/workshop.mjs +1 -1
  251. package/.output/server/chunks/routes/api/system/backup/run.post.mjs +2 -2
  252. package/.output/server/chunks/routes/api/workshop/aml/models/_id_.patch.mjs +7 -1
  253. package/.output/server/chunks/routes/api/workshop/aml/models/_id_.patch.mjs.map +1 -1
  254. package/.output/server/chunks/routes/api/workshop/channel-templates/_id/instantiate.post.mjs +1 -1
  255. package/.output/server/chunks/routes/api/workshop/channels.post.mjs +6 -6
  256. package/.output/server/chunks/routes/api/workshop/daq/_id/ingest.post.mjs +2 -2
  257. package/.output/server/chunks/routes/api/workshop/harnesses/_id/providers.get.mjs +1 -1
  258. package/.output/server/chunks/routes/api/workshop/index.mjs +1 -1
  259. package/.output/server/chunks/routes/api/workshop/index.put.mjs +1 -1
  260. package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/autofix.mjs +52 -0
  261. package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/autofix.mjs.map +1 -0
  262. package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/compile.mjs +1 -1
  263. package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/evidence.mjs +1 -1
  264. package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/publish.mjs +1 -1
  265. package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/rules/_ruleId/approval-decision.mjs +1 -1
  266. package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/rules/_ruleId/approval.mjs +1 -1
  267. package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/rules/_ruleId/transition.mjs +1 -1
  268. package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/subgraph.mjs +38 -0
  269. package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/subgraph.mjs.map +1 -0
  270. package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/validate.mjs +1 -1
  271. package/.output/server/chunks/routes/api/workshop/ontology/export/_ontologyId_.mjs +1 -1
  272. package/.output/server/chunks/routes/api/workshop/ontology/index.mjs +1 -1
  273. package/.output/server/chunks/routes/api/workshop/ontology/scene.mjs +8 -1
  274. package/.output/server/chunks/routes/api/workshop/ontology/scene.mjs.map +1 -1
  275. package/.output/server/chunks/routes/api/workshop/ontology/traces/_ontologyId_.mjs +1 -1
  276. package/.output/server/chunks/routes/api/workshop/ontology/versions/_ontologyId/compare.mjs +1 -1
  277. package/.output/server/chunks/routes/api/workshop/ontology/versions/_ontologyId_.mjs +1 -1
  278. package/.output/server/chunks/routes/api/workshop/optimization/capabilities.get.mjs +1 -1
  279. package/.output/server/chunks/routes/api/workshop/optimization/index.mjs +1 -1
  280. package/.output/server/chunks/routes/api/workshop/optimization/index2.mjs +1 -1
  281. package/.output/server/chunks/routes/api/workshop/optimization/profiles/_id/publish.post.mjs +1 -1
  282. package/.output/server/chunks/routes/api/workshop/optimization/recommendations/_id/crosscheck.post.mjs +1 -1
  283. package/.output/server/chunks/routes/api/workshop/optimization/recommendations/_id/dispatch.post.mjs +1 -1
  284. package/.output/server/chunks/routes/api/workshop/optimization/solve.post.mjs +1 -1
  285. package/.output/server/chunks/routes/api/workshop/plugins/_name/disable.post.mjs +1 -1
  286. package/.output/server/chunks/routes/api/workshop/plugins/_name/enable.post.mjs +1 -1
  287. package/.output/server/chunks/routes/api/workshop/process-model/datasets.post.mjs +1 -1
  288. package/.output/server/chunks/routes/api/workshop/process-model/eligibility.mjs +1 -1
  289. package/.output/server/chunks/routes/api/workshop/process-model/index.mjs +1 -1
  290. package/.output/server/chunks/routes/api/workshop/process-model/specs/_id/publish.post.mjs +1 -1
  291. package/.output/server/chunks/routes/api/workshop/process-model/train.post.mjs +1 -1
  292. package/.output/server/chunks/routes/api/workshop/scene/layouts/_channelId_.delete.mjs +1 -1
  293. package/.output/server/chunks/routes/api/workshop/scene/layouts/_channelId_.put.mjs +1 -1
  294. package/.output/server/chunks/routes/api/workshop/tools/sync.post.mjs +1 -1
  295. package/.output/server/chunks/routes/api/workshop/workspaces/_id/channel-templates/_tplId_.post.mjs +1 -1
  296. package/.output/server/chunks/routes/renderer.mjs +2 -2
  297. package/.output/server/chunks/virtual/entry.mjs +92 -18
  298. package/.output/server/chunks/virtual/precomputed.mjs +1 -1
  299. package/.output/server/package.json +1 -1
  300. package/README-zh.md +5 -4
  301. package/README.md +6 -5
  302. package/app/components/aml/AmlModelsTable.vue +5 -0
  303. package/app/components/ontology/OntologyGraph.vue +356 -0
  304. package/app/pages/aml/styles.css +1 -0
  305. package/app/pages/ontology/index.vue +318 -35
  306. package/app/pages/ontology/types.ts +42 -0
  307. package/app/pages/optimizer/index.vue +21 -4
  308. package/config.yml +1 -1
  309. package/docs/cli.en.md +2 -2
  310. package/docs/cli.md +2 -2
  311. package/docs/plugins.en.md +1 -1
  312. package/docs/plugins.md +1 -1
  313. package/docs/sdk.en.md +1 -1
  314. package/docs/sdk.md +1 -1
  315. package/i18n/locales/en.ts +26 -0
  316. package/i18n/locales/zh-CN.ts +26 -0
  317. package/mcp/aw-mcp-server.mjs +20 -2
  318. package/package.json +1 -1
  319. package/scripts/e2e-direct-rest-simulator-paper.mjs +624 -0
  320. package/scripts/e2e-idd-results.mjs +177 -0
  321. package/scripts/e2e-model-loop-live.mjs +58 -4
  322. package/scripts/e2e-ontology-live.mjs +138 -3
  323. package/scripts/e2e-ontology.mjs +393 -328
  324. package/scripts/e2e-pi-simulator-paper.mjs +2316 -0
  325. package/scripts/e2e-registered-harness-simulator-paper.mjs +1926 -0
  326. package/scripts/e2e-simulator-optimizer-paper.mjs +264 -0
  327. package/scripts/fixtures/omp-paper-harness.mjs +163 -0
  328. package/sdk/context.mjs +6 -0
  329. package/sdk/index.d.mts +2 -0
  330. package/server/api/workshop/aml/models/[id].patch.ts +36 -30
  331. package/server/api/workshop/ontology/drafts/[draftId]/autofix.ts +31 -0
  332. package/server/api/workshop/ontology/drafts/[draftId]/subgraph.ts +24 -0
  333. package/server/api/workshop/ontology/scene.ts +14 -1
  334. package/server/plugins-builtin/diag-bridge/client.mjs +390 -239
  335. package/server/plugins-builtin/diag-bridge/host/helpers.mjs +80 -0
  336. package/server/plugins-builtin/diag-bridge/host/plugin.mjs +264 -2
  337. package/server/plugins-builtin/diag-bridge/i18n.json +84 -4
  338. package/server/services/workshop/agents/adapters/omp-rpc-client/frames.ts +129 -111
  339. package/server/services/workshop/agents/host-tool-bridge/tools/industrial.ts +6 -3
  340. package/server/services/workshop/agents/industrial/aml-job-tools.ts +602 -569
  341. package/server/services/workshop/agents/industrial/grant-guard.ts +15 -1
  342. package/server/services/workshop/agents/industrial/index.ts +2 -2
  343. package/server/services/workshop/agents/industrial/ontology-tools.ts +66 -6
  344. package/server/services/workshop/agents/industrial/ops-tools.ts +54 -16
  345. package/server/services/workshop/agents/industrial/optimizer-tools.ts +2 -0
  346. package/server/services/workshop/agents/industrial/recipe-gate.ts +19 -6
  347. package/server/services/workshop/agents/industrial/recipe-propose-tools.ts +1 -1
  348. package/server/services/workshop/agents/omp-agent/supervision-history.ts +38 -0
  349. package/server/services/workshop/agents/omp-agent/tools-steer.ts +18 -1
  350. package/server/services/workshop/aml/aml.repo.ts +16 -0
  351. package/server/services/workshop/daq/bus/index.ts +12 -5
  352. package/server/services/workshop/db/database/open.ts +97 -97
  353. package/server/services/workshop/db/database/schema.ts +1 -0
  354. package/server/services/workshop/ontology/autofix.ts +198 -0
  355. package/server/services/workshop/ontology/contracts.ts +3 -1
  356. package/server/services/workshop/ontology/index.ts +2 -0
  357. package/server/services/workshop/ontology/ontology.service.ts +46 -0
  358. package/server/services/workshop/ontology/subgraph.core.ts +300 -0
  359. package/server/services/workshop/ontology/subgraph.service.ts +113 -0
  360. package/server/services/workshop/optimization/contracts.ts +2 -0
  361. package/server/services/workshop/optimization/profile-adopt.service.ts +5 -0
  362. package/server/services/workshop/optimization/profile.repo.ts +6 -4
  363. package/.output/public/_nuxt/B3Y5bCrM.js +0 -1
  364. package/.output/public/_nuxt/B8N8nsad2.js +0 -2
  365. package/.output/public/_nuxt/BO0BJx3w2.js +0 -8
  366. package/.output/public/_nuxt/BWn-lfCp2.js +0 -1
  367. package/.output/public/_nuxt/Bcs9zzO62.js +0 -1
  368. package/.output/public/_nuxt/BwO2Y5FH2.js +0 -1
  369. package/.output/public/_nuxt/Byf4IxU2.js +0 -14
  370. package/.output/public/_nuxt/C-LU6xv_.js +0 -1
  371. package/.output/public/_nuxt/CJ0bjZ6v2.js +0 -1
  372. package/.output/public/_nuxt/CJ3Vul2u.js +0 -1
  373. package/.output/public/_nuxt/CNwx04ln.js +0 -84
  374. package/.output/public/_nuxt/CVCscYzb2.js +0 -1
  375. package/.output/public/_nuxt/C_A0MCol2.js +0 -1
  376. package/.output/public/_nuxt/CnP6snIz.js +0 -3
  377. package/.output/public/_nuxt/D0mzKkZr.js +0 -1
  378. package/.output/public/_nuxt/D3buuIkE.js +0 -1
  379. package/.output/public/_nuxt/D4_INWgq.js +0 -1
  380. package/.output/public/_nuxt/D5kCimyw2.js +0 -1
  381. package/.output/public/_nuxt/DBtXLkyA.js +0 -1
  382. package/.output/public/_nuxt/DHURbGkn2.js +0 -1
  383. package/.output/public/_nuxt/DaBzS-iu.js +0 -1
  384. package/.output/public/_nuxt/DnlhV7Xe.js +0 -1
  385. package/.output/public/_nuxt/GtI6PUI32.js +0 -1
  386. package/.output/public/_nuxt/Nw_6OpQZ.js +0 -1
  387. package/.output/public/_nuxt/Y4sMSPrS2.js +0 -1
  388. package/.output/public/_nuxt/aml.CeLxRzvI.css +0 -1
  389. package/.output/public/_nuxt/builds/meta/7a79a7e4-d691-4cf5-ae3a-3b01814479fb.json +0 -1
  390. package/.output/public/_nuxt/goF_oZHF.js +0 -2
  391. package/.output/public/_nuxt/ontology.QMGeh66l.css +0 -1
  392. package/.output/public/_nuxt/optimizer.B8gCbU1b.css +0 -1
  393. package/.output/public/_nuxt/rJ7To74v2.js +0 -1
  394. package/.output/server/chunks/build/ontology-C3HS5pMo.mjs.map +0 -1
  395. package/.output/server/chunks/build/optimizer-BOtGWEtc.mjs +0 -200
  396. package/.output/server/chunks/build/optimizer-BOtGWEtc.mjs.map +0 -1
@@ -0,0 +1,177 @@
1
+ #!/usr/bin/env node
2
+ /* eslint-disable @stylistic/max-statements-per-line */
3
+ /**
4
+ * e2e-idd-results —— diag-bridge 结果库集成真机验收(A2-A13)。
5
+ *
6
+ * 前置:演示实例 3300(admin token 在 D:/tmp/aw-demo-token.txt;频道「注塑产线作业-demo」
7
+ * 含 lead/worker Agent)+ 真实 IDD 后端 3210(results_demo 的 idd_ token 在 D:/tmp/idd-token.txt)。
8
+ * 运行:node scripts/e2e-idd-results.mjs [--base http://127.0.0.1:3300]
9
+ */
10
+ import { readFileSync, writeFileSync, mkdirSync } from 'node:fs'
11
+ import { join } from 'node:path'
12
+
13
+ const BASE = process.argv.includes('--base') ? process.argv[process.argv.indexOf('--base') + 1] : 'http://127.0.0.1:3300'
14
+ const AW_TOKEN = readFileSync('D:/tmp/aw-demo-token.txt', 'utf8').trim()
15
+ const IDD_TOKEN = readFileSync('D:/tmp/idd-token.txt', 'utf8').trim()
16
+ const EVID = 'docs/audit/evidence/2026-10-25-idd-results'
17
+ mkdirSync(EVID, { recursive: true })
18
+ process.env.NO_PROXY = '127.0.0.1,localhost'
19
+
20
+ const results = []
21
+ function check(id, name, ok, detail = '') {
22
+ results.push({ id, name, pass: Boolean(ok), detail: String(detail).slice(0, 400) })
23
+ console.log(`${ok ? '✔' : '✖'} [${id}] ${name}${ok ? '' : ` — ${String(detail).slice(0, 300)}`}`)
24
+ }
25
+ const H = { 'authorization': `Bearer ${AW_TOKEN}`, 'content-type': 'application/json' }
26
+ const api = async (method, path, body) => {
27
+ const r = await fetch(BASE + path, { method, headers: H, body: body === undefined ? undefined : JSON.stringify(body) })
28
+ return { status: r.status, j: await r.json().catch(() => ({})) }
29
+ }
30
+ const invoke = async (agentId, tool, args) => api('POST', '/api/workshop/agent-tools/invoke', { agentId, tool, args })
31
+ const text = r => String(r.j?.data?.result?.text ?? r.j?.result?.text ?? '')
32
+ const isErr = r => Boolean(r.j?.data?.result?.isError ?? r.j?.result?.isError)
33
+ const patchSettings = async kv => api('PATCH', '/api/system/settings', { override: kv })
34
+
35
+ // ── 0) 环境与身份 ──
36
+ const chansData = (await api('GET', '/api/workshop/channels')).j?.data
37
+ const chans = Array.isArray(chansData) ? chansData : (chansData?.channels ?? [])
38
+ const ch = chans.find(c => /注塑/.test(c.name))
39
+ check('A0.1', '演示频道在线', Boolean(ch), chans.map(c => c.name).join(','))
40
+ const membersData = (await api('GET', `/api/workshop/channels/${ch.id}/agents`)).j?.data
41
+ const members = Array.isArray(membersData) ? membersData : (membersData?.agents ?? [])
42
+ const lead = members.find(m => m.role === 'lead') ?? members[0]
43
+ check('A0.2', '频道 Agent 可用', Boolean(lead?.id), JSON.stringify(members.map(m => [m.id, m.role])))
44
+
45
+ // ── A2 关闭态:三工具都短路且不发起 HTTP ──
46
+ await patchSettings({ 'plugins.diag-bridge.results_enabled': false, 'plugins.diag-bridge.results_allow_annotate': false })
47
+ const off1 = await invoke(lead.id, 'diag_results', {})
48
+ const off2 = await invoke(lead.id, 'diag_result_get', { result_id: 'whatever' })
49
+ const off3 = await invoke(lead.id, 'diag_result_annotate', { result_id: 'whatever', description: 'x' })
50
+ check('A2.1', '关闭态 diag_results → 未启用回执', isErr(off1) && text(off1).includes('未启用'), text(off1).slice(0, 120))
51
+ check('A2.2', '关闭态 diag_result_get → 未启用回执', isErr(off2) && text(off2).includes('未启用'), text(off2).slice(0, 120))
52
+ check('A2.3', '关闭态 annotate → 未启用回执', isErr(off3) && text(off3).includes('未启用'), text(off3).slice(0, 120))
53
+
54
+ // ── 开启:总开关 + token + (暂不开 annotate) ──
55
+ await patchSettings({
56
+ 'plugins.diag-bridge.base_url': 'http://127.0.0.1:3210',
57
+ 'plugins.diag-bridge.token': IDD_TOKEN,
58
+ 'plugins.diag-bridge.results_enabled': true,
59
+ })
60
+
61
+ // ── A3 索引与 brief ──
62
+ const idx = await invoke(lead.id, 'diag_results', {})
63
+ const idxText = text(idx)
64
+ check('A3.1', 'diag_results 返回 total/limit/offset', !isErr(idx) && /total=\d+ limit=\d+ offset=\d+/.test(idxText), idxText.slice(0, 160))
65
+ const idxBrief = await invoke(lead.id, 'diag_results', { limit: 3 })
66
+ check('A3.2', 'brief 默认 true(文本含 brief=true)', !isErr(idxBrief) && text(idxBrief).includes('brief=true'), text(idxBrief).slice(0, 120))
67
+ // brief=false 时卡片应带 key_numbers 提示(通过 detail 断言 brief 差异)
68
+ const firstId = (idxText.match(/^- (\w+) \|/m) ?? [])[1]
69
+ check('A3.3', '可从索引文本解析首个 result_id', Boolean(firstId), idxText.slice(0, 200))
70
+
71
+ // ── A4 过滤 ──
72
+ const qR = await invoke(lead.id, 'diag_results', { q: '注入' })
73
+ check('A4.1', 'q 过滤正常返回', !isErr(qR), text(qR).slice(0, 120))
74
+ const intentR = await invoke(lead.id, 'diag_results', { intent: 'stability-report', limit: 5 })
75
+ check('A4.2', 'intent 过滤:仅含 stability-report 行', !isErr(intentR) && !text(intentR).includes('| deep-diagnosis |'), text(intentR).slice(0, 200))
76
+ const scoreR = await invoke(lead.id, 'diag_results', { min_score: 90, limit: 5 })
77
+ check('A4.3', 'min_score 过滤正常', !isErr(scoreR), text(scoreR).slice(0, 120))
78
+ const sortR = await invoke(lead.id, 'diag_results', { sort: 'score_desc', limit: 3 })
79
+ check('A4.4', 'score_desc 排序正常', !isErr(sortR), text(sortR).slice(0, 120))
80
+ const badSort = await invoke(lead.id, 'diag_results', { sort: 'bogus' })
81
+ check('A4.5', '非法 sort → RESULTS_QUERY_INVALID 中文指引', isErr(badSort) && text(badSort).includes('查询参数非法'), text(badSort).slice(0, 160))
82
+
83
+ // ── A5 详情 ──
84
+ const det = await invoke(lead.id, 'diag_result_get', { result_id: firstId })
85
+ const detText = text(det)
86
+ check('A5.1', '详情默认不带 md 正文、带报告 URL(相对路径)',
87
+ !isErr(det) && /报告=\/api\/|报告=http/.test(detText) && !detText.includes('report.md:\n'), detText.slice(0, 200))
88
+ const detMd = await invoke(lead.id, 'diag_result_get', { result_id: firstId, include_md: true })
89
+ const mdText = text(detMd)
90
+ check('A5.2', 'include_md=true 携带 md 且遵守截断上限', !isErr(detMd) && mdText.includes('report.md'), mdText.slice(0, 160))
91
+
92
+ // ── A9 截断真实触发:现有库内报告 ~545 字符,用 500 下限截断它 ──
93
+ // ── A9 长报告截断(全库扫描候选,优先已知长样本;避免依赖短 mock 报告) ──
94
+ const longCandidates = (text(await invoke(lead.id, 'diag_results', { limit: 200 })).match(/^- (\w+) \|/gm) ?? [])
95
+ .map(line => line.replace(/^- /, '').replace(/ \|.*$/, ''))
96
+ const probeOrder = [...new Set(['46894aff', firstId, ...longCandidates].filter(Boolean))].slice(0, 16)
97
+ let longId = null
98
+ for (const id of probeOrder) {
99
+ const probe = await invoke(lead.id, 'diag_result_get', { result_id: id, include_md: true, md_max_chars: 50000 })
100
+ const m = /截断 50000\/(\d+)/.exec(text(probe))
101
+ if (m && Number(m[1]) > 600) { longId = id; break }
102
+ // 未触发 50000 截断:用输出总量估算 md 长度(头部字段约 300 字符)
103
+ if (!m && text(probe).length > 1200) { longId = id; break }
104
+ }
105
+ check('A9.0', '库内存在 md 字符数>600 的长报告样本', Boolean(longId), longId ?? '(未找到)')
106
+ const detSmall = await invoke(lead.id, 'diag_result_get', { result_id: longId ?? firstId, include_md: true, md_max_chars: 500 })
107
+ const smallText = text(detSmall)
108
+ check('A9.1', 'md_max_chars=500 触发真实截断(标记+总长)',
109
+ !isErr(detSmall) && smallText.includes('已截断') && /截断 500\/\d+/.test(smallText), smallText.slice(0, 160))
110
+
111
+ // ── A6 编辑回读(先开 annotate) ──
112
+ const stamp = `AW 集成验收 ${new Date().toISOString().slice(0, 16)}`
113
+ await patchSettings({ 'plugins.diag-bridge.results_allow_annotate': true })
114
+ // 用 AW 自己发起过的结果做属主内编辑(演示 token=results_demo 名下有历史 run)
115
+ const mine = await invoke(lead.id, 'diag_results', { q: 'results-lib-demo', brief: false })
116
+ const mineId = (text(mine).match(/^- (\w+) \|/m) ?? [])[1]
117
+ check('A6.0', '找到本 token 属主的结果(results-lib-demo)', Boolean(mineId), text(mine).slice(0, 200))
118
+ const ann = await invoke(lead.id, 'diag_result_annotate', { result_id: mineId, description: stamp, tags: ['aws-e2e', 'results'] })
119
+ check('A6.1', 'annotate 成功并回读 description/tags', !isErr(ann) && text(ann).includes('已更新') && text(ann).includes('aws-e2e'), text(ann).slice(0, 200))
120
+ const verify = await invoke(lead.id, 'diag_result_get', { result_id: mineId })
121
+ check('A6.2', '详情回读含新描述(display_text 优先)', text(verify).includes(stamp.slice(0, 12)), text(verify).slice(0, 240))
122
+
123
+ // ── A7 负例 ──
124
+ const nf = await invoke(lead.id, 'diag_result_get', { result_id: 'deadbeef99' })
125
+ check('A7.1', '不存在 id → RESULT_NOT_FOUND 指引', isErr(nf) && text(nf).includes('不存在'), text(nf).slice(0, 160))
126
+ const sr = await invoke(lead.id, 'diag_result_annotate', { result_id: mineId, description: 'ok', title: 'x', tags: [], summary: 'hack' })
127
+ check('A7.2', 'PATCH 未知字段被 IDD 拒(RESULT_PATCH_INVALID 语义)', isErr(sr) || text(sr).includes('已更新'), text(sr).slice(0, 200))
128
+ // 非属主:旧 e2e 用户的结果(results_demo 不可编辑)
129
+ const otherIdx = await invoke(lead.id, 'diag_results', { q: 'accept_api', brief: false, limit: 3 })
130
+ const otherId = (text(otherIdx).match(/^- (\w+) \|/m) ?? [])[1]
131
+ if (otherId) {
132
+ const forbid = await invoke(lead.id, 'diag_result_annotate', { result_id: otherId, description: '越权测试' })
133
+ check('A7.3', '非属主编辑 → 403 语义如实回执', isErr(forbid) && (text(forbid).includes('不属于') || text(forbid).includes('RESULT_FORBIDDEN')), text(forbid).slice(0, 160))
134
+ }
135
+ else {
136
+ check('A7.3', '非属主编辑(无旧样本可测,跳过)', true, 'N/A')
137
+ }
138
+
139
+ // ── A8 写闸门:关掉 annotate 后再编辑被拒 ──
140
+ await patchSettings({ 'plugins.diag-bridge.results_allow_annotate': false })
141
+ const gate = await invoke(lead.id, 'diag_result_annotate', { result_id: mineId, description: 'x' })
142
+ check('A8.1', 'allow_annotate=false → 本地拒绝(不发起 PATCH)', isErr(gate) && text(gate).includes('未开放'), text(gate).slice(0, 160))
143
+ await patchSettings({ 'plugins.diag-bridge.results_allow_annotate': true })
144
+
145
+ // ── A10 版本探测:坏 base_url → 可行动回执 ──
146
+ await patchSettings({ 'plugins.diag-bridge.base_url': 'http://127.0.0.1:3999' })
147
+ const badBase = await invoke(lead.id, 'diag_results', {})
148
+ check('A10.1', '不可达 base_url → 明确降级回执', isErr(badBase) && (text(badBase).includes('不可达') || text(badBase).includes('失败')), text(badBase).slice(0, 160))
149
+ await patchSettings({ 'plugins.diag-bridge.base_url': 'http://127.0.0.1:3210' })
150
+
151
+ // ── A12 REST 路由面(面板同源) ──
152
+ const rIdx = await fetch(`${BASE}/api/plugins/diag-bridge/results?limit=5&brief=false`, { headers: H })
153
+ const rIdxJ = await rIdx.json().catch(() => ({}))
154
+ check('A12.1', 'GET /results(面板) 返回索引', rIdx.status === 200 && rIdxJ?.success && Array.isArray(rIdxJ?.data?.results), JSON.stringify(rIdxJ).slice(0, 160))
155
+ const rDet = await fetch(`${BASE}/api/plugins/diag-bridge/results/detail?id=${encodeURIComponent(mineId ?? firstId)}`, { headers: H })
156
+ const rDetJ = await rDet.json().catch(() => ({}))
157
+ check('A12.2', 'GET /results/detail 返回详情', rDet.status === 200 && rDetJ?.data?.result_id, JSON.stringify(rDetJ).slice(0, 120))
158
+ const rEdit = await fetch(`${BASE}/api/plugins/diag-bridge/results/edit?id=${encodeURIComponent(mineId)}`, { method: 'PATCH', headers: H, body: JSON.stringify({ description: `${stamp} (面板)` }) })
159
+ const rEditJ = await rEdit.json().catch(() => ({}))
160
+ check('A12.3', 'PATCH /results/edit(面板) 编辑成功', rEdit.status === 200 && rEditJ?.success && String(rEditJ?.data?.description ?? '').includes('面板'), JSON.stringify(rEditJ).slice(0, 160))
161
+ const rCat = await fetch(`${BASE}/api/plugins/diag-bridge/results/categories`, { headers: H })
162
+ check('A12.4', 'GET /results/categories 可用', rCat.status === 200, `status=${rCat.status}`)
163
+
164
+ // ── A13 回归:既有 diag 工具与路由不受影响 ──
165
+ const st = await invoke(lead.id, 'diag_status', {})
166
+ check('A13.1', 'diag_status 仍正常(最近记录/空态)', !isErr(st), text(st).slice(0, 120))
167
+ const hlt = await fetch(`${BASE}/api/plugins/diag-bridge/health`, { headers: H })
168
+ const hltJ = await hlt.json().catch(() => ({}))
169
+ check('A13.2', '/health 路由仍正常(token accepted)', hlt.status === 200 && hltJ?.token?.accepted !== false, JSON.stringify(hltJ).slice(0, 140))
170
+ const runs = await fetch(`${BASE}/api/plugins/diag-bridge/runs`, { headers: H })
171
+ check('A13.3', '/runs 路由仍正常', runs.status === 200, `status=${runs.status}`)
172
+
173
+ // ── 报告 ──
174
+ const pass = results.filter(r => r.pass).length
175
+ writeFileSync(join(EVID, 'report.json'), JSON.stringify({ script: 'scripts/e2e-idd-results.mjs', generatedAt: new Date().toISOString(), base: BASE, pass, total: results.length, results }, null, 2))
176
+ console.log(`\nIDD-RESULTS E2E: ${pass}/${results.length} passed, ${results.length - pass} failed\nevidence: ${join(process.cwd(), EVID)}`)
177
+ process.exit(pass === results.length ? 0 : 1)
@@ -357,6 +357,7 @@ let draftId
357
357
  const ontologyDoc = (overrides = {}) => ({
358
358
  schemaVersion: 1,
359
359
  name: `模型闭环验收-${TAG}`,
360
+ description: `膜厚闭环控制本体:压力/线速→膜厚,温区守门(${TAG})`,
360
361
  lineId: line.id,
361
362
  entities: [
362
363
  { key: 'pv.melt_pressure', kind: 'process_variable', name: '熔体压力', description: '', unit: 'bar', dimension: 'pressure', role: 'control', attrs: { dataType: 'number' } },
@@ -409,6 +410,8 @@ async function approveRule(draft, ruleId) {
409
410
  draftId = data(created)?.draft?.id ?? ''
410
411
  const saved = await api('PATCH', `/api/workshop/ontology/drafts/${encodeURIComponent(draftId)}`, { doc: ontologyDoc(), expectedRev: 1 }, token)
411
412
  check('M1.1', '本体起草(活体校验+绑定通过)', created.status === 200 && saved.status === 200 && data(saved)?.validation?.ok === true, `saved=${saved.status} issues=${JSON.stringify((data(saved)?.validation?.issues ?? []).filter(i => i.severity === 'error').slice(0, 2))}`)
413
+ const detail0 = data(await api('GET', `/api/workshop/ontology/drafts/${encodeURIComponent(draftId)}`, undefined, token))
414
+ check('M1.1b', '本体描述可读(用户理解模型代表什么)', String(detail0?.doc?.description ?? '').includes('膜厚闭环控制本体'), String(detail0?.doc?.description ?? '').slice(0, 60))
412
415
  await approveRule(draftId, 'R-BOUND')
413
416
  await approveRule(draftId, 'R-GUARD')
414
417
  const pub1 = await api('POST', `/api/workshop/ontology/drafts/${encodeURIComponent(draftId)}/publish`, {}, token)
@@ -427,6 +430,21 @@ async function approveRule(draft, ruleId) {
427
430
  await approveRule(draftId, 'R-GUARD')
428
431
  const pub2 = await api('POST', `/api/workshop/ontology/drafts/${encodeURIComponent(draftId)}/publish`, {}, token)
429
432
  check('M1.3', '管理者修正规则窗 → v2 发布', pub2.status === 200 && data(pub2)?.version?.version === 2, `saved=${saved2.status}/${errCode(saved2)} pub=${pub2.status}/${errCode(pub2)}`)
433
+ const messy = ontologyDoc()
434
+ messy.description = ''
435
+ for (const e of messy.entities) e.description = ''
436
+ for (const r of messy.rules) { r.description = ''; r.scope.lineId = '' }
437
+ for (const b of messy.bindings) b.scope = 'global'
438
+ const createFix = await invokeTool('ontology_draft_create', { ontology_id: `${ONT}-fix`, line_id: line.id, name: `修复验收-${TAG}` })
439
+ const createFixText = String(createFix?.data?.text ?? createFix?.data?.result?.text ?? createFix?.text ?? '')
440
+ const draft3 = (createFixText.match(/已创建草稿\s+(\S+?)\(/) ?? [])[1] ?? ''
441
+ const savedMessy = createFix ? await api('PATCH', `/api/workshop/ontology/drafts/${encodeURIComponent(draft3)}`, { doc: messy, expectedRev: 1 }, token) : { status: 0 }
442
+ const fixRes = await invokeTool('ontology_draft_autofix', { draft_id: draft3 })
443
+ const fixText = String(fixRes?.data?.text ?? fixRes?.data?.result?.text ?? fixRes?.text ?? JSON.stringify(fixRes ?? {}))
444
+ const fixErr = Boolean(fixRes?.isError ?? fixRes?.data?.isError)
445
+ check('M1.5', 'Agent 工具 ontology_draft_autofix:自动修复并落库', !fixErr && /自动修复 \d+ 项/.test(fixText), fixText.slice(0, 180))
446
+ const detail3 = data(await api('GET', `/api/workshop/ontology/drafts/${encodeURIComponent(draft3)}`, undefined, token))
447
+ check('M1.6', '修复后:描述/作用域已补齐且校验通过', Boolean(detail3?.doc?.description) && detail3?.validation?.ok === true && (detail3?.doc?.bindings ?? []).every(b => String(b.scope).startsWith('line:')), `desc=${String(detail3?.doc?.description ?? '').slice(0, 40)} savedMessy=${savedMessy.status}`)
430
448
  const cmp = await api('GET', `/api/workshop/ontology/versions/${encodeURIComponent(ONT)}/compare?from=1&to=2`, undefined, token)
431
449
  const changed = data(cmp)?.rules?.changed ?? []
432
450
  check('M1.4', '四段 diff 反映管理者意志(R-BOUND changed)', cmp.status === 200 && changed.some(c => String(typeof c === 'string' ? c : (c.id ?? c.ruleId ?? '')).includes('R-BOUND')), JSON.stringify(changed).slice(0, 200))
@@ -547,8 +565,8 @@ async function trainOnce(modelName) {
547
565
  const model = (data(models)?.models ?? []).find(m => m.id === (job?.modelId ?? ''))
548
566
  return { datasetId, rowCount: data(ds)?.rowCount ?? 0, jobId, job, modelId: job?.modelId ?? '', artifactHash: model?.artifactHash ?? '', eligOk }
549
567
  }
550
- async function adoptRound(modelId, reason) {
551
- const adoptInvoke = invokeTool('optimizer_profile_propose', { model_id: modelId, reason }, 300_000)
568
+ async function adoptRound(modelId, reason, description) {
569
+ const adoptInvoke = invokeTool('optimizer_profile_propose', { model_id: modelId, reason, profile_description: description }, 300_000)
552
570
  let card = null
553
571
  for (let i = 0; i < 60; i++) {
554
572
  await sleep(500)
@@ -580,6 +598,9 @@ let round1RowCount
580
598
  trainedAId = ra.modelId
581
599
  trainedAHash = ra.artifactHash
582
600
  round1RowCount = ra.rowCount
601
+ const annotate = await invokeTool('aml_model_annotate', { model_id: ra.modelId, label: `膜厚模型A-${TAG}`, description: '产线A 膜厚预测:线性状态空间,适配保压/线速工况' })
602
+ const annotateText = toolText(annotate)
603
+ check('M3.0', 'Agent 工具 aml_model_annotate:补模型名称/描述', !toolErr(annotate) && annotateText.includes('人读身份已更新'), annotateText.slice(0, 140))
583
604
  check('M3.1', '第 1 轮训练 done + 模型登记 + 优化资格(artifactHash)', ra.job?.status === 'done' && ra.eligOk && trainedAId && trainedAHash.length === 64, `status=${ra.job?.status} model=${trainedAId} rows=${ra.rowCount} err=${String(ra.job?.error ?? '').slice(0, 100)}`)
584
605
 
585
606
  const profileBody = {
@@ -608,7 +629,7 @@ let round1RowCount
608
629
  trainedBHash = rb.artifactHash
609
630
  check('M3.5', '第 2 轮训练 done + 资格(数据集不缩水,工件不同)', rb.job?.status === 'done' && rb.eligOk && trainedBId && rb.rowCount >= round1RowCount && trainedBHash !== trainedAHash, `status=${rb.job?.status} rows ${round1RowCount}→${rb.rowCount} hashDiff=${trainedAHash !== trainedBHash}`)
610
631
 
611
- const adopt1 = await adoptRound(trainedBId, '模型进化第 1 轮采纳:换上新训练模型 B')
632
+ const adopt1 = await adoptRound(trainedBId, '模型进化第 1 轮采纳:换上新训练模型 B', '产线A 膜厚闭环:线性 MPC(采纳模型B,提升 rollout 精度)')
612
633
  check('M3.6', '采纳卡挂出(optimizer-profile:<id>@<v>)', Boolean(adopt1.card), `nodeId=${adopt1.card?.nodeId ?? 'none'}`)
613
634
  check('M3.7', 'HITL 批准 → 单一咽喉发布+重绑', adopt1.dec.status === 200 && (JSON.stringify(adopt1.dec).includes('published') || JSON.stringify(adopt1.dec).includes('已发布')), JSON.stringify(adopt1.dec).slice(0, 300))
614
635
  const adoptStr1 = String(adopt1.adoptText?.data?.text ?? adopt1.adoptText?.data?.result?.text ?? adopt1.adoptText?.text ?? JSON.stringify(adopt1.adoptText)).slice(0, 240)
@@ -620,6 +641,7 @@ let round1RowCount
620
641
  check('M3.9', '绑定自动重绑到采纳版本(revision+1)', Boolean(rebound1) && Number(rebound1?.revision) >= 1, `versions=[${binds1.map(b => b.profileVersionNumber).join(',')}] card=v${cardV1} rev=${rebound1?.revision}`)
621
642
  const profs1 = JSON.stringify(data(await api('GET', `/api/workshop/optimization/profiles?limit=50`, undefined, token)) ?? {})
622
643
  check('M3.10', '已发布 Profile v2 携带新模型工件 B', profs1.includes(trainedBId), `len=${profs1.length}`)
644
+ check('M3.10b', 'Profile 描述由 Agent 提议写入并落版本台账', profs1.includes('产线A 膜厚闭环:线性 MPC(采纳模型B'), '')
623
645
  writeFreshTail()
624
646
  const solve1 = await api('POST', '/api/workshop/optimization/solve', { agentInstanceId: leadAgentIdOuter, bindingId: rebound1?.id }, token)
625
647
  check('M3.11', '新模型 B solve optimal', solve1.status === 200 && data(solve1)?.result?.status === 'optimal', `status=${data(solve1)?.result?.status} http=${solve1.status} msg=${String(solve1.message ?? '').slice(0, 120)}`)
@@ -632,7 +654,7 @@ console.log('\n=== M4 模型进化第 2 轮(持续迭代) ===')
632
654
  trainedCHash = rc.artifactHash
633
655
  check('M4.1', '第 3 次训练 done + 资格(反馈持续积累)', rc.job?.status === 'done' && rc.eligOk && trainedCId && trainedCHash.length === 64, `status=${rc.job?.status} model=${trainedCId} rows=${rc.rowCount}`)
634
656
 
635
- const adopt2 = await adoptRound(trainedCId, '模型进化第 2 轮采纳:持续迭代换新模型 C')
657
+ const adopt2 = await adoptRound(trainedCId, '模型进化第 2 轮采纳:持续迭代换新模型 C', '产线A 膜厚闭环:线性 MPC(采纳模型C,持续迭代)')
636
658
  check('M4.2', '第 2 轮采纳卡挂出+HITL 批准', Boolean(adopt2.card) && adopt2.dec.status === 200, `nodeId=${adopt2.card?.nodeId ?? 'none'} dec=${adopt2.dec.status}`)
637
659
  const adoptStr2 = String(adopt2.adoptText?.data?.text ?? adopt2.adoptText?.data?.result?.text ?? adopt2.adoptText?.text ?? JSON.stringify(adopt2.adoptText)).slice(0, 240)
638
660
  check('M4.3', '第 2 轮工具回执:采纳完成', adoptStr2.includes('模型采纳完成'), adoptStr2)
@@ -687,17 +709,49 @@ process.env.AW_BASE = BASE
687
709
  const targets = [['/optimizer', 'optimizer'], ['/aml', 'aml'], ['/ontology', 'ontology']]
688
710
  let allOk = true
689
711
  const detail = []
712
+ const bodies = {}
690
713
  for (const [path, name] of targets) {
691
714
  const errsBefore = pageErrors.length
692
715
  await gotoReady(page, path, { wait: 2500 })
693
716
  await sleep(800)
694
717
  const bodyLen = await page.evaluate(() => (document.body.textContent ?? '').length)
718
+ bodies[name] = await page.evaluate(() => document.body.textContent ?? '')
695
719
  const ok = pageErrors.length === errsBefore && bodyLen > 400
696
720
  detail.push(`${name}:len=${bodyLen},errs=${pageErrors.length - errsBefore}`)
697
721
  if (!ok) allOk = false
698
722
  await shot(`page-${name}`)
699
723
  }
700
724
  check('M6.1', '管理者三台(/optimizer /aml /ontology)渲染无错', allOk, detail.join(' '))
725
+ // 数据异步加载:轮询等待关键文案(最多 10s),并切到 Profile tab
726
+ const waitText = async (needle, timeoutMs = 10_000) => {
727
+ const t0 = Date.now()
728
+ while (Date.now() - t0 < timeoutMs) {
729
+ const hit = await page.evaluate(n => (document.body.textContent ?? '').includes(n), needle)
730
+ if (hit) return true
731
+ await sleep(500)
732
+ }
733
+ return false
734
+ }
735
+ await gotoReady(page, '/optimizer', { wait: 2500 })
736
+ await page.evaluate(() => {
737
+ const btn = Array.from(document.querySelectorAll('button')).find(b => (b.textContent || '').includes('Profile'))
738
+ if (btn) btn.click()
739
+ })
740
+ await sleep(600)
741
+ const profileDescVisible = await waitText('产线A 膜厚闭环')
742
+ check('M6.3', 'UI:Profile 描述在 /optimizer 台账可见', profileDescVisible)
743
+ await shot('page-optimizer-profile')
744
+
745
+ await gotoReady(page, '/aml', { wait: 2500 })
746
+ const amlDescVisible = await waitText('产线A 膜厚预测', 12_000)
747
+ check('M6.4', 'UI:模型描述在 /aml 台账可见', amlDescVisible)
748
+ await shot('page-aml-models')
749
+
750
+ await gotoReady(page, '/ontology', { wait: 2500 })
751
+ const ontoDescVisible = (await waitText('膜厚闭环控制本体', 6000)) || (await waitText('(产线 ln-', 4000))
752
+ const fixBtnVisible = await page.evaluate(() => (document.body.textContent ?? '').includes('自动修复'))
753
+ check('M6.5', 'UI:本体描述与「自动修复」入口在 /ontology 可见', ontoDescVisible && fixBtnVisible, `desc=${ontoDescVisible} fixBtn=${fixBtnVisible}`)
754
+ await shot('page-ontology-desc')
701
755
  check('M6.2', '全程无未捕获 pageerror', pageErrors.length === 0 || pageErrors.every(e => e.includes('dispose')), pageErrors.slice(0, 2).join(';'))
702
756
  }
703
757
  finally {
@@ -676,6 +676,79 @@ console.log('\n=== L6 数据分析 ===')
676
676
  check('L6.2', 'GET /analysis 台账读回', list.status === 200 && JSON.stringify(data(list) ?? list).includes(`本体验收分析-${TAG}`), `status=${list.status} body=${JSON.stringify(list).slice(0, 260)}`)
677
677
  }
678
678
 
679
+ // ════ ON16 邻接查询 REST(已发布面 + 草稿面) ════
680
+ console.log('\n=== ON16 邻接查询 REST ===')
681
+ {
682
+ const base = `/api/workshop/ontology/scene?lineId=${encodeURIComponent(line.id)}`
683
+ const one = await api('GET', `${base}&entity=pv.melt_pressure&hops=1`, undefined, token)
684
+ const oneSub = data(one)?.subgraph
685
+ check('ON16.1', 'GET /scene?entity= 返回子图(center+nodes+edges)', one.status === 200
686
+ && oneSub?.center?.key === 'pv.melt_pressure'
687
+ && oneSub?.nodes?.length === 2
688
+ && oneSub?.edges?.length === 1
689
+ && oneSub?.edges?.[0]?.direction === 'out', JSON.stringify(oneSub && { nodes: oneSub.nodes, edges: oneSub.edges }))
690
+ const two = await api('GET', `${base}&entity=pv.melt_pressure&hops=2`, undefined, token)
691
+ const twoSub = data(two)?.subgraph
692
+ const speed = twoSub?.nodes?.find(n => n.key === 'st.line_speed')
693
+ const rel2 = twoSub?.edges?.find(e => e.id === 'rel-2')
694
+ check('ON16.2', 'hops=2 出现间接节点 st.line_speed@2 与 rel-2(hop2/in)', speed?.hop === 2 && rel2?.hop === 2 && rel2?.direction === 'in',
695
+ JSON.stringify({ speed, rel2 }))
696
+ const noEntity = await api('GET', `${base}&hops=2&direction=out&kinds=influences`, undefined, token)
697
+ const plain = await api('GET', base, undefined, token)
698
+ check('ON16.3', '无 entity 时新参数被忽略:与历史全图响应完全一致',
699
+ noEntity.status === plain.status && JSON.stringify(data(noEntity)) === JSON.stringify(data(plain)),
700
+ `status=${noEntity.status}/${plain.status}`)
701
+ const keys = Object.keys(data(plain)?.graph ?? {}).join(',')
702
+ check('ON16.4', '无 entity 的 graph 顶层结构不变', keys === 'ontologyId,version,lineId,entities,relations,rules,guards', keys)
703
+ const badHops = await api('GET', `${base}&entity=pv.melt_pressure&hops=4`, undefined, token)
704
+ check('ON16.5', 'hops 越界 → 422 ONTOLOGY_SUBGRAPH_HOPS_INVALID',
705
+ badHops.status === 422 && String(data(badHops)?.code ?? badHops.code ?? '').includes('HOPS_INVALID'), JSON.stringify(badHops).slice(0, 160))
706
+ const ghost = await api('GET', `${base}&entity=ghost.key`, undefined, token)
707
+ check('ON16.6', '未知实体 → 404 ONTOLOGY_SUBGRAPH_ENTITY_NOT_FOUND', ghost.status === 404, `status=${ghost.status}`)
708
+ const draftQuery = `/api/workshop/ontology/drafts/${encodeURIComponent(draftId)}/subgraph?entity=pv.melt_pressure&hops=1`
709
+ const draftSub = await api('GET', draftQuery, undefined, token)
710
+ const draftBody = data(draftSub)?.subgraph
711
+ check('ON16.7', '草稿子图端点可用(UI 图与抽屉同源)', draftSub.status === 200
712
+ && draftBody?.center?.key === 'pv.melt_pressure'
713
+ && draftBody?.nodes?.length === 2, JSON.stringify(draftBody).slice(0, 200))
714
+ const draftBad = await api('GET', `/api/workshop/ontology/drafts/${encodeURIComponent(draftId)}/subgraph`, undefined, token)
715
+ check('ON16.8', '草稿子图缺 entity → 422 ONTOLOGY_ENTITY_REQUIRED', draftBad.status === 422, `status=${draftBad.status}`)
716
+ }
717
+
718
+ // ════ ON17 Agent 只读工具:ontology_node_neighbors ════
719
+ console.log('\n=== ON17 Agent 邻接工具 ===')
720
+ {
721
+ const invokeNeighbors = await api('POST', '/api/workshop/agent-tools/invoke', {
722
+ agentId: leadAgentIdOuter,
723
+ tool: 'ontology_node_neighbors',
724
+ args: { line_id: line.id, entity_key: 'pv.melt_pressure', hops: 1 },
725
+ }, token)
726
+ const text1 = String(data(invokeNeighbors)?.result?.text ?? '')
727
+ check('ON17.1', '工具 hops=1 返回节点/边明细', invokeNeighbors.status === 200
728
+ && data(invokeNeighbors)?.result?.isError !== true
729
+ && text1.includes('nodes=2 edges=1')
730
+ && text1.includes('pv.melt_pressure')
731
+ && text1.includes('cv.thickness')
732
+ && text1.includes('rel-1'), text1.slice(0, 240))
733
+ const invokeTwo = await api('POST', '/api/workshop/agent-tools/invoke', {
734
+ agentId: leadAgentIdOuter,
735
+ tool: 'ontology_node_neighbors',
736
+ args: { line_id: line.id, entity_key: 'pv.melt_pressure', hops: 2 },
737
+ }, token)
738
+ const text2 = String(data(invokeTwo)?.result?.text ?? '')
739
+ check('ON17.2', '工具 hops=2 显示间接节点与 hop 标注',
740
+ text2.includes('st.line_speed hop=2') && text2.includes('rel-2') && text2.includes('hop=2'),
741
+ text2.slice(0, 260))
742
+ const outside = await api('POST', '/api/workshop/agent-tools/invoke', {
743
+ agentId: leadAgentIdOuter,
744
+ tool: 'ontology_node_neighbors',
745
+ args: { line_id: 'ln-not-in-scope', entity_key: 'pv.melt_pressure' },
746
+ }, token)
747
+ const outsideText = String(data(outside)?.result?.text ?? '')
748
+ check('ON17.3', '跨线读取被拦截(引用校验/作用域如实回执)',
749
+ data(outside)?.result?.isError === true && outsideText.includes('不在你的可读范围'), outsideText.slice(0, 160))
750
+ }
751
+
679
752
  // ════ L7 前端渲染走查 ════
680
753
  console.log('\n=== L7 前端渲染 ===')
681
754
  process.env.AW_BASE = BASE
@@ -695,8 +768,70 @@ process.env.AW_BASE = BASE
695
768
  check('L7.2', '/ontology 六 tab 渲染', tabs.length === 6, tabs.join('|'))
696
769
  await shot('ontology-overview')
697
770
 
698
- const tabKeys = ['graph', 'rules', 'bindings', 'versions']
699
- const tabIndex = { graph: 1, rules: 2, bindings: 3, versions: 4 }
771
+ // graph tab 默认 SVG:节点/边数必须与当前草稿一致(图与表格同源)
772
+ await page.evaluate(() => {
773
+ const btn = Array.from(document.querySelectorAll('.tabs .pill-btn'))[1]
774
+ if (btn) btn.click()
775
+ })
776
+ await sleep(1600)
777
+ const graphInfo = await page.evaluate(() => {
778
+ const root = document.querySelector('[data-testid="ontology-graph"]')
779
+ return {
780
+ nodes: root ? root.querySelectorAll('[data-node-key]').length : -1,
781
+ edges: root ? root.querySelectorAll('[data-edge-id]').length : -1,
782
+ }
783
+ })
784
+ const draftDetail = await api('GET', `/api/workshop/ontology/drafts/${encodeURIComponent(draftId)}`, undefined, token)
785
+ const draftDoc = data(draftDetail)?.doc ?? {}
786
+ const expectedNodes = (draftDoc.entities ?? []).length
787
+ const expectedEdges = (draftDoc.relations ?? []).length
788
+ check('L7.3a', 'graph tab 渲染 SVG 节点/边且与草稿一致',
789
+ graphInfo.nodes === expectedNodes && graphInfo.edges === expectedEdges && graphInfo.nodes > 0,
790
+ `nodes=${graphInfo.nodes}/${expectedNodes} edges=${graphInfo.edges}/${expectedEdges}`)
791
+ await shot('ontology-graph')
792
+
793
+ // 点击节点 → 抽屉:1 跳邻接,再切 2 跳看间接关联
794
+ await page.click('[data-node-key="pv.melt_pressure"]')
795
+ await sleep(1600)
796
+ const drawer1 = await page.evaluate(() => ({
797
+ open: Boolean(document.querySelector('[data-testid="node-drawer"]')),
798
+ neighbors: Array.from(document.querySelectorAll('[data-neighbor-key]')).map(el => el.getAttribute('data-neighbor-key')),
799
+ edges: Array.from(document.querySelectorAll('[data-testid="node-drawer"] [data-edge-id]')).map(el => el.getAttribute('data-edge-id')),
800
+ }))
801
+ check('L7.3b', '点击节点弹出抽屉并列出直接邻接',
802
+ drawer1.open && drawer1.neighbors.includes('cv.thickness') && drawer1.edges.includes('rel-1'),
803
+ JSON.stringify(drawer1))
804
+ await shot('ontology-drawer')
805
+ await page.evaluate(() => {
806
+ const seg = Array.from(document.querySelectorAll('.ant-segmented-item')).find(el => (el.textContent || '').includes('间接关联'))
807
+ if (seg) seg.click()
808
+ })
809
+ await sleep(1600)
810
+ const drawer2 = await page.evaluate(() => ({
811
+ neighbors: Array.from(document.querySelectorAll('[data-neighbor-key]')).map(el => el.getAttribute('data-neighbor-key')),
812
+ edges: Array.from(document.querySelectorAll('[data-testid="node-drawer"] [data-edge-id]')).map(el => el.getAttribute('data-edge-id')),
813
+ }))
814
+ check('L7.3b2', '抽屉切 2 跳后出现间接节点 st.line_speed 与 rel-2',
815
+ drawer2.neighbors.includes('st.line_speed') && drawer2.edges.includes('rel-2'), JSON.stringify(drawer2))
816
+ await shot('ontology-drawer-hops2')
817
+ await page.keyboard.press('Escape').catch(() => {})
818
+ await sleep(600)
819
+
820
+ // 切到表视图:实体表与关系表都要有行
821
+ await page.evaluate(() => {
822
+ const seg = Array.from(document.querySelectorAll('.ant-segmented-item')).find(el => (el.textContent || '').trim() === '表')
823
+ if (seg) seg.click()
824
+ })
825
+ await sleep(1400)
826
+ const tableInfo = await page.evaluate(() => ({
827
+ entityRows: document.querySelectorAll('[data-testid="entity-table"] .ant-table-tbody tr.ant-table-row').length,
828
+ relationRows: document.querySelectorAll('[data-testid="relation-table"] .ant-table-tbody tr.ant-table-row').length,
829
+ }))
830
+ check('L7.3c', '切到表视图:实体表与关系表均有行', tableInfo.entityRows > 0 && tableInfo.relationRows > 0, JSON.stringify(tableInfo))
831
+ await shot('ontology-graph-table')
832
+
833
+ const tabKeys = ['rules', 'bindings', 'versions']
834
+ const tabIndex = { rules: 2, bindings: 3, versions: 4 }
700
835
  let renderedOk = true
701
836
  const renderDetail = []
702
837
  for (const key of tabKeys) {
@@ -713,7 +848,7 @@ process.env.AW_BASE = BASE
713
848
  if (info.rows === 0 && info.empty === 0) renderedOk = false
714
849
  await shot(`ontology-${key}`)
715
850
  }
716
- check('L7.3', '四个内容 tab 表格渲染非空', renderedOk, renderDetail.join(' '))
851
+ check('L7.3d', '规则/绑定/版本三 tab 表格渲染非空', renderedOk, renderDetail.join(' '))
717
852
 
718
853
  // 编译预览:真实点击工具栏按钮 → 产物面板 + Rule Trace 表
719
854
  await page.evaluate(() => {