agentworkshop 0.7.71 → 0.8.0

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 (358) hide show
  1. package/.AgentWorkShop/prompts/host-tools.json +332 -0
  2. package/.output/.AgentWorkShop/prompts/host-tools.json +332 -0
  3. package/.output/nitro.json +1 -1
  4. package/.output/public/_nuxt/BH8RvpVy.js +1 -0
  5. package/.output/public/_nuxt/Byf4IxU2.js +14 -0
  6. package/.output/public/_nuxt/CxVhG0Xx.js +1 -0
  7. package/.output/public/_nuxt/D0mzKkZr.js +1 -0
  8. package/.output/public/_nuxt/DIFkTkdS.js +1 -0
  9. package/.output/public/_nuxt/DgrK8UCQ.js +0 -0
  10. package/.output/public/_nuxt/builds/latest.json +1 -1
  11. package/.output/public/_nuxt/builds/meta/7a79a7e4-d691-4cf5-ae3a-3b01814479fb.json +1 -0
  12. package/.output/public/_nuxt/{default.BzOcvmSE.css → default.BEXGWZFQ.css} +1 -1
  13. package/.output/public/_nuxt/{entry.CL2i0F8o.css → entry.C7koBPom.css} +1 -1
  14. package/.output/public/_nuxt/ontology.QMGeh66l.css +1 -0
  15. package/.output/server/chunks/_/access.mjs +1 -1
  16. package/.output/server/chunks/_/binding-authz.mjs +1 -1
  17. package/.output/server/chunks/_/catalog-view.mjs +1 -1
  18. package/.output/server/chunks/_/character-asset.repo.mjs +1 -1
  19. package/.output/server/chunks/_/chart-repo.mjs +1 -1
  20. package/.output/server/chunks/_/dashboard-repo.mjs +1 -1
  21. package/.output/server/chunks/_/data-export.mjs +6 -6
  22. package/.output/server/chunks/_/data-query.mjs +3 -3
  23. package/.output/server/chunks/_/eda-run.repo.mjs +2 -2
  24. package/.output/server/chunks/_/entity.mjs +1 -1
  25. package/.output/server/chunks/_/features.mjs +5 -5
  26. package/.output/server/chunks/_/golden.mjs +3 -3
  27. package/.output/server/chunks/_/host-bindings.mjs +1 -1
  28. package/.output/server/chunks/_/index.mjs +1 -1
  29. package/.output/server/chunks/_/mes-console.mjs +1 -1
  30. package/.output/server/chunks/_/nitro.mjs +5362 -2240
  31. package/.output/server/chunks/_/nitro.mjs.map +1 -1
  32. package/.output/server/chunks/_/ocap.mjs +1 -1
  33. package/.output/server/chunks/_/rest-auth.mjs +1 -1
  34. package/.output/server/chunks/_/scene-layout.repo.mjs +1 -1
  35. package/.output/server/chunks/_/spc.mjs +2 -2
  36. package/.output/server/chunks/build/TownView-BWMDbosY.mjs +1 -1
  37. package/.output/server/chunks/build/api-BEW_ebY_.mjs +64 -0
  38. package/.output/server/chunks/build/api-BEW_ebY_.mjs.map +1 -0
  39. package/.output/server/chunks/build/daq-CdxcfY_G.mjs +1 -1
  40. package/.output/server/chunks/build/dcw-BlDQtS4q.mjs +1 -1
  41. package/.output/server/chunks/build/{default-BeB88U7y.mjs → default-CJkOcmrm.mjs} +14 -8
  42. package/.output/server/chunks/build/{default-BeB88U7y.mjs.map → default-CJkOcmrm.mjs.map} +1 -1
  43. package/.output/server/chunks/build/ontology-C3HS5pMo.mjs +977 -0
  44. package/.output/server/chunks/build/ontology-C3HS5pMo.mjs.map +1 -0
  45. package/.output/server/chunks/build/types-D6J7slEa.mjs +6 -2
  46. package/.output/server/chunks/build/useDaqAddNode-D_Rkju0f.mjs +1 -1
  47. package/.output/server/chunks/build/useDaqDetailNode-DeOsDxK5.mjs +1 -1
  48. package/.output/server/chunks/build/useDaqDetailParams-Cm9a9r5G.mjs +1 -1
  49. package/.output/server/chunks/build/useDaqFilters-CctmO03p.mjs +1 -1
  50. package/.output/server/chunks/build/useDaqStream-B9ZBVQrI.mjs +1 -1
  51. package/.output/server/chunks/build/useDaqTemplates-CK37sMfi.mjs +1 -1
  52. package/.output/server/chunks/build/useDcwAddNode-DACVcEHs.mjs +1 -1
  53. package/.output/server/chunks/build/useDcwStream-Dir5ufAU.mjs +1 -1
  54. package/.output/server/chunks/routes/api/mcp/workshop.mjs +1 -1
  55. package/.output/server/chunks/routes/api/system/backup/run.post.mjs +2 -2
  56. package/.output/server/chunks/routes/api/workshop/agent-tools/approvals/_id/decide.post.mjs +17 -4
  57. package/.output/server/chunks/routes/api/workshop/agent-tools/approvals/_id/decide.post.mjs.map +1 -1
  58. package/.output/server/chunks/routes/api/workshop/agent-tools/bindings/_id_.delete.mjs +1 -1
  59. package/.output/server/chunks/routes/api/workshop/agent-tools/bindings/_id_.patch.mjs +1 -1
  60. package/.output/server/chunks/routes/api/workshop/agent-tools/bindings/grant.post.mjs +1 -1
  61. package/.output/server/chunks/routes/api/workshop/agent-tools/bindings/revoke.post.mjs +1 -1
  62. package/.output/server/chunks/routes/api/workshop/agent-tools/index.get.mjs +1 -1
  63. package/.output/server/chunks/routes/api/workshop/agent-tools/index.post.mjs +1 -1
  64. package/.output/server/chunks/routes/api/workshop/agent-tools/index2.get.mjs +1 -1
  65. package/.output/server/chunks/routes/api/workshop/agent-tools/invoke.post.mjs +1 -1
  66. package/.output/server/chunks/routes/api/workshop/agent-tools/list.get.mjs +1 -1
  67. package/.output/server/chunks/routes/api/workshop/aml/datasets/_id/preview.get.mjs +1 -1
  68. package/.output/server/chunks/routes/api/workshop/aml/datasets/_id_.delete.mjs +1 -1
  69. package/.output/server/chunks/routes/api/workshop/aml/datasets/_id_.get.mjs +1 -1
  70. package/.output/server/chunks/routes/api/workshop/aml/datasets/_id_.patch.mjs +1 -1
  71. package/.output/server/chunks/routes/api/workshop/aml/env/recheck.post.mjs +1 -1
  72. package/.output/server/chunks/routes/api/workshop/aml/env/uv.post.mjs +1 -1
  73. package/.output/server/chunks/routes/api/workshop/aml/env/venv.post.mjs +1 -1
  74. package/.output/server/chunks/routes/api/workshop/aml/index.get.mjs +1 -1
  75. package/.output/server/chunks/routes/api/workshop/aml/index.post.mjs +1 -1
  76. package/.output/server/chunks/routes/api/workshop/aml/index2.post.mjs +1 -1
  77. package/.output/server/chunks/routes/api/workshop/aml/index3.get.mjs +1 -1
  78. package/.output/server/chunks/routes/api/workshop/aml/index3.post.mjs +1 -1
  79. package/.output/server/chunks/routes/api/workshop/aml/index4.get.mjs +1 -1
  80. package/.output/server/chunks/routes/api/workshop/aml/index5.get.mjs +1 -1
  81. package/.output/server/chunks/routes/api/workshop/aml/index6.get.mjs +1 -1
  82. package/.output/server/chunks/routes/api/workshop/aml/index7.get.mjs +1 -1
  83. package/.output/server/chunks/routes/api/workshop/aml/jobs/_id/cancel.post.mjs +1 -1
  84. package/.output/server/chunks/routes/api/workshop/aml/jobs/_id/logs.get.mjs +1 -1
  85. package/.output/server/chunks/routes/api/workshop/aml/jobs/_id/retry.post.mjs +1 -1
  86. package/.output/server/chunks/routes/api/workshop/aml/jobs/_id_.delete.mjs +1 -1
  87. package/.output/server/chunks/routes/api/workshop/aml/jobs/_id_.get.mjs +1 -1
  88. package/.output/server/chunks/routes/api/workshop/aml/models/_id/predict.post.mjs +1 -1
  89. package/.output/server/chunks/routes/api/workshop/aml/models/_id/promote.post.mjs +1 -1
  90. package/.output/server/chunks/routes/api/workshop/aml/models/_id_.delete.mjs +1 -1
  91. package/.output/server/chunks/routes/api/workshop/aml/models/_id_.patch.mjs +1 -1
  92. package/.output/server/chunks/routes/api/workshop/aml/training-plans/_id/train.post.mjs +1 -1
  93. package/.output/server/chunks/routes/api/workshop/aml/training-plans/_id_.delete.mjs +1 -1
  94. package/.output/server/chunks/routes/api/workshop/aml/training-plans/_id_.patch.mjs +1 -1
  95. package/.output/server/chunks/routes/api/workshop/aml/twin/providers.get.mjs +1 -1
  96. package/.output/server/chunks/routes/api/workshop/analysis/_id_.delete.mjs +1 -1
  97. package/.output/server/chunks/routes/api/workshop/analysis/_id_.get.mjs +1 -1
  98. package/.output/server/chunks/routes/api/workshop/analysis/_id_.patch.mjs +1 -1
  99. package/.output/server/chunks/routes/api/workshop/approvals/_id/decide.post.mjs +1 -1
  100. package/.output/server/chunks/routes/api/workshop/assets/index.post.mjs +1 -1
  101. package/.output/server/chunks/routes/api/workshop/assets/index2.post.mjs +1 -1
  102. package/.output/server/chunks/routes/api/workshop/channel-templates/_id/instantiate.post.mjs +2 -2
  103. package/.output/server/chunks/routes/api/workshop/channels/_id/activate.post.mjs +1 -1
  104. package/.output/server/chunks/routes/api/workshop/channels/_id/chat/index.post.mjs +1 -1
  105. package/.output/server/chunks/routes/api/workshop/channels/_id/index.post.mjs +1 -1
  106. package/.output/server/chunks/routes/api/workshop/channels/_id/index.put.mjs +1 -1
  107. package/.output/server/chunks/routes/api/workshop/channels/_id/index2.put.mjs +1 -1
  108. package/.output/server/chunks/routes/api/workshop/channels/_id/index3.post.mjs +1 -1
  109. package/.output/server/chunks/routes/api/workshop/channels/_id/index4.post.mjs +1 -1
  110. package/.output/server/chunks/routes/api/workshop/channels/_id/index5.get.mjs +1 -1
  111. package/.output/server/chunks/routes/api/workshop/channels/_id/line.put.mjs +1 -1
  112. package/.output/server/chunks/routes/api/workshop/channels/_id/members/join.post.mjs +1 -1
  113. package/.output/server/chunks/routes/api/workshop/channels/_id/terminals.get.mjs +1 -1
  114. package/.output/server/chunks/routes/api/workshop/channels/_id/tools/reset.post.mjs +1 -1
  115. package/.output/server/chunks/routes/api/workshop/channels/_id/twin-profile.get.mjs +1 -1
  116. package/.output/server/chunks/routes/api/workshop/channels/_id/twin-profile.patch.mjs +1 -1
  117. package/.output/server/chunks/routes/api/workshop/channels/index.get.mjs +1 -1
  118. package/.output/server/chunks/routes/api/workshop/channels.post.mjs +7 -7
  119. package/.output/server/chunks/routes/api/workshop/daq/_id/bind.post.mjs +1 -1
  120. package/.output/server/chunks/routes/api/workshop/daq/_id/bindings.put.mjs +1 -1
  121. package/.output/server/chunks/routes/api/workshop/daq/_id/frames/content.get.mjs +1 -1
  122. package/.output/server/chunks/routes/api/workshop/daq/_id/frames.get.mjs +1 -1
  123. package/.output/server/chunks/routes/api/workshop/daq/_id/ingest.post.mjs +2 -2
  124. package/.output/server/chunks/routes/api/workshop/daq/_id/samples.get.mjs +1 -1
  125. package/.output/server/chunks/routes/api/workshop/daq/_id/test.post.mjs +1 -1
  126. package/.output/server/chunks/routes/api/workshop/daq/_id_.delete.mjs +1 -1
  127. package/.output/server/chunks/routes/api/workshop/daq/_id_.patch.mjs +1 -1
  128. package/.output/server/chunks/routes/api/workshop/daq/alarms/_id/ack.post.mjs +1 -1
  129. package/.output/server/chunks/routes/api/workshop/daq/alarms.get.mjs +1 -1
  130. package/.output/server/chunks/routes/api/workshop/daq/controller.post.mjs +1 -1
  131. package/.output/server/chunks/routes/api/workshop/daq/export/_id_.get.mjs +1 -1
  132. package/.output/server/chunks/routes/api/workshop/daq/index2.post.mjs +1 -1
  133. package/.output/server/chunks/routes/api/workshop/daq/infra/reconnect.post.mjs +1 -1
  134. package/.output/server/chunks/routes/api/workshop/daq/infra.get.mjs +1 -1
  135. package/.output/server/chunks/routes/api/workshop/daq/templates/_key_.delete.mjs +1 -1
  136. package/.output/server/chunks/routes/api/workshop/daq/templates/_key_.patch.mjs +1 -1
  137. package/.output/server/chunks/routes/api/workshop/daq/test-driver.post.mjs +1 -1
  138. package/.output/server/chunks/routes/api/workshop/dcw/_id/bind.post.mjs +1 -1
  139. package/.output/server/chunks/routes/api/workshop/dcw/_id/bindings.put.mjs +1 -1
  140. package/.output/server/chunks/routes/api/workshop/dcw/_id/param-ledger.get.mjs +1 -1
  141. package/.output/server/chunks/routes/api/workshop/dcw/_id/read.post.mjs +1 -1
  142. package/.output/server/chunks/routes/api/workshop/dcw/_id/test.post.mjs +1 -1
  143. package/.output/server/chunks/routes/api/workshop/dcw/_id/write.post.mjs +1 -1
  144. package/.output/server/chunks/routes/api/workshop/dcw/_id_.delete.mjs +1 -1
  145. package/.output/server/chunks/routes/api/workshop/dcw/_id_.patch.mjs +1 -1
  146. package/.output/server/chunks/routes/api/workshop/dcw/controller.post.mjs +1 -1
  147. package/.output/server/chunks/routes/api/workshop/dcw/index.get.mjs +1 -1
  148. package/.output/server/chunks/routes/api/workshop/dcw/index.post.mjs +1 -1
  149. package/.output/server/chunks/routes/api/workshop/dcw/index2.get.mjs +1 -1
  150. package/.output/server/chunks/routes/api/workshop/dcw/index2.post.mjs +1 -1
  151. package/.output/server/chunks/routes/api/workshop/dcw/index3.get.mjs +1 -1
  152. package/.output/server/chunks/routes/api/workshop/dcw/index3.post.mjs +1 -1
  153. package/.output/server/chunks/routes/api/workshop/dcw/index4.get.mjs +1 -1
  154. package/.output/server/chunks/routes/api/workshop/dcw/index4.post.mjs +1 -1
  155. package/.output/server/chunks/routes/api/workshop/dcw/index5.get.mjs +1 -1
  156. package/.output/server/chunks/routes/api/workshop/dcw/index5.post.mjs +1 -1
  157. package/.output/server/chunks/routes/api/workshop/dcw/index6.get.mjs +1 -1
  158. package/.output/server/chunks/routes/api/workshop/dcw/index7.get.mjs +1 -1
  159. package/.output/server/chunks/routes/api/workshop/dcw/journal/node/_nodeId/rollback.post.mjs +1 -1
  160. package/.output/server/chunks/routes/api/workshop/dcw/line/query.get.mjs +1 -1
  161. package/.output/server/chunks/routes/api/workshop/dcw/lines/_id/start.post.mjs +1 -1
  162. package/.output/server/chunks/routes/api/workshop/dcw/lines/_id/stop.post.mjs +1 -1
  163. package/.output/server/chunks/routes/api/workshop/dcw/lines/_id_.delete.mjs +1 -1
  164. package/.output/server/chunks/routes/api/workshop/dcw/lines/_id_.patch.mjs +1 -1
  165. package/.output/server/chunks/routes/api/workshop/dcw/mes-artifacts/file.get.mjs +1 -1
  166. package/.output/server/chunks/routes/api/workshop/dcw/mes-hook-test.post.mjs +1 -1
  167. package/.output/server/chunks/routes/api/workshop/dcw/mes-test-read.post.mjs +1 -1
  168. package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id/judge.post.mjs +1 -1
  169. package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id/rollback.post.mjs +1 -1
  170. package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id/series.get.mjs +1 -1
  171. package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id_.get.mjs +1 -1
  172. package/.output/server/chunks/routes/api/workshop/dcw/params/_id/read.post.mjs +1 -1
  173. package/.output/server/chunks/routes/api/workshop/dcw/params/_id/write.post.mjs +1 -1
  174. package/.output/server/chunks/routes/api/workshop/dcw/params/_id_.delete.mjs +1 -1
  175. package/.output/server/chunks/routes/api/workshop/dcw/params/_id_.patch.mjs +1 -1
  176. package/.output/server/chunks/routes/api/workshop/dcw/products/_id_.delete.mjs +1 -1
  177. package/.output/server/chunks/routes/api/workshop/dcw/products/_id_.patch.mjs +1 -1
  178. package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id/apply.post.mjs +1 -1
  179. package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id/mark-good.post.mjs +1 -1
  180. package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id/revert.post.mjs +1 -1
  181. package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id/rollback-good.post.mjs +1 -1
  182. package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id/versions.get.mjs +1 -1
  183. package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id_.delete.mjs +1 -1
  184. package/.output/server/chunks/routes/api/workshop/dcw/recipes/index.patch.mjs +1 -1
  185. package/.output/server/chunks/routes/api/workshop/dcw/runs/_id/close.post.mjs +1 -1
  186. package/.output/server/chunks/routes/api/workshop/dcw/runs/_id/data.get.mjs +1 -1
  187. package/.output/server/chunks/routes/api/workshop/dcw/runs/_id/rollback.post.mjs +1 -1
  188. package/.output/server/chunks/routes/api/workshop/dcw/templates/_key_.delete.mjs +1 -1
  189. package/.output/server/chunks/routes/api/workshop/dcw/templates/_key_.patch.mjs +1 -1
  190. package/.output/server/chunks/routes/api/workshop/dcw/test-driver.post.mjs +1 -1
  191. package/.output/server/chunks/routes/api/workshop/device-twins/_id/control.post.mjs +1 -1
  192. package/.output/server/chunks/routes/api/workshop/device-twins/_id/telemetry.post.mjs +1 -1
  193. package/.output/server/chunks/routes/api/workshop/device-twins/_id_.delete.mjs +1 -1
  194. package/.output/server/chunks/routes/api/workshop/device-twins/_id_.patch.mjs +1 -1
  195. package/.output/server/chunks/routes/api/workshop/eda/commonality.get.mjs +1 -1
  196. package/.output/server/chunks/routes/api/workshop/eda/features/run.post.mjs +1 -1
  197. package/.output/server/chunks/routes/api/workshop/eda/index3.get.mjs +1 -1
  198. package/.output/server/chunks/routes/api/workshop/eda/index6.get.mjs +1 -1
  199. package/.output/server/chunks/routes/api/workshop/eda/index6.post.mjs +1 -1
  200. package/.output/server/chunks/routes/api/workshop/eda/runs/_id/labels.patch.mjs +1 -1
  201. package/.output/server/chunks/routes/api/workshop/eda/runs.get.mjs +1 -1
  202. package/.output/server/chunks/routes/api/workshop/eda/vm/predict.post.mjs +1 -1
  203. package/.output/server/chunks/routes/api/workshop/exp/confirmations/_id/decide.post.mjs +1 -1
  204. package/.output/server/chunks/routes/api/workshop/exp/index.get.mjs +1 -1
  205. package/.output/server/chunks/routes/api/workshop/fs/dirs.get.mjs +1 -1
  206. package/.output/server/chunks/routes/api/workshop/harnesses/_id/providers.get.mjs +1 -1
  207. package/.output/server/chunks/routes/api/workshop/harnesses.get.mjs +1 -1
  208. package/.output/server/chunks/routes/api/workshop/hitl/pending.get.mjs +1 -1
  209. package/.output/server/chunks/routes/api/workshop/hitl/respond.post.mjs +1 -1
  210. package/.output/server/chunks/routes/api/workshop/index.mjs +62 -0
  211. package/.output/server/chunks/routes/api/workshop/index.mjs.map +1 -0
  212. package/.output/server/chunks/routes/api/workshop/index.put.mjs +1 -1
  213. package/.output/server/chunks/routes/api/workshop/index10.get.mjs +1 -1
  214. package/.output/server/chunks/routes/api/workshop/index11.get.mjs +1 -1
  215. package/.output/server/chunks/routes/api/workshop/index12.get.mjs +1 -1
  216. package/.output/server/chunks/routes/api/workshop/index2.get.mjs +1 -1
  217. package/.output/server/chunks/routes/api/workshop/index3.get.mjs +1 -1
  218. package/.output/server/chunks/routes/api/workshop/index3.post.mjs +1 -1
  219. package/.output/server/chunks/routes/api/workshop/index4.post.mjs +1 -1
  220. package/.output/server/chunks/routes/api/workshop/index5.post.mjs +1 -1
  221. package/.output/server/chunks/routes/api/workshop/index6.get.mjs +1 -1
  222. package/.output/server/chunks/routes/api/workshop/index6.post.mjs +1 -1
  223. package/.output/server/chunks/routes/api/workshop/index7.get.mjs +1 -1
  224. package/.output/server/chunks/routes/api/workshop/index8.get.mjs +1 -1
  225. package/.output/server/chunks/routes/api/workshop/mes/datasets.get.mjs +1 -1
  226. package/.output/server/chunks/routes/api/workshop/mes/preview.post.mjs +1 -1
  227. package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/compile.mjs +54 -0
  228. package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/compile.mjs.map +1 -0
  229. package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/evidence.mjs +51 -0
  230. package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/evidence.mjs.map +1 -0
  231. package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/publish.mjs +67 -0
  232. package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/publish.mjs.map +1 -0
  233. package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/rules/_ruleId/approval-decision.mjs +49 -0
  234. package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/rules/_ruleId/approval-decision.mjs.map +1 -0
  235. package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/rules/_ruleId/approval.mjs +35 -0
  236. package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/rules/_ruleId/approval.mjs.map +1 -0
  237. package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/rules/_ruleId/transition.mjs +49 -0
  238. package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/rules/_ruleId/transition.mjs.map +1 -0
  239. package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/validate.mjs +35 -0
  240. package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/validate.mjs.map +1 -0
  241. package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId_.mjs +70 -0
  242. package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId_.mjs.map +1 -0
  243. package/.output/server/chunks/routes/api/workshop/ontology/export/_ontologyId_.mjs +64 -0
  244. package/.output/server/chunks/routes/api/workshop/ontology/export/_ontologyId_.mjs.map +1 -0
  245. package/.output/server/chunks/routes/api/workshop/ontology/index.mjs +44 -0
  246. package/.output/server/chunks/routes/api/workshop/ontology/index.mjs.map +1 -0
  247. package/.output/server/chunks/routes/api/workshop/ontology/scene.mjs +36 -0
  248. package/.output/server/chunks/routes/api/workshop/ontology/scene.mjs.map +1 -0
  249. package/.output/server/chunks/routes/api/workshop/ontology/traces/_ontologyId_.mjs +38 -0
  250. package/.output/server/chunks/routes/api/workshop/ontology/traces/_ontologyId_.mjs.map +1 -0
  251. package/.output/server/chunks/routes/api/workshop/ontology/versions/_ontologyId/compare.mjs +40 -0
  252. package/.output/server/chunks/routes/api/workshop/ontology/versions/_ontologyId/compare.mjs.map +1 -0
  253. package/.output/server/chunks/routes/api/workshop/ontology/versions/_ontologyId_.mjs +63 -0
  254. package/.output/server/chunks/routes/api/workshop/ontology/versions/_ontologyId_.mjs.map +1 -0
  255. package/.output/server/chunks/routes/api/workshop/optimization/capabilities.get.mjs +1 -1
  256. package/.output/server/chunks/routes/api/workshop/optimization/index.get.mjs +1 -1
  257. package/.output/server/chunks/routes/api/workshop/optimization/index.mjs +1 -1
  258. package/.output/server/chunks/routes/api/workshop/optimization/index2.mjs +1 -1
  259. package/.output/server/chunks/routes/api/workshop/optimization/profiles/_id/publish.post.mjs +1 -1
  260. package/.output/server/chunks/routes/api/workshop/optimization/recommendations/_id/crosscheck.post.mjs +1 -1
  261. package/.output/server/chunks/routes/api/workshop/optimization/recommendations/_id/dispatch.post.mjs +1 -1
  262. package/.output/server/chunks/routes/api/workshop/optimization/solve.post.mjs +1 -1
  263. package/.output/server/chunks/routes/api/workshop/plugins/_name/disable.post.mjs +1 -1
  264. package/.output/server/chunks/routes/api/workshop/plugins/_name/enable.post.mjs +1 -1
  265. package/.output/server/chunks/routes/api/workshop/process-model/datasets.post.mjs +1 -1
  266. package/.output/server/chunks/routes/api/workshop/process-model/eligibility.mjs +1 -1
  267. package/.output/server/chunks/routes/api/workshop/process-model/experiments.mjs +1 -1
  268. package/.output/server/chunks/routes/api/workshop/process-model/index.mjs +1 -1
  269. package/.output/server/chunks/routes/api/workshop/process-model/specs/_id/publish.post.mjs +1 -1
  270. package/.output/server/chunks/routes/api/workshop/process-model/train.post.mjs +1 -1
  271. package/.output/server/chunks/routes/api/workshop/scene/layouts/_channelId_.delete.mjs +1 -1
  272. package/.output/server/chunks/routes/api/workshop/scene/layouts/_channelId_.put.mjs +1 -1
  273. package/.output/server/chunks/routes/api/workshop/teams/_id/deploy.post.mjs +1 -1
  274. package/.output/server/chunks/routes/api/workshop/teams/_id/index.put.mjs +1 -1
  275. package/.output/server/chunks/routes/api/workshop/teams/_id/index2.get.mjs +1 -1
  276. package/.output/server/chunks/routes/api/workshop/tools/_name_.get.mjs +1 -1
  277. package/.output/server/chunks/routes/api/workshop/tools/sync.post.mjs +1 -1
  278. package/.output/server/chunks/routes/api/workshop/workspaces/_id/channel-templates/_tplId_.post.mjs +2 -2
  279. package/.output/server/chunks/routes/renderer.mjs +2 -2
  280. package/.output/server/chunks/virtual/entry.mjs +234 -3
  281. package/.output/server/chunks/virtual/precomputed.mjs +1 -1
  282. package/.output/server/package.json +1 -1
  283. package/README-zh.md +27 -6
  284. package/README.md +25 -4
  285. package/app/components/AppSidebar.vue +1 -0
  286. package/app/pages/ontology/api.ts +18 -0
  287. package/app/pages/ontology/index.vue +779 -0
  288. package/app/pages/ontology/types.ts +122 -0
  289. package/config.yml +1 -1
  290. package/docs/cli.en.md +2 -2
  291. package/docs/cli.md +2 -2
  292. package/docs/plugins.en.md +1 -1
  293. package/docs/plugins.md +1 -1
  294. package/docs/sdk.en.md +1 -1
  295. package/docs/sdk.md +1 -1
  296. package/i18n/locales/en.ts +58 -0
  297. package/i18n/locales/zh-CN.ts +58 -0
  298. package/mcp/aw-mcp-server.mjs +35 -1
  299. package/package.json +1 -1
  300. package/scripts/docs-shots.mjs +36 -0
  301. package/scripts/e2e-model-loop-live.mjs +731 -0
  302. package/scripts/e2e-ontology-live.mjs +774 -0
  303. package/scripts/e2e-ontology.mjs +328 -0
  304. package/scripts/ontology-idd-rag-e2e.mjs +449 -0
  305. package/server/api/workshop/agent-tools/approvals/[id]/decide.post.ts +16 -0
  306. package/server/api/workshop/ontology/drafts/[draftId]/compile.ts +39 -0
  307. package/server/api/workshop/ontology/drafts/[draftId]/evidence.ts +33 -0
  308. package/server/api/workshop/ontology/drafts/[draftId]/publish.ts +44 -0
  309. package/server/api/workshop/ontology/drafts/[draftId]/rules/[ruleId]/approval-decision.ts +28 -0
  310. package/server/api/workshop/ontology/drafts/[draftId]/rules/[ruleId]/approval.ts +17 -0
  311. package/server/api/workshop/ontology/drafts/[draftId]/rules/[ruleId]/transition.ts +32 -0
  312. package/server/api/workshop/ontology/drafts/[draftId]/validate.ts +16 -0
  313. package/server/api/workshop/ontology/drafts/[draftId].ts +52 -0
  314. package/server/api/workshop/ontology/drafts/index.ts +20 -0
  315. package/server/api/workshop/ontology/export/[ontologyId].ts +50 -0
  316. package/server/api/workshop/ontology/index.ts +38 -0
  317. package/server/api/workshop/ontology/scene.ts +21 -0
  318. package/server/api/workshop/ontology/traces/[ontologyId].ts +19 -0
  319. package/server/api/workshop/ontology/versions/[ontologyId]/compare.ts +21 -0
  320. package/server/api/workshop/ontology/versions/[ontologyId].ts +42 -0
  321. package/server/services/workshop/agents/hitl-decision/dispatcher.ts +15 -0
  322. package/server/services/workshop/agents/host-tool-bridge/tools/industrial.ts +13 -1
  323. package/server/services/workshop/agents/industrial/grant-guard.ts +59 -0
  324. package/server/services/workshop/agents/industrial/index.ts +38 -32
  325. package/server/services/workshop/agents/industrial/ontology-tools.ts +320 -0
  326. package/server/services/workshop/agents/industrial/optimizer-tools.ts +79 -0
  327. package/server/services/workshop/agents/industrial/tool-verify.ts +32 -2
  328. package/server/services/workshop/agents/tool-reference-spec.ts +1 -1
  329. package/server/services/workshop/aml/twin/physics-spec.ts +6 -22
  330. package/server/services/workshop/daq/storage/index.ts +6 -5
  331. package/server/services/workshop/daq/storage/sqlite.adapter.ts +25 -13
  332. package/server/services/workshop/db/database/open.ts +2 -0
  333. package/server/services/workshop/db/database/schema.ts +155 -1
  334. package/server/services/workshop/ontology/compiler.ts +474 -0
  335. package/server/services/workshop/ontology/contracts.ts +441 -0
  336. package/server/services/workshop/ontology/guards.ts +139 -0
  337. package/server/services/workshop/ontology/index.ts +10 -0
  338. package/server/services/workshop/ontology/ontology.service.ts +892 -0
  339. package/server/services/workshop/ontology/repo.ts +449 -0
  340. package/server/services/workshop/ontology/semantic-binding.service.ts +226 -0
  341. package/server/services/workshop/ontology/validator.ts +218 -0
  342. package/server/services/workshop/optimization/binding.repo.ts +7 -0
  343. package/server/services/workshop/optimization/contracts.ts +14 -0
  344. package/server/services/workshop/optimization/dispatch.service.ts +16 -0
  345. package/server/services/workshop/optimization/profile-adopt.service.ts +256 -0
  346. package/server/services/workshop/optimization/profile.repo.ts +19 -3
  347. package/server/services/workshop/optimization/python/__pycache__/problems.cpython-312.pyc +0 -0
  348. package/shared/dimensions.ts +124 -0
  349. package/.output/public/_nuxt/B7s2qeyT.js +0 -14
  350. package/.output/public/_nuxt/LHIav-Kv.js +0 -1
  351. package/.output/public/_nuxt/RuMLNeQE.js +0 -1
  352. package/.output/public/_nuxt/builds/meta/0ae8cb0f-6ce5-4096-9692-9b1fc197b30d.json +0 -1
  353. /package/.output/public/_nuxt/{62J4vljm2.js → 62J4vljm.js} +0 -0
  354. /package/.output/public/_nuxt/{BO0BJx3w.js → BO0BJx3w2.js} +0 -0
  355. /package/.output/public/_nuxt/{C-MY-JQE2.js → C-MY-JQE.js} +0 -0
  356. /package/.output/public/_nuxt/{D5kCimyw.js → D5kCimyw2.js} +0 -0
  357. /package/.output/public/_nuxt/{DGrrucbG2.js → DGrrucbG.js} +0 -0
  358. /package/.output/public/_nuxt/{Y4sMSPrS.js → Y4sMSPrS2.js} +0 -0
@@ -0,0 +1,218 @@
1
+ /**
2
+ * 本体文档校验(零 DB 纯函数,可单测)。
3
+ *
4
+ * 只做结构/语义自洽判定;存在性、归属、读写能力等「活体」判定在
5
+ * semantic-binding.service(需要查 daq/dcw/recipe 真实对象)。
6
+ *
7
+ * fail-closed 原则:每条问题都带可行动 hint,禁止静默降级。
8
+ */
9
+ import type { CompileIssue, EvidenceLevel, OntologyDraftDoc, OntologyEntity, OntologyRule } from './contracts'
10
+ import {
11
+ ONTOLOGY_STATES,
12
+ RULE_ERROR_CODES,
13
+ entityUnitIssue,
14
+ evidenceLevelRank,
15
+ maxEvidenceLevel,
16
+ unitsCompatible,
17
+ } from './contracts'
18
+
19
+ export interface DraftStats {
20
+ entities: number
21
+ relations: number
22
+ rules: number
23
+ bindings: number
24
+ byState: Record<string, number>
25
+ byEvidence: Record<string, number>
26
+ }
27
+
28
+ export interface DraftValidationReport {
29
+ ok: boolean
30
+ issues: CompileIssue[]
31
+ stats: DraftStats
32
+ }
33
+
34
+ function issue(code: string, path: string, message: string, severity: 'error' | 'warning' = 'error', hint?: string, ruleId?: string): CompileIssue {
35
+ return { code, path, message, severity, hint, ruleId }
36
+ }
37
+
38
+ /** 规则 DSL 里出现的全部变量引用 */
39
+ export function ruleVariableRefs(rule: OntologyRule): string[] {
40
+ const dsl = rule.dsl
41
+ switch (dsl.type) {
42
+ case 'bound': return [dsl.variableKey]
43
+ case 'rate': return [dsl.variableKey]
44
+ case 'linear_coupling': return [dsl.variableKey, dsl.ofKey]
45
+ case 'nonlinear': return [dsl.variableKey]
46
+ case 'state_condition': return [dsl.when.variableKey, dsl.forbid.variableKey]
47
+ case 'interlock': return dsl.variableKey ? [dsl.variableKey] : []
48
+ case 'informal': return []
49
+ default: return []
50
+ }
51
+ }
52
+
53
+ /** 规则证据能支持的最强级别 */
54
+ export function ruleEvidenceLevel(rule: OntologyRule): EvidenceLevel | '' {
55
+ return maxEvidenceLevel(rule.evidence.map(e => e.level))
56
+ }
57
+
58
+ export function validateDraftDoc(doc: OntologyDraftDoc): DraftValidationReport {
59
+ const issues: CompileIssue[] = []
60
+ const entityByKey = new Map<string, OntologyEntity>()
61
+
62
+ // ---- 实体 ----
63
+ const seenKeys = new Set<string>()
64
+ doc.entities.forEach((entity, index) => {
65
+ if (seenKeys.has(entity.key)) {
66
+ issues.push(issue(RULE_ERROR_CODES.INVALID, `entities[${index}]`, `实体 key「${entity.key}」重复`, 'error', '实体 key 必须在单份本体文档内唯一'))
67
+ }
68
+ seenKeys.add(entity.key)
69
+ entityByKey.set(entity.key, entity)
70
+ if (entity.unit) {
71
+ const unitIssue = entityUnitIssue(entity)
72
+ if (unitIssue) issues.push(unitIssue)
73
+ }
74
+ if (entity.kind === 'process_variable' || entity.kind === 'quality_variable') {
75
+ if (!entity.role) {
76
+ issues.push(issue(RULE_ERROR_CODES.ROLE_UNRESOLVED, `entities[${entity.key}]`,
77
+ `变量实体「${entity.key}」缺少 role`, 'warning',
78
+ '缺 role 时无法参与 bound/rate 规则编译(编译器会拒绝);建议补 control/target/disturbance/feature/state/guard/observation'))
79
+ }
80
+ }
81
+ })
82
+
83
+ // ---- 关系 ----
84
+ const relationIds = new Set<string>()
85
+ const relationTriples = new Set<string>()
86
+ doc.relations.forEach((rel, index) => {
87
+ const path = `relations[${index}]`
88
+ if (relationIds.has(rel.id)) issues.push(issue(RULE_ERROR_CODES.INVALID, path, `关系 id「${rel.id}」重复`))
89
+ relationIds.add(rel.id)
90
+ const triple = `${rel.srcKey}|${rel.dstKey}|${rel.kind}`
91
+ if (relationTriples.has(triple)) {
92
+ issues.push(issue(RULE_ERROR_CODES.INVALID, path, `关系重复(${rel.srcKey} -${rel.kind}-> ${rel.dstKey})`))
93
+ }
94
+ relationTriples.add(triple)
95
+ if (rel.srcKey === rel.dstKey) {
96
+ issues.push(issue(RULE_ERROR_CODES.INVALID, path, `关系 ${rel.id} 自引用(src 与 dst 相同)`, 'warning'))
97
+ }
98
+ if (!entityByKey.has(rel.srcKey)) {
99
+ issues.push(issue(RULE_ERROR_CODES.UNKNOWN_ENTITY, path, `关系 ${rel.id} 的 srcKey「${rel.srcKey}」不存在`, 'error', '先在 entities 里定义该实体'))
100
+ }
101
+ if (!entityByKey.has(rel.dstKey)) {
102
+ issues.push(issue(RULE_ERROR_CODES.UNKNOWN_ENTITY, path, `关系 ${rel.id} 的 dstKey「${rel.dstKey}」不存在`, 'error', '先在 entities 里定义该实体'))
103
+ }
104
+ const tier = rel.properties.evidenceTier
105
+ const declaredMax = maxEvidenceLevel(rel.evidence.map(e => e.level))
106
+ if (rel.evidence.length > 0 && evidenceLevelRank(tier) > evidenceLevelRank(declaredMax)) {
107
+ issues.push(issue(RULE_ERROR_CODES.EVIDENCE_INSUFFICIENT, path,
108
+ `关系 ${rel.id} 声明证据档 ${tier} 高于其证据最高级别 ${declaredMax || '无'}`,
109
+ 'error', '补足对应级别证据,或下调 evidenceTier'))
110
+ }
111
+ if ((rel.properties.gainPerUnit !== undefined || rel.properties.lagMs !== undefined) && tier !== 'validated_control') {
112
+ issues.push(issue(RULE_ERROR_CODES.EVIDENCE_INSUFFICIENT, path,
113
+ `关系 ${rel.id} 携带增益/时滞,但证据档为 ${tier}`,
114
+ 'error', '增益与时滞只能来自受控验证(validated_control:run+crosscheck+outcome);否则请留空,仅作候选影响'))
115
+ }
116
+ })
117
+
118
+ // ---- 规则 ----
119
+ const ruleIds = new Set<string>()
120
+ const ruleKeys = new Set<string>()
121
+ doc.rules.forEach((rule, index) => {
122
+ const path = `rules[${index}]`
123
+ if (ruleIds.has(rule.id)) issues.push(issue(RULE_ERROR_CODES.INVALID, path, `规则 id「${rule.id}」重复`))
124
+ ruleIds.add(rule.id)
125
+ if (ruleKeys.has(rule.key)) issues.push(issue(RULE_ERROR_CODES.INVALID, path, `规则 key「${rule.key}」重复`))
126
+ ruleKeys.add(rule.key)
127
+ if (rule.kind !== rule.dsl.type) {
128
+ issues.push(issue(RULE_ERROR_CODES.INVALID, path,
129
+ `规则 ${rule.id} 的 kind(${rule.kind}) 与 dsl.type(${rule.dsl.type}) 不一致`,
130
+ 'error', 'kind 决定编译形态,必须与 DSL 形态一致'))
131
+ }
132
+ for (const ref of ruleVariableRefs(rule)) {
133
+ if (!entityByKey.has(ref)) {
134
+ issues.push(issue(RULE_ERROR_CODES.UNKNOWN_ENTITY, path,
135
+ `规则 ${rule.id} 引用的实体「${ref}」不存在`, 'error', '先定义实体,或改用语义绑定后的平台变量', rule.id))
136
+ }
137
+ }
138
+ const level = ruleEvidenceLevel(rule)
139
+ // 硬约束只约束「数值强制」形态(bound/rate/nonlinear);state_condition 与 interlock
140
+ // 分别落运行时守卫 / PLC 解释层,不改变数值可行域,因此不要求 validated_control。
141
+ const numericHard = rule.constraintLevel === 'hard' && (rule.dsl.type === 'bound' || rule.dsl.type === 'rate' || rule.dsl.type === 'nonlinear')
142
+ if (numericHard && level !== 'validated_control') {
143
+ issues.push(issue(RULE_ERROR_CODES.EVIDENCE_INSUFFICIENT, path,
144
+ `规则 ${rule.id} 要求硬约束,但证据最高级别为 ${level || '无'}`,
145
+ 'error', '硬约束只接受 validated_control(run+crosscheck+outcome);否则降为 soft 或改为 guard', rule.id))
146
+ }
147
+ if (rule.dsl.type === 'bound' && rule.dsl.min !== undefined && rule.dsl.max !== undefined && rule.dsl.min > rule.dsl.max) {
148
+ issues.push(issue(RULE_ERROR_CODES.RULE_CONFLICT, path,
149
+ `规则 ${rule.id} 的界区间为空(min ${rule.dsl.min} > max ${rule.dsl.max})`, 'error', '检查上下限是否写反', rule.id))
150
+ }
151
+ if (rule.dsl.type === 'nonlinear') {
152
+ // 简单阈值形态可由运行时守卫执行;复杂表达式需后端支持
153
+ const simple = /^\s*[a-z][a-z0-9_.]*\s*(<=|>=|<|>|==|!=)\s*-?\d+(?:\.\d+)?\s*$/.test(rule.dsl.expression)
154
+ if (!simple) {
155
+ issues.push(issue(RULE_ERROR_CODES.UNSUPPORTED_FORM, path,
156
+ `规则 ${rule.id} 的非线性表达式无法由运行时守卫执行`,
157
+ 'warning', '建议改写为「变量 比较 阈值」形式,或落到 PhysicsSpec 由求解器/孪生后端支持', rule.id))
158
+ }
159
+ }
160
+ })
161
+
162
+ // ---- 语义绑定(草稿期) ----
163
+ const bindingIds = new Set<string>()
164
+ const bindingTriples = new Set<string>()
165
+ doc.bindings.forEach((binding, index) => {
166
+ const path = `bindings[${index}]`
167
+ if (bindingIds.has(binding.id)) issues.push(issue(RULE_ERROR_CODES.INVALID, path, `绑定 id「${binding.id}」重复`))
168
+ bindingIds.add(binding.id)
169
+ const triple = `${binding.entityKey}|${binding.platformKind}|${binding.platformId}`
170
+ if (bindingTriples.has(triple)) {
171
+ issues.push(issue(RULE_ERROR_CODES.INVALID, path, `绑定重复(实体 ${binding.entityKey} → ${binding.platformKind}:${binding.platformId})`))
172
+ }
173
+ bindingTriples.add(triple)
174
+ const entity = entityByKey.get(binding.entityKey)
175
+ if (!entity) {
176
+ issues.push(issue(RULE_ERROR_CODES.UNKNOWN_ENTITY, path, `绑定 ${binding.id} 的实体「${binding.entityKey}」不存在`))
177
+ return
178
+ }
179
+ if (entity.unit && binding.unitDeclared && !unitsCompatible(entity.unit, binding.unitDeclared)) {
180
+ issues.push(issue(RULE_ERROR_CODES.UNIT_MISMATCH, path,
181
+ `绑定 ${binding.id} 的声明单位「${binding.unitDeclared}」与实体「${entity.key}」单位「${entity.unit}」量纲不相容`))
182
+ }
183
+ if (binding.unitDeclared && binding.unitTarget && !unitsCompatible(binding.unitDeclared, binding.unitTarget)) {
184
+ issues.push(issue(RULE_ERROR_CODES.UNIT_MISMATCH, path,
185
+ `绑定 ${binding.id} 的单位「${binding.unitDeclared}」与目标单位「${binding.unitTarget}」量纲不相容`))
186
+ }
187
+ if (!Number.isFinite(binding.scale) || binding.scale === 0) {
188
+ issues.push(issue(RULE_ERROR_CODES.INVALID, path, `绑定 ${binding.id} 的 scale 必须为非零有限数(禁止兜底)`))
189
+ }
190
+ if (binding.platformKind === 'daq_node' && binding.direction !== 'read') {
191
+ issues.push(issue(RULE_ERROR_CODES.INVALID, path,
192
+ `绑定 ${binding.id} 把数采节点声明为 ${binding.direction}`, 'warning',
193
+ '平台数采节点通常是只读通道;写入应绑定 dcw_node 或 recipe_param(活体校验会拒绝)'))
194
+ }
195
+ })
196
+
197
+ const byState: Record<string, number> = {}
198
+ for (const state of ONTOLOGY_STATES) byState[state] = 0
199
+ for (const rule of doc.rules) byState[rule.status] = (byState[rule.status] ?? 0) + 1
200
+ const byEvidence: Record<string, number> = { candidate_influence: 0, observed_correlation: 0, validated_control: 0 }
201
+ for (const rule of doc.rules) {
202
+ const level = ruleEvidenceLevel(rule)
203
+ if (level) byEvidence[level] = (byEvidence[level] ?? 0) + 1
204
+ }
205
+
206
+ return {
207
+ ok: !issues.some(i => i.severity === 'error'),
208
+ issues,
209
+ stats: {
210
+ entities: doc.entities.length,
211
+ relations: doc.relations.length,
212
+ rules: doc.rules.length,
213
+ bindings: doc.bindings.length,
214
+ byState,
215
+ byEvidence,
216
+ },
217
+ }
218
+ }
@@ -111,6 +111,13 @@ export function createBindingRepo(db: DatabaseSync) {
111
111
  return row?.revision ?? 0
112
112
  },
113
113
 
114
+ /** 模型采纳重绑:绑定升到新 Profile 版本并 bump revision(在飞求解 BINDING_STALE 收敛)。 */
115
+ rebindVersion(id: string, toVersion: number): number {
116
+ const r = db.prepare('UPDATE optimizer_bindings SET profile_version = ?, revision = revision + 1, valid_from = ?, updated_at = ? WHERE id = ?')
117
+ .run(toVersion, new Date().toISOString(), new Date().toISOString(), id)
118
+ return Number(r.changes)
119
+ },
120
+
114
121
  removeByAgent(channelAgentId: string): number {
115
122
  const r = db.prepare('DELETE FROM optimizer_bindings WHERE channel_agent_id = ?').run(channelAgentId)
116
123
  return Number(r.changes)
@@ -72,9 +72,23 @@ export interface OptimizationProfile {
72
72
  ownerUserId?: string
73
73
  /** 发布时冻结的问题结构 hash */
74
74
  problemIrHash?: string
75
+ /**
76
+ * 本体引用摘要(发布时冻结):**进 profileContentHash,绝不进 problemIrHash**。
77
+ * 漂移比对走独立校验(ONTOLOGY_PACK_DRIFTED),避免本体演化把旧 Profile
78
+ * 全部打成 PROBLEM_IR_CHANGED(与 D1/D12 同因)。
79
+ */
80
+ ontologyRefs?: OntologyRefSummary[]
75
81
  createdAt?: string
76
82
  }
77
83
 
84
+ export interface OntologyRefSummary {
85
+ ontologyId: string
86
+ ontologyVersion: number
87
+ contentHash?: string
88
+ rulePackHash?: string
89
+ guardCount?: number
90
+ }
91
+
78
92
  export function assertProfileSolverCompatible(profile: Pick<OptimizationProfile, 'solverRef' | 'modelRef' | 'problemTemplateRef'>): void {
79
93
  assertSolverSupportsArtifact(profile.solverRef, profile.modelRef.artifactKind, `profile model=${profile.modelRef.modelId}`)
80
94
  if (profile.solverRef === 'osqp_mpc@1' && profile.problemTemplateRef !== 'linear_mpc_quadratic@1') {
@@ -37,6 +37,7 @@ import { getDcwLineRepo } from '../dcw/dcw-line.repo'
37
37
  import { assertRecipeOpInterval } from '../dcw/recipe-op-anchor'
38
38
  import { getToolApprovals } from '../agents/tool-approvals'
39
39
  import { amlActivityForLine } from '../agents/industrial/aml-activity'
40
+ import { assertOntologyUnchanged, evaluateOntologyGuardsForNodes } from '../ontology/ontology.service'
40
41
  import type { RecipeProposePayload } from '../agents/industrial/recipe-propose-tools'
41
42
 
42
43
  export function isOptimizerDispatchCard(nodeId: string): boolean {
@@ -342,6 +343,21 @@ export async function createDispatchCard(initiator: ResolvedUser, recommendation
342
343
  }
343
344
  })
344
345
  const { recipe } = loadRec(recommendationId)
346
+ // 本体运行时守卫(ONT):已发布本体的 block 级守卫对本次下发意图求值。
347
+ // 只增拒不放行;无本体/无守卫时零开销。批准时刻 D13 仍全量重验。
348
+ const ontologyGuard = evaluateOntologyGuardsForNodes(spec.lineId, paramRows.map(p => ({ nodeId: p.nodeId, from: p.from, to: p.to })))
349
+ if (ontologyGuard.blocked) {
350
+ const violation = ontologyGuard.violations[0]!
351
+ throw new AppError(409, 'ONTOLOGY_GUARD_BLOCKED',
352
+ `本体运行时守卫阻断下发:${violation.message}(规则 ${violation.ruleId};本体包 ${ontologyGuard.packHash.slice(0, 12)})`)
353
+ }
354
+ // Profile 冻结的本体引用漂移:独立校验(不进 IR hash,不变更 D13 八项语义)
355
+ const dispatchRun = db().prepare('SELECT profile_id AS profileId, profile_version AS profileVersion FROM optimizer_runs WHERE id = ?')
356
+ .get(rec.runId) as { profileId?: string, profileVersion?: number } | undefined
357
+ if (dispatchRun?.profileId) {
358
+ const dispatchProfileRow = getProfileRepo().get(dispatchRun.profileId, Number(dispatchRun.profileVersion ?? 1))
359
+ if (dispatchProfileRow) assertOntologyUnchanged(parseProfileRow(dispatchProfileRow).ontologyRefs)
360
+ }
345
361
  // 闸序预检(建卡时刻;批准时刻 D13 全量重验)
346
362
  const gate = await assertDispatchApprovable(recommendationId, { modelFirstMove, packages: [{ params: paramRows }] })
347
363
  if (!gate.ok) throw new AppError(gate.code.startsWith('DISPATCH_GATE') || gate.code === 'DISPATCH_STEP_EXCEEDED' ? 403 : 409, gate.code, gate.comment)
@@ -0,0 +1,256 @@
1
+ /**
2
+ * Profile 模型采纳服务 —— Agent 迭代闭环的"采纳"环节(OW-adopt)。
3
+ *
4
+ * 闭环语义:Agent 训练出新模型(aml_job_submit→done)后,可以用
5
+ * `optimizer_profile_propose` 工具发起「采纳提议」:复制当前已发布 Profile
6
+ * 的全部求解配置、换上新模型工件、生成新草稿版本,并挂一张 HITL 卡。
7
+ * 人类批准 → **发布新版本 + 自动重绑**所有绑定在旧版本的 Agent(绑定 revision+1,
8
+ * 在飞求解按 BINDING_STALE 收敛,下一次 solve 即用新模型);拒绝 → 零写,意见回流。
9
+ *
10
+ * 治理不变量:
11
+ * - 提议 = 草稿 + 卡,本身不改运行行为(旧版本继续求解);
12
+ * - 发布只发生在人类批准之后(单一咽喉,dispatcher/decide 双入口同路由);
13
+ * - 模型工件/求解器/模板兼容性在提议时校验(D21 矩阵,不兼容 422);
14
+ * - 全链审计(actor 三态,publish/adopt/rebind 各一条)。
15
+ */
16
+ import { AppError } from '../../../utils/errors'
17
+ import { getAmlRuntime } from '../aml/runtime'
18
+ import { recordOps } from '../ops/ops'
19
+ import { getProfileRepo, parseProfileRow } from './profile.repo'
20
+ import { getBindingRepo } from './binding.repo'
21
+ import { assertProfileSolverCompatible, type OptimizationProfile } from './contracts'
22
+ import type { ProblemTemplateRef, SolverRef } from '../process-model/contracts'
23
+ import { securityRecipeDispatchTimeoutMs } from '../settings'
24
+ import { createLogger } from '../logger'
25
+
26
+ import { getToolApprovals } from '../agents/tool-approvals'
27
+
28
+ const log = createLogger('optimizer.profile-adopt')
29
+
30
+ export const PROFILE_ADOPT_PREFIX = 'optimizer-profile:'
31
+
32
+ export function isProfileAdoptCard(nodeId: string): boolean {
33
+ return nodeId.startsWith(PROFILE_ADOPT_PREFIX)
34
+ }
35
+
36
+ export interface ProposeAdoptionInput {
37
+ /** 发起 Agent 的 channel 实例 id(HITL 卡挂在其频道) */
38
+ agentInstanceId: string
39
+ /** 人类发起时为用户 id;Agent 发起传 agentId(actorKind='agent') */
40
+ initiatorId: string
41
+ initiatorKind?: 'user' | 'agent'
42
+ profileId: string
43
+ modelId: string
44
+ /** 可选切换问题模板/求解器(不兼容 → 422,D21 矩阵) */
45
+ templateRef?: ProblemTemplateRef
46
+ solverRef?: SolverRef
47
+ /** 提议理由(必填;审批卡展示) */
48
+ reason: string
49
+ /** 依赖注入(单测 stub 用) */
50
+ deps?: {
51
+ requestApproval?: (agentId: string, nodeId: string, kind: 'dcw', detail: string, opts?: { title?: string, timeoutMs?: number, payload?: unknown }) => Promise<{ approved: boolean, comment: string, choice: number | null }>
52
+ }
53
+ }
54
+
55
+ export interface ProposeAdoptionResult {
56
+ cardId: string
57
+ profileId: string
58
+ version: number
59
+ priorVersion: number
60
+ modelId: string
61
+ decision: { approved: boolean, comment: string, choice: number | null }
62
+ published: boolean
63
+ rebindCount: number
64
+ }
65
+
66
+ /** 提议采纳:建草稿新版本 + 挂 HITL 卡 + 等待裁决(approved 时已完成发布与重绑)。 */
67
+ export async function proposeProfileAdoption(input: ProposeAdoptionInput): Promise<ProposeAdoptionResult> {
68
+ const repo = getProfileRepo()
69
+ const published = repo.latestPublished(input.profileId)
70
+ if (!published) {
71
+ throw new AppError(404, 'PROFILE_NOT_PUBLISHED', `Profile ${input.profileId} 没有已发布版本;采纳以已发布版本为基线`)
72
+ }
73
+ const model = getAmlRuntime().repo.model.get(input.modelId)
74
+ if (!model) throw new AppError(404, 'MODEL_NOT_FOUND', `模型 ${input.modelId} 不存在(先经 AML 训练登记)`)
75
+
76
+ const prior = parseProfileRow(published)
77
+ const version = published.version + 1
78
+ const nextProfile: OptimizationProfile = {
79
+ ...prior,
80
+ version,
81
+ status: 'draft',
82
+ modelRef: {
83
+ modelId: input.modelId,
84
+ artifactKind: (model.artifactKind || 'onnx_one_step@1') as OptimizationProfile['modelRef']['artifactKind'],
85
+ modelInterface: (model.modelInterface || 'one_step') as OptimizationProfile['modelRef']['modelInterface'],
86
+ artifactHash: model.artifactHash || '',
87
+ stage: 'candidate',
88
+ },
89
+ ...(input.templateRef ? { problemTemplateRef: input.templateRef } : {}),
90
+ ...(input.solverRef ? { solverRef: input.solverRef } : {}),
91
+ }
92
+ // D21 分派矩阵:工件×模板×求解器不兼容在此显式拒绝(不产生草稿)
93
+ assertProfileSolverCompatible(nextProfile)
94
+ repo.insert(nextProfile, input.initiatorId)
95
+
96
+ const cardId = `${PROFILE_ADOPT_PREFIX}${input.profileId}@${version}`
97
+ const detail = [
98
+ `模型采纳提议:${input.profileId} v${published.version} → v${version}`,
99
+ `新模型:${input.modelId}(${nextProfile.modelRef.artifactKind},hash ${String(nextProfile.modelRef.artifactHash).slice(0, 12)}…)`,
100
+ nextProfile.problemTemplateRef !== prior.problemTemplateRef || nextProfile.solverRef !== prior.solverRef
101
+ ? `求解配置变更:模板 ${prior.problemTemplateRef}→${nextProfile.problemTemplateRef},求解器 ${prior.solverRef}→${nextProfile.solverRef}`
102
+ : `求解配置不变(模板 ${nextProfile.problemTemplateRef} / ${nextProfile.solverRef})`,
103
+ `理由:${input.reason}`,
104
+ `批准 = 冻结发布 v${version} 并把绑定在 v${published.version} 的 Agent 自动重绑(在飞求解 BINDING_STALE 收敛);拒绝 = 零写。`,
105
+ ].join('\n')
106
+
107
+ recordOps({
108
+ actor: input.initiatorId,
109
+ actorName: input.initiatorId,
110
+ actorKind: input.initiatorKind ?? 'agent',
111
+ action: 'optimizer.profile.adopt_propose',
112
+ kind: 'system',
113
+ targetKind: 'optimizer_profile',
114
+ targetId: `${input.profileId}@${version}`,
115
+ summary: `提议采纳模型 ${input.modelId} → ${input.profileId}@${version}(卡 ${cardId})`,
116
+ detail: { profileId: input.profileId, version, priorVersion: published.version, modelId: input.modelId, reason: input.reason },
117
+ })
118
+
119
+ const requestApproval = input.deps?.requestApproval
120
+ ?? ((agentId: string, nodeId: string, kind: 'dcw', detail_: string, opts?: { title?: string, timeoutMs?: number, payload?: unknown }) =>
121
+ getToolApprovals().request(agentId, nodeId, kind, detail_, opts))
122
+
123
+ const decision = await requestApproval(input.agentInstanceId, cardId, 'dcw', detail, {
124
+ title: `模型采纳:${input.profileId} → v${version}`,
125
+ timeoutMs: securityRecipeDispatchTimeoutMs(),
126
+ payload: { schemaVersion: 1, profileId: input.profileId, version, priorVersion: published.version, modelId: input.modelId },
127
+ })
128
+
129
+ if (!decision.approved) {
130
+ return { cardId, profileId: input.profileId, version, priorVersion: published.version, modelId: input.modelId, decision: { approved: false, comment: decision.comment, choice: decision.choice ?? null }, published: false, rebindCount: 0 }
131
+ }
132
+ // 批准路径的发布/重绑在单一咽喉(decideProfileAdoption)已完成;此处防御式复核
133
+ const publishedRow = repo.get(input.profileId, version)
134
+ const rebindCount = countBindingsOn(input.profileId, version)
135
+ return {
136
+ cardId,
137
+ profileId: input.profileId,
138
+ version,
139
+ priorVersion: published.version,
140
+ modelId: input.modelId,
141
+ decision: { approved: true, comment: decision.comment, choice: decision.choice ?? null },
142
+ published: publishedRow?.status === 'published',
143
+ rebindCount,
144
+ }
145
+ }
146
+
147
+ function countBindingsOn(profileId: string, version: number): number {
148
+ return getBindingRepo().listAll(500).filter(b => b.profileId === profileId && b.profileVersionNumber === version).length
149
+ }
150
+
151
+ export interface DecideAdoptionInput {
152
+ /** 审批单 id(ap-…;listPending 的主键) */
153
+ cardId: string
154
+ /** 卡的 nodeId(optimizer-profile:<id>@<v>);缺省时经审批单反查 */
155
+ nodeId?: string
156
+ approved: boolean
157
+ comment: string
158
+ actingUser: { id: string, name?: string }
159
+ via: 'hitl/respond' | 'decide-endpoint'
160
+ /** 依赖注入(单测 stub);缺省走真实 ToolApprovalService(卡必须在册) */
161
+ deps?: {
162
+ decideApproval?: (id: string, approved: boolean, comment: string, by: string, name: string) => void
163
+ }
164
+ }
165
+
166
+ /** 卡落定(真实面:审批必须在册;stub 面:直接回调)。失败不击穿咽喉主流程。 */
167
+ function settle(deps: DecideAdoptionInput['deps'], cardId: string, approved: boolean, comment: string, by: string, name: string): void {
168
+ try {
169
+ const decide = deps?.decideApproval ?? ((id: string, ok: boolean, msg: string, by2: string, name2: string) => getToolApprovals().decide(id, ok, msg, by2, name2))
170
+ decide(cardId, approved, comment, by, name)
171
+ }
172
+ catch (err) {
173
+ log.warn(`[profile-adopt] 卡落定失败(不影响裁决结果):${err instanceof Error ? err.message : String(err)}`)
174
+ }
175
+ }
176
+
177
+ export interface DecideAdoptionResult {
178
+ handled: boolean
179
+ approved: boolean
180
+ comment: string
181
+ code?: string
182
+ published?: { profileId: string, version: number, rebindCount: number }
183
+ }
184
+
185
+ /** 单一咽喉:optimizer-profile:* 卡的裁决 → 发布 + 重绑 + 审计(业务拒绝在咽喉内落定)。 */
186
+ export async function decideProfileAdoption(input: DecideAdoptionInput): Promise<DecideAdoptionResult> {
187
+ // nodeId 解析:分支显式传入优先;否则经审批单反查(卡 id ≠ nodeId,两个命名空间)
188
+ const nodeId = input.nodeId
189
+ ?? getToolApprovals().listPending().find(a => a.id === input.cardId)?.nodeId
190
+ ?? input.cardId
191
+ if (!isProfileAdoptCard(nodeId)) return { handled: false, approved: input.approved, comment: input.comment }
192
+ const parsed = nodeId.slice(PROFILE_ADOPT_PREFIX.length).split('@')
193
+ const profileId = parsed[0] ?? ''
194
+ const version = Number(parsed[1])
195
+ if (!profileId || !Number.isInteger(version)) {
196
+ throw new AppError(422, 'PROFILE_ADOPT_CARD_INVALID', `采纳卡 nodeId 形状非法:${nodeId}`)
197
+ }
198
+ const repo = getProfileRepo()
199
+ const row = repo.get(profileId, version)
200
+ if (!row) {
201
+ settle(input.deps, input.cardId, false, `Profile ${profileId}@${version} 已不存在;按拒收敛`, input.actingUser.id, input.actingUser.name ?? '')
202
+ return { handled: true, approved: false, comment: '目标 Profile 版本不存在', code: 'PROFILE_NOT_FOUND' }
203
+ }
204
+
205
+ if (!input.approved) {
206
+ // 拒绝:草稿保留(可修订后重新 propose,新卡重走),零写
207
+ settle(input.deps, input.cardId, false, input.comment || '采纳提议被拒绝', input.actingUser.id, input.actingUser.name ?? '')
208
+ recordOps({
209
+ actor: input.actingUser.id, actorName: input.actingUser.name ?? input.actingUser.id, actorKind: 'user',
210
+ action: 'optimizer.profile.adopt_reject', kind: 'system',
211
+ targetKind: 'optimizer_profile', targetId: `${profileId}@${version}`,
212
+ summary: `拒绝模型采纳 ${profileId}@${version}(草稿保留,零写)`,
213
+ detail: { profileId, version, comment: input.comment, via: input.via },
214
+ })
215
+ return { handled: true, approved: false, comment: input.comment || '采纳提议被拒绝', code: 'PROFILE_ADOPT_REJECTED' }
216
+ }
217
+
218
+ // 批准:发布冻结 + 自动重绑(旧 published 版本 → 新版本;revision+1 使在飞求解 BINDING_STALE 收敛)
219
+ const priorVersion = version - 1
220
+ try {
221
+ repo.publish(profileId, version)
222
+ const rebindCount = rebindBindings(profileId, priorVersion, version)
223
+ recordOps({
224
+ actor: input.actingUser.id, actorName: input.actingUser.name ?? input.actingUser.id, actorKind: 'user',
225
+ action: 'optimizer.profile.adopt', kind: 'system',
226
+ targetKind: 'optimizer_profile', targetId: `${profileId}@${version}`,
227
+ summary: `批准并发布 ${profileId}@${version}(重绑 ${rebindCount} 个绑定;来自采纳卡)`,
228
+ detail: { profileId, version, priorVersion, rebindCount, via: input.via, comment: input.comment },
229
+ })
230
+ settle(input.deps, input.cardId, true, input.comment || `已发布 v${version},重绑 ${rebindCount} 个绑定`, input.actingUser.id, input.actingUser.name ?? '')
231
+ return { handled: true, approved: true, comment: input.comment, published: { profileId, version, rebindCount } }
232
+ }
233
+ catch (err) {
234
+ const message = err instanceof Error ? err.message : String(err)
235
+ settle(input.deps, input.cardId, false, `发布失败,按拒收敛:${message}`, input.actingUser.id, input.actingUser.name ?? '')
236
+ recordOps({
237
+ actor: input.actingUser.id, actorName: input.actingUser.name ?? input.actingUser.id, actorKind: 'user',
238
+ action: 'optimizer.profile.adopt_reject', kind: 'system', level: 'error',
239
+ targetKind: 'optimizer_profile', targetId: `${profileId}@${version}`,
240
+ summary: `采纳发布失败按拒收敛 ${profileId}@${version}:${message}`,
241
+ detail: { profileId, version, error: message, via: input.via },
242
+ })
243
+ return { handled: true, approved: false, comment: `发布失败:${message}`, code: 'PROFILE_ADOPT_PUBLISH_FAILED' }
244
+ }
245
+ }
246
+
247
+ function rebindBindings(profileId: string, fromVersion: number, toVersion: number): number {
248
+ const repo = getBindingRepo()
249
+ let count = 0
250
+ for (const b of repo.listAll(500)) {
251
+ if (b.profileId !== profileId || b.profileVersionNumber !== fromVersion) continue
252
+ const moved = repo.rebindVersion(b.id, toVersion)
253
+ if (moved > 0) count += 1
254
+ }
255
+ return count
256
+ }
@@ -28,6 +28,8 @@ export interface ProfileRow {
28
28
  problemIrHash: string
29
29
  /** 发布不可变校验:内容 hash(不含 status/createdAt/problemIrHash) */
30
30
  contentHash: string
31
+ /** 本体引用冻结(JSON 数组;缺省 '[]' = 无本体约束域) */
32
+ ontologyRefsJson: string
31
33
  createdAt: string
32
34
  updatedAt: string
33
35
  }
@@ -38,6 +40,7 @@ const COLS = `id, version, name, model_ref AS modelRef, model_artifact_hash AS m
38
40
  process_spec_ref AS processSpecRef,
39
41
  solver_ref AS solverRef, solver_version AS solverVersion, condition_ids_json AS conditionIdsJson,
40
42
  status, owner_user_id AS ownerUserId, problem_ir_hash AS problemIrHash, content_hash AS contentHash,
43
+ ontology_refs_json AS ontologyRefsJson,
41
44
  created_at AS createdAt, updated_at AS updatedAt`
42
45
 
43
46
  export function profileContentHash(profile: OptimizationProfile): string {
@@ -61,12 +64,13 @@ export function createProfileRepo(db: DatabaseSync) {
61
64
  db.prepare(`INSERT INTO optimizer_profiles
62
65
  (id, version, name, model_ref, model_artifact_hash, model_artifact_kind, model_interface,
63
66
  problem_template_ref, problem_config_json, process_spec_ref, solver_ref, solver_version, condition_ids_json,
64
- status, owner_user_id, problem_ir_hash, content_hash, created_at, updated_at)
65
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
67
+ status, owner_user_id, problem_ir_hash, content_hash, ontology_refs_json, created_at, updated_at)
68
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
66
69
  .run(profile.id, profile.version, profile.name ?? '', profile.modelRef.modelId, profile.modelRef.artifactHash,
67
70
  profile.modelRef.artifactKind, profile.modelRef.modelInterface, profile.problemTemplateRef,
68
71
  JSON.stringify(profile.problemConfig ?? {}), profile.processSpecRef ?? '', profile.solverRef, profile.solverVersion,
69
- JSON.stringify(profile.conditionIds ?? []), profile.status, ownerUserId, profile.problemIrHash ?? '', contentHash, now, now)
72
+ JSON.stringify(profile.conditionIds ?? []), profile.status, ownerUserId, profile.problemIrHash ?? '', contentHash,
73
+ JSON.stringify(profile.ontologyRefs ?? []), now, now)
70
74
  return this.get(profile.id, profile.version)!
71
75
  },
72
76
 
@@ -92,6 +96,11 @@ export function createProfileRepo(db: DatabaseSync) {
92
96
  return (r.v ?? 0) + 1
93
97
  },
94
98
 
99
+ /** 最近已发布版本(采纳服务以它为基线;无则 undefined) */
100
+ latestPublished(id: string): ProfileRow | undefined {
101
+ return db.prepare(`SELECT ${COLS} FROM optimizer_profiles WHERE id = ? AND status = 'published' ORDER BY version DESC LIMIT 1`).get(id) as unknown as ProfileRow | undefined
102
+ },
103
+
95
104
  /** 发布:冻结 problemIrHash;published 行禁止原地修改(服务层拒绝 UPDATE)。 */
96
105
  publish(id: string, version: number, problemIrHash?: string): ProfileRow {
97
106
  const row = this.get(id, version)
@@ -153,6 +162,13 @@ export function parseProfileRow(row: ProfileRow): OptimizationProfile {
153
162
  status: row.status,
154
163
  ownerUserId: row.ownerUserId,
155
164
  problemIrHash: row.problemIrHash || undefined,
165
+ ontologyRefs: (() => {
166
+ try {
167
+ const parsed = JSON.parse(row.ontologyRefsJson || '[]') as OptimizationProfile['ontologyRefs']
168
+ return parsed && parsed.length > 0 ? parsed : undefined
169
+ }
170
+ catch { return undefined }
171
+ })(),
156
172
  createdAt: row.createdAt,
157
173
  }
158
174
  }