@faicad/faijs 0.14.1 → 0.16.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 (338) hide show
  1. package/dist/api/api-namespace.d.ts +7 -0
  2. package/dist/api/api-namespace.d.ts.map +1 -1
  3. package/dist/api/api-namespace.js +23 -22
  4. package/dist/api/api-namespace.js.map +1 -1
  5. package/dist/api/boolean.d.ts.map +1 -1
  6. package/dist/api/boolean.js +26 -8
  7. package/dist/api/boolean.js.map +1 -1
  8. package/dist/api/chamfer.d.ts.map +1 -1
  9. package/dist/api/chamfer.js +4 -1
  10. package/dist/api/chamfer.js.map +1 -1
  11. package/dist/api/generated/cad/script-face.d.ts +1 -1
  12. package/dist/api/generated/cad/script-face.d.ts.map +1 -1
  13. package/dist/api/generated/cad/script-face.js +1 -2
  14. package/dist/api/generated/cad/script-face.js.map +1 -1
  15. package/dist/api/generated/operations.js +16 -16
  16. package/dist/api/generated/operations.js.map +1 -1
  17. package/dist/api/generated/script-face-manifest.d.ts.map +1 -1
  18. package/dist/api/generated/script-face-manifest.js +0 -1
  19. package/dist/api/generated/script-face-manifest.js.map +1 -1
  20. package/dist/api/generated/script-face.d.ts +1 -4
  21. package/dist/api/generated/script-face.d.ts.map +1 -1
  22. package/dist/api/generated/script-face.js +2 -3
  23. package/dist/api/generated/script-face.js.map +1 -1
  24. package/dist/api/generated/sketching.js +1 -1
  25. package/dist/api/generated/sketching.js.map +1 -1
  26. package/dist/api/generated/topology.d.ts +0 -8
  27. package/dist/api/generated/topology.d.ts.map +1 -1
  28. package/dist/api/generated/topology.js +19 -26
  29. package/dist/api/generated/topology.js.map +1 -1
  30. package/dist/api/index.d.ts +1 -10
  31. package/dist/api/index.d.ts.map +1 -1
  32. package/dist/api/index.js +10 -18
  33. package/dist/api/index.js.map +1 -1
  34. package/dist/api/internal/compat-projection.d.ts +3 -1
  35. package/dist/api/internal/compat-projection.d.ts.map +1 -1
  36. package/dist/api/internal/compat-projection.js +8 -5
  37. package/dist/api/internal/compat-projection.js.map +1 -1
  38. package/dist/api/internal/replica-role-table.d.ts +36 -0
  39. package/dist/api/internal/replica-role-table.d.ts.map +1 -0
  40. package/dist/api/internal/replica-role-table.js +73 -0
  41. package/dist/api/internal/replica-role-table.js.map +1 -0
  42. package/dist/api/internal/result-unwrap.d.ts +3 -1
  43. package/dist/api/internal/result-unwrap.d.ts.map +1 -1
  44. package/dist/api/internal/result-unwrap.js +2 -2
  45. package/dist/api/internal/result-unwrap.js.map +1 -1
  46. package/dist/api/occt-kernel-bridge.d.ts +105 -27
  47. package/dist/api/occt-kernel-bridge.d.ts.map +1 -1
  48. package/dist/api/occt-kernel-bridge.js +255 -41
  49. package/dist/api/occt-kernel-bridge.js.map +1 -1
  50. package/dist/api/pattern.d.ts.map +1 -1
  51. package/dist/api/pattern.js +25 -61
  52. package/dist/api/pattern.js.map +1 -1
  53. package/dist/api/replicate.d.ts +145 -0
  54. package/dist/api/replicate.d.ts.map +1 -0
  55. package/dist/api/replicate.js +351 -0
  56. package/dist/api/replicate.js.map +1 -0
  57. package/dist/api/revolve.d.ts +36 -0
  58. package/dist/api/revolve.d.ts.map +1 -0
  59. package/dist/api/revolve.js +165 -0
  60. package/dist/api/revolve.js.map +1 -0
  61. package/dist/api/surface/arg-spec.d.ts +8 -0
  62. package/dist/api/surface/arg-spec.d.ts.map +1 -1
  63. package/dist/api/surface/arg-spec.js +37 -36
  64. package/dist/api/surface/arg-spec.js.map +1 -1
  65. package/dist/api/surface/projection-overrides.d.ts.map +1 -1
  66. package/dist/api/surface/projection-overrides.js +6 -0
  67. package/dist/api/surface/projection-overrides.js.map +1 -1
  68. package/dist/boolean/deriveNormals.d.ts +5 -4
  69. package/dist/boolean/deriveNormals.d.ts.map +1 -1
  70. package/dist/boolean/deriveNormals.js +24 -7
  71. package/dist/boolean/deriveNormals.js.map +1 -1
  72. package/dist/brep/engine/adapters/brep-mock.d.ts.map +1 -1
  73. package/dist/brep/engine/adapters/brep-mock.js +58 -0
  74. package/dist/brep/engine/adapters/brep-mock.js.map +1 -1
  75. package/dist/brep/engine/adapters/brepkit.d.ts.map +1 -1
  76. package/dist/brep/engine/adapters/brepkit.js +39 -1
  77. package/dist/brep/engine/adapters/brepkit.js.map +1 -1
  78. package/dist/brep/engine/adapters/occt.d.ts +1 -5
  79. package/dist/brep/engine/adapters/occt.d.ts.map +1 -1
  80. package/dist/brep/engine/adapters/occt.js +232 -18
  81. package/dist/brep/engine/adapters/occt.js.map +1 -1
  82. package/dist/brep/engine/primitives.d.ts +79 -0
  83. package/dist/brep/engine/primitives.d.ts.map +1 -1
  84. package/dist/brep/engine/primitives.js.map +1 -1
  85. package/dist/brep/engine/types.d.ts +18 -1
  86. package/dist/brep/engine/types.d.ts.map +1 -1
  87. package/dist/brep/engine/types.js.map +1 -1
  88. package/dist/brepkit-kernel/brepkitKernel.d.ts.map +1 -1
  89. package/dist/brepkit-kernel/brepkitKernel.js +81 -11
  90. package/dist/brepkit-kernel/brepkitKernel.js.map +1 -1
  91. package/dist/browser.d.ts +6 -28
  92. package/dist/browser.d.ts.map +1 -1
  93. package/dist/browser.js +6 -17
  94. package/dist/browser.js.map +1 -1
  95. package/dist/cad-runtime/admit-compat-lib.d.ts +13 -18
  96. package/dist/cad-runtime/admit-compat-lib.d.ts.map +1 -1
  97. package/dist/cad-runtime/admit-compat-lib.js +25 -18
  98. package/dist/cad-runtime/admit-compat-lib.js.map +1 -1
  99. package/dist/cad-runtime/backend-dispatch.d.ts +4 -2
  100. package/dist/cad-runtime/backend-dispatch.d.ts.map +1 -1
  101. package/dist/cad-runtime/backend-dispatch.js +2 -0
  102. package/dist/cad-runtime/backend-dispatch.js.map +1 -1
  103. package/dist/cad-runtime/browser-lib-loader.d.ts +4 -6
  104. package/dist/cad-runtime/browser-lib-loader.d.ts.map +1 -1
  105. package/dist/cad-runtime/browser-lib-loader.js +4 -9
  106. package/dist/cad-runtime/browser-lib-loader.js.map +1 -1
  107. package/dist/cad-runtime/ports.d.ts +0 -7
  108. package/dist/cad-runtime/ports.d.ts.map +1 -1
  109. package/dist/cad-runtime/ports.js.map +1 -1
  110. package/dist/cad-runtime/runtime.d.ts +1 -3
  111. package/dist/cad-runtime/runtime.d.ts.map +1 -1
  112. package/dist/cad-runtime/runtime.js +13 -18
  113. package/dist/cad-runtime/runtime.js.map +1 -1
  114. package/dist/env-agnostic.d.ts +38 -0
  115. package/dist/env-agnostic.d.ts.map +1 -0
  116. package/dist/env-agnostic.js +29 -0
  117. package/dist/env-agnostic.js.map +1 -0
  118. package/dist/fcstd/codegen.d.ts.map +1 -1
  119. package/dist/fcstd/codegen.js +8 -1
  120. package/dist/fcstd/codegen.js.map +1 -1
  121. package/dist/fcstd/expressions.d.ts +24 -0
  122. package/dist/fcstd/expressions.d.ts.map +1 -1
  123. package/dist/fcstd/expressions.js +91 -0
  124. package/dist/fcstd/expressions.js.map +1 -1
  125. package/dist/fcstd/feature-translate.d.ts.map +1 -1
  126. package/dist/fcstd/feature-translate.js +16 -2
  127. package/dist/fcstd/feature-translate.js.map +1 -1
  128. package/dist/fcstd/structural-types.d.ts.map +1 -1
  129. package/dist/fcstd/structural-types.js +5 -0
  130. package/dist/fcstd/structural-types.js.map +1 -1
  131. package/dist/index.d.ts +7 -24
  132. package/dist/index.d.ts.map +1 -1
  133. package/dist/index.js +10 -16
  134. package/dist/index.js.map +1 -1
  135. package/dist/lang/determinism-scanner.d.ts +9 -0
  136. package/dist/lang/determinism-scanner.d.ts.map +1 -1
  137. package/dist/lang/determinism-scanner.js +7 -1
  138. package/dist/lang/determinism-scanner.js.map +1 -1
  139. package/dist/lang/symbol-table.d.ts +31 -0
  140. package/dist/lang/symbol-table.d.ts.map +1 -1
  141. package/dist/lang/symbol-table.generated.d.ts +6 -16
  142. package/dist/lang/symbol-table.generated.d.ts.map +1 -1
  143. package/dist/lang/symbol-table.generated.js +6 -16
  144. package/dist/lang/symbol-table.generated.js.map +1 -1
  145. package/dist/lang/symbol-table.js +50 -1
  146. package/dist/lang/symbol-table.js.map +1 -1
  147. package/dist/mesh/creased-normals.d.ts +50 -0
  148. package/dist/mesh/creased-normals.d.ts.map +1 -0
  149. package/dist/mesh/creased-normals.js +114 -0
  150. package/dist/mesh/creased-normals.js.map +1 -0
  151. package/dist/mesh/decoration-provider.d.ts +53 -0
  152. package/dist/mesh/decoration-provider.d.ts.map +1 -0
  153. package/dist/mesh/decoration-provider.js +21 -0
  154. package/dist/mesh/decoration-provider.js.map +1 -0
  155. package/dist/mesh/engrave.d.ts +4 -0
  156. package/dist/mesh/engrave.d.ts.map +1 -1
  157. package/dist/mesh/engrave.js +22 -31
  158. package/dist/mesh/engrave.js.map +1 -1
  159. package/dist/mesh/index.d.ts +5 -14
  160. package/dist/mesh/index.d.ts.map +1 -1
  161. package/dist/mesh/index.js +7 -19
  162. package/dist/mesh/index.js.map +1 -1
  163. package/dist/mesh/io.d.ts +2 -1
  164. package/dist/mesh/io.d.ts.map +1 -1
  165. package/dist/mesh/io.js +5 -7
  166. package/dist/mesh/io.js.map +1 -1
  167. package/dist/mesh/primitives.d.ts +5 -18
  168. package/dist/mesh/primitives.d.ts.map +1 -1
  169. package/dist/mesh/primitives.js +4 -48
  170. package/dist/mesh/primitives.js.map +1 -1
  171. package/dist/mesh/stl-loader.d.ts +23 -0
  172. package/dist/mesh/stl-loader.d.ts.map +1 -0
  173. package/dist/mesh/stl-loader.js +139 -0
  174. package/dist/mesh/stl-loader.js.map +1 -0
  175. package/dist/module-resolver/parse-imports.d.ts +37 -0
  176. package/dist/module-resolver/parse-imports.d.ts.map +1 -0
  177. package/dist/module-resolver/parse-imports.js +39 -0
  178. package/dist/module-resolver/parse-imports.js.map +1 -0
  179. package/dist/module-resolver/resolver.d.ts +1 -1
  180. package/dist/module-resolver/resolver.js +2 -2
  181. package/dist/module-resolver/resolver.js.map +1 -1
  182. package/dist/node-host/cli.d.ts.map +1 -1
  183. package/dist/node-host/cli.js +1 -22
  184. package/dist/node-host/cli.js.map +1 -1
  185. package/dist/primitives/text/cjk-font.d.ts +42 -0
  186. package/dist/primitives/text/cjk-font.d.ts.map +1 -0
  187. package/dist/primitives/text/cjk-font.js +86 -0
  188. package/dist/primitives/text/cjk-font.js.map +1 -0
  189. package/dist/sdk.d.ts +2 -2
  190. package/dist/sdk.js +2 -2
  191. package/dist/sdk.js.map +1 -1
  192. package/dist/symbol-table.d.ts +15 -0
  193. package/dist/symbol-table.d.ts.map +1 -0
  194. package/dist/symbol-table.js +14 -0
  195. package/dist/symbol-table.js.map +1 -0
  196. package/dist/topology/naming/lineage-resolve.js +1 -1
  197. package/dist/topology/naming/lineage-resolve.js.map +1 -1
  198. package/dist/vendored/brepjs/kernel/index.d.ts +5 -0
  199. package/dist/vendored/brepjs/kernel/index.d.ts.map +1 -1
  200. package/dist/vendored/brepjs/kernel/index.js +11 -0
  201. package/dist/vendored/brepjs/kernel/index.js.map +1 -1
  202. package/dist/weapp.d.ts +3 -3
  203. package/dist/weapp.d.ts.map +1 -1
  204. package/dist/weapp.js +6 -3
  205. package/dist/weapp.js.map +1 -1
  206. package/package.json +16 -14
  207. package/dist/api/compat/index.d.ts +0 -173
  208. package/dist/api/compat/index.d.ts.map +0 -1
  209. package/dist/api/compat/index.js +0 -222
  210. package/dist/api/compat/index.js.map +0 -1
  211. package/dist/api/compound.d.ts +0 -110
  212. package/dist/api/compound.d.ts.map +0 -1
  213. package/dist/api/compound.js +0 -164
  214. package/dist/api/compound.js.map +0 -1
  215. package/dist/api/copy.d.ts +0 -40
  216. package/dist/api/copy.d.ts.map +0 -1
  217. package/dist/api/copy.js +0 -83
  218. package/dist/api/copy.js.map +0 -1
  219. package/dist/api/fai_drill.d.ts +0 -46
  220. package/dist/api/fai_drill.d.ts.map +0 -1
  221. package/dist/api/fai_drill.js +0 -243
  222. package/dist/api/fai_drill.js.map +0 -1
  223. package/dist/api/fai_extrude.d.ts +0 -36
  224. package/dist/api/fai_extrude.d.ts.map +0 -1
  225. package/dist/api/fai_extrude.js +0 -79
  226. package/dist/api/fai_extrude.js.map +0 -1
  227. package/dist/api/fai_split.d.ts +0 -46
  228. package/dist/api/fai_split.d.ts.map +0 -1
  229. package/dist/api/fai_split.js +0 -254
  230. package/dist/api/fai_split.js.map +0 -1
  231. package/dist/api/load.d.ts +0 -41
  232. package/dist/api/load.d.ts.map +0 -1
  233. package/dist/api/load.js +0 -84
  234. package/dist/api/load.js.map +0 -1
  235. package/dist/api/svgExtrude.d.ts +0 -32
  236. package/dist/api/svgExtrude.d.ts.map +0 -1
  237. package/dist/api/svgExtrude.js +0 -74
  238. package/dist/api/svgExtrude.js.map +0 -1
  239. package/dist/api/text.d.ts +0 -34
  240. package/dist/api/text.d.ts.map +0 -1
  241. package/dist/api/text.js +0 -101
  242. package/dist/api/text.js.map +0 -1
  243. package/dist/brep/text/fontTestHelper.d.ts +0 -30
  244. package/dist/brep/text/fontTestHelper.d.ts.map +0 -1
  245. package/dist/brep/text/fontTestHelper.js +0 -57
  246. package/dist/brep/text/fontTestHelper.js.map +0 -1
  247. package/dist/cad-runtime/module-executor.d.ts +0 -271
  248. package/dist/cad-runtime/module-executor.d.ts.map +0 -1
  249. package/dist/cad-runtime/module-executor.js +0 -630
  250. package/dist/cad-runtime/module-executor.js.map +0 -1
  251. package/dist/cad-runtime/terminal-dag.d.ts +0 -65
  252. package/dist/cad-runtime/terminal-dag.d.ts.map +0 -1
  253. package/dist/cad-runtime/terminal-dag.js +0 -167
  254. package/dist/cad-runtime/terminal-dag.js.map +0 -1
  255. package/dist/faqts/browser.d.ts +0 -16
  256. package/dist/faqts/browser.d.ts.map +0 -1
  257. package/dist/faqts/browser.js +0 -13
  258. package/dist/faqts/browser.js.map +0 -1
  259. package/dist/faqts/exec-blob.d.ts +0 -14
  260. package/dist/faqts/exec-blob.d.ts.map +0 -1
  261. package/dist/faqts/exec-blob.js +0 -22
  262. package/dist/faqts/exec-blob.js.map +0 -1
  263. package/dist/faqts/exec-node.d.ts +0 -15
  264. package/dist/faqts/exec-node.d.ts.map +0 -1
  265. package/dist/faqts/exec-node.js +0 -29
  266. package/dist/faqts/exec-node.js.map +0 -1
  267. package/dist/faqts/imports.d.ts +0 -74
  268. package/dist/faqts/imports.d.ts.map +0 -1
  269. package/dist/faqts/imports.js +0 -95
  270. package/dist/faqts/imports.js.map +0 -1
  271. package/dist/faqts/index.d.ts +0 -22
  272. package/dist/faqts/index.d.ts.map +0 -1
  273. package/dist/faqts/index.js +0 -21
  274. package/dist/faqts/index.js.map +0 -1
  275. package/dist/faqts/node.d.ts +0 -23
  276. package/dist/faqts/node.d.ts.map +0 -1
  277. package/dist/faqts/node.js +0 -23
  278. package/dist/faqts/node.js.map +0 -1
  279. package/dist/faqts/run.d.ts +0 -62
  280. package/dist/faqts/run.d.ts.map +0 -1
  281. package/dist/faqts/run.js +0 -62
  282. package/dist/faqts/run.js.map +0 -1
  283. package/dist/faqts/transform.d.ts +0 -43
  284. package/dist/faqts/transform.d.ts.map +0 -1
  285. package/dist/faqts/transform.js +0 -35
  286. package/dist/faqts/transform.js.map +0 -1
  287. package/dist/lang/compile.d.ts +0 -50
  288. package/dist/lang/compile.d.ts.map +0 -1
  289. package/dist/lang/compile.js +0 -368
  290. package/dist/lang/compile.js.map +0 -1
  291. package/dist/lang/keep.d.ts +0 -109
  292. package/dist/lang/keep.d.ts.map +0 -1
  293. package/dist/lang/keep.js +0 -226
  294. package/dist/lang/keep.js.map +0 -1
  295. package/dist/lang/parser.d.ts +0 -91
  296. package/dist/lang/parser.d.ts.map +0 -1
  297. package/dist/lang/parser.js +0 -1594
  298. package/dist/lang/parser.js.map +0 -1
  299. package/dist/mesh/drill-hole/DrillHoleCore.d.ts +0 -90
  300. package/dist/mesh/drill-hole/DrillHoleCore.d.ts.map +0 -1
  301. package/dist/mesh/drill-hole/DrillHoleCore.js +0 -287
  302. package/dist/mesh/drill-hole/DrillHoleCore.js.map +0 -1
  303. package/dist/mesh/drill-hole/drill-types.d.ts +0 -34
  304. package/dist/mesh/drill-hole/drill-types.d.ts.map +0 -1
  305. package/dist/mesh/drill-hole/drill-types.js +0 -7
  306. package/dist/mesh/drill-hole/drill-types.js.map +0 -1
  307. package/dist/mesh/fai_drill.d.ts +0 -21
  308. package/dist/mesh/fai_drill.d.ts.map +0 -1
  309. package/dist/mesh/fai_drill.js +0 -92
  310. package/dist/mesh/fai_drill.js.map +0 -1
  311. package/dist/mesh/fai_extrude.d.ts +0 -24
  312. package/dist/mesh/fai_extrude.d.ts.map +0 -1
  313. package/dist/mesh/fai_extrude.js +0 -42
  314. package/dist/mesh/fai_extrude.js.map +0 -1
  315. package/dist/mesh/fai_split.d.ts +0 -164
  316. package/dist/mesh/fai_split.d.ts.map +0 -1
  317. package/dist/mesh/fai_split.js +0 -269
  318. package/dist/mesh/fai_split.js.map +0 -1
  319. package/dist/primitives/svg-extrude.d.ts +0 -43
  320. package/dist/primitives/svg-extrude.d.ts.map +0 -1
  321. package/dist/primitives/svg-extrude.js +0 -78
  322. package/dist/primitives/svg-extrude.js.map +0 -1
  323. package/dist/primitives/text/cjk.d.ts +0 -61
  324. package/dist/primitives/text/cjk.d.ts.map +0 -1
  325. package/dist/primitives/text/cjk.js +0 -215
  326. package/dist/primitives/text/cjk.js.map +0 -1
  327. package/dist/primitives/text-geometry.d.ts +0 -47
  328. package/dist/primitives/text-geometry.d.ts.map +0 -1
  329. package/dist/primitives/text-geometry.js +0 -127
  330. package/dist/primitives/text-geometry.js.map +0 -1
  331. package/dist/test-helpers.d.ts +0 -31
  332. package/dist/test-helpers.d.ts.map +0 -1
  333. package/dist/test-helpers.js +0 -55
  334. package/dist/test-helpers.js.map +0 -1
  335. package/dist/vendored/brepjs/core/kernelReentrancy.d.ts +0 -41
  336. package/dist/vendored/brepjs/core/kernelReentrancy.d.ts.map +0 -1
  337. package/dist/vendored/brepjs/core/kernelReentrancy.js +0 -68
  338. package/dist/vendored/brepjs/core/kernelReentrancy.js.map +0 -1
@@ -0,0 +1,165 @@
1
+ /**
2
+ * revolve — 手写平台 op(E3 / Q13 路线①的 revolve 实例)
3
+ *
4
+ * 生成投影(`api/generated/operations.ts` 的 revolve)是 compat op:几何由
5
+ * vendored brepjs 承载,但**没有可挂面命名的代码位置**,产物不带 roleTable,
6
+ * 下游 `cad.edgeRef` 抛 "nameless shape"(ModelFromV021 缺陷)。
7
+ *
8
+ * 本文件按 `cut` 覆盖生成投影的同一先例(`api-namespace.ts`),用 defineOp 包住
9
+ * 投影调用,并在产物登记处建链根 roleTable(origin = 语句 StmtId,与
10
+ * `extrude.ts` / `import-brep.ts` 同源机制)。
11
+ *
12
+ * 词汇表沿用生成 spec 的 construct 声明:`bottom` / `top`(旋转轴两端的平面
13
+ * 端面)+ `wall:<i>`(其余侧面,按枚举序)。判定口径与 extrude 相同——现场
14
+ * 几何是唯一真值:平面法向与轴 |cos| ≈ 1 → 端面,按中心沿轴坐标分 bottom/top;
15
+ * 其余(含圆柱等曲面侧面)→ wall:i。无法分类的面不进表(缺身份是显式状态)。
16
+ */
17
+ import { defineOp } from '../sdk.js';
18
+ import { getBackends, getCurrentStmt } from '../runtime-state.js';
19
+ import { brepOf } from '../shape.js';
20
+ import { adoptEntity, callBrepjs } from './internal/l3-bridge.js';
21
+ import { borrowDeep } from './internal/compat-op.js';
22
+ import { unwrapResult } from './internal/result-unwrap.js';
23
+ import { runtimeLineage } from '../topology/naming/lineage.js';
24
+ import { revolve as vendoredRevolve } from '../vendored/brepjs/operations/api.js';
25
+ import { formatRoleName, semantic, wall } from '../topology/naming/role-name.js';
26
+ /**
27
+ * revolve 的 construct 词汇表:`bottom` / `top`(旋转轴两端的平面端面)+ `wall:<i>`。
28
+ * 判定口径见 {@link revolveConstructRoles}。
29
+ */
30
+ /** options.axis 的宽松形态(数组或 {x,y,z})。 */
31
+ function axisVec(v) {
32
+ if (Array.isArray(v) && v.length >= 3 && v.every((n) => typeof n === 'number')) {
33
+ return [v[0], v[1], v[2]];
34
+ }
35
+ if (typeof v === 'object' && v !== null && 'x' in v) {
36
+ const o = v;
37
+ return [o.x, o.y, o.z];
38
+ }
39
+ return [0, 0, 1];
40
+ }
41
+ /**
42
+ * revolve 的 construct 词汇枚举器(与 `extrudeConstructRoles` 同口径,轴来源不同:
43
+ * extrude 从端面法向对差反推,revolve 直接用调用点声明的旋转轴)。
44
+ *
45
+ * @param kernel - the OCCT kernel.
46
+ * @param solid - the revolved solid.
47
+ * @param axis - the revolution axis (call-site declared; default [0,0,1]).
48
+ * @returns role(线格式串)→ hash 子表。
49
+ */
50
+ function revolveConstructRoles(kernel, solid, axisOpt) {
51
+ const roles = new Map();
52
+ const faceHandles = kernel.getSubShapes(solid, 'face');
53
+ try {
54
+ const hashes = kernel.subShapeHashes(solid, 'face', 2147483647);
55
+ const [ax0, ax1, ax2] = axisVec(axisOpt);
56
+ const axLen = Math.hypot(ax0, ax1, ax2);
57
+ if (axLen < 1e-9)
58
+ return roles;
59
+ const ax = [ax0 / axLen, ax1 / axLen, ax2 / axLen];
60
+ const caps = [];
61
+ const isPlaneCap = faceHandles.map((f) => {
62
+ if (kernel.surfaceType(f) !== 'plane')
63
+ return false;
64
+ const uv = kernel.uvBounds(f);
65
+ const n = kernel.surfaceNormal(f, (uv.uMin + uv.uMax) / 2, (uv.vMin + uv.vMax) / 2);
66
+ const len = Math.hypot(n.x, n.y, n.z) || 1;
67
+ const cos = Math.abs(n.x * ax[0] + n.y * ax[1] + n.z * ax[2]) / len;
68
+ return cos > 0.999;
69
+ });
70
+ for (let i = 0; i < faceHandles.length; i++) {
71
+ if (hashes[i] === undefined)
72
+ continue;
73
+ if (isPlaneCap[i]) {
74
+ const c = kernel.getSurfaceCenterOfMass(faceHandles[i]);
75
+ caps.push({ idx: i, t: c.x * ax[0] + c.y * ax[1] + c.z * ax[2] });
76
+ }
77
+ }
78
+ if (caps.length >= 2) {
79
+ // 常规旋转体:轴两端平面端面 = bottom/top,其余面(含曲面侧面)wall:<i>
80
+ let wallIdx = 0;
81
+ for (let i = 0; i < faceHandles.length; i++) {
82
+ const hash = hashes[i];
83
+ if (hash === undefined || isPlaneCap[i])
84
+ continue;
85
+ roles.set(formatRoleName(wall(wallIdx)), [hash]);
86
+ wallIdx++;
87
+ }
88
+ caps.sort((p, q) => p.t - q.t);
89
+ roles.set(formatRoleName(semantic('bottom')), [hashes[caps[0].idx]]);
90
+ roles.set(formatRoleName(semantic('top')), [hashes[caps[caps.length - 1].idx]]);
91
+ }
92
+ else {
93
+ // GOTCHA(退化形态,2026-09-23):轮廓面在轴平面内(如 XY 草图绕 Z 转)
94
+ // 时产物的面法向全部 ∥ 轴 → caps 判不出两端。此时退化为按枚举序
95
+ // wall:<i> 命名全部面——身份是能力,退化形态不给名字就会重演 nameless
96
+ // shape 缺陷;枚举序稳定(同 extrude 的 wall 序依据)。
97
+ for (let i = 0; i < faceHandles.length; i++) {
98
+ const hash = hashes[i];
99
+ if (hash === undefined)
100
+ continue;
101
+ roles.set(formatRoleName(wall(i)), [hash]);
102
+ }
103
+ }
104
+ return roles;
105
+ }
106
+ finally {
107
+ for (const h of faceHandles) {
108
+ try {
109
+ kernel.release(h);
110
+ }
111
+ catch { /* 已释放 */ }
112
+ }
113
+ }
114
+ }
115
+ /**
116
+ * 旋转成形:把平面轮廓绕轴旋转(兼容生成投影签名)。
117
+ * @group 特征
118
+ * @inputs 1
119
+ * @async true
120
+ * @qual ok
121
+ * @name revolve
122
+ * @param face - 平面轮廓。type:Shape required:true
123
+ * @param options - 旋转轴/点/角度(透传 vendored 语义)。type:RevolveOptions
124
+ * @returns Shape 旋转体(带链根 roleTable:bottom/top/wall:i)。
125
+ * @example
126
+ * const p1 = await cad.revolve(part0, { axis: [0, 0, 1], at: [0, 0, 0], angle: 6.283185307179586 })
127
+ */
128
+ export const revolve = defineOp({
129
+ brep: async (face, options) => {
130
+ // vendored 语义经 l3-bridge 三步桥接(与 compatOp 的 adapter 相同步骤,
131
+ // 但在这里执行以便在**同一处**收编产物并建链根 roleTable——compatOp 的
132
+ // 自动 adoptOut 会先登记一次,二次 fromBrep 会让 edgeRef 读到残缺表)。
133
+ const value = unwrapResult(await callBrepjs(vendoredRevolve, [borrowDeep(face, 0), borrowDeep(options ?? {}, 0)]), 'revolve');
134
+ const s = adoptEntity(value, 'revolve');
135
+ const kernel = getBackends().kernel.brep;
136
+ const handle = kernel ? brepOf(s) : undefined;
137
+ if (!kernel || !handle)
138
+ return s;
139
+ // E3(Q13 路线①):链根建 roleTable,origin = 语句 StmtId(Phase 1.6 口径)。
140
+ // GOTCHA(2026-09-23):不能对 adoptEntity 的产物再走一次 fromBrep——同语句的
141
+ // registeredStmtId 去重会让第二次登记被吞(探针实测:outputTables 里没有本
142
+ // 语句键)。直接经 runtimeLineage.recordOutput 落语句键表;define-op 包装层
143
+ // 会在 impl 返回后把它传播到 part 键权威位(edgeRef 的读口)。
144
+ const origin = String(getCurrentStmt()?.id ?? '');
145
+ const table = new Map([[origin, revolveConstructRoles(kernel, handle, options?.axis)]]);
146
+ // GOTCHA:recordOutput 必须带第 4 参 part——part 键表(outputTablesByPart)
147
+ // 是 op 实现与 edgeRef 解析的权威读口,只落语句键表时 part 键会保持
148
+ // adoptEntity 时登记的空表(探针实测),下游仍报 no role lineage。
149
+ const part = getCurrentStmt()?.outputs?.[0];
150
+ runtimeLineage.recordOutput(origin, table, handle, part);
151
+ return s;
152
+ },
153
+ naming: {
154
+ kind: 'construct',
155
+ newFaces: {
156
+ via: 'explicit',
157
+ vocab: [
158
+ { kind: 'semantic', name: 'top' },
159
+ { kind: 'semantic', name: 'bottom' },
160
+ { kind: 'wall', index: 0 },
161
+ ],
162
+ },
163
+ },
164
+ });
165
+ //# sourceMappingURL=revolve.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"revolve.js","sourceRoot":"","sources":["../../src/api/revolve.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * revolve — 手写平台 op(E3 / Q13 路线①的 revolve 实例)\n *\n * 生成投影(`api/generated/operations.ts` 的 revolve)是 compat op:几何由\n * vendored brepjs 承载,但**没有可挂面命名的代码位置**,产物不带 roleTable,\n * 下游 `cad.edgeRef` 抛 \"nameless shape\"(ModelFromV021 缺陷)。\n *\n * 本文件按 `cut` 覆盖生成投影的同一先例(`api-namespace.ts`),用 defineOp 包住\n * 投影调用,并在产物登记处建链根 roleTable(origin = 语句 StmtId,与\n * `extrude.ts` / `import-brep.ts` 同源机制)。\n *\n * 词汇表沿用生成 spec 的 construct 声明:`bottom` / `top`(旋转轴两端的平面\n * 端面)+ `wall:<i>`(其余侧面,按枚举序)。判定口径与 extrude 相同——现场\n * 几何是唯一真值:平面法向与轴 |cos| ≈ 1 → 端面,按中心沿轴坐标分 bottom/top;\n * 其余(含圆柱等曲面侧面)→ wall:i。无法分类的面不进表(缺身份是显式状态)。\n */\n\nimport type { Shape } from '../mesh/types'\nimport { defineOp } from '../sdk'\nimport { getBackends, getCurrentStmt } from '../runtime-state'\nimport { brepOf } from '../shape'\nimport { adoptEntity, callBrepjs } from './internal/l3-bridge'\nimport { borrowDeep } from './internal/compat-op'\nimport { unwrapResult } from './internal/result-unwrap'\nimport { runtimeLineage } from '../topology/naming/lineage'\nimport { revolve as vendoredRevolve } from '../vendored/brepjs/operations/api.js'\nimport { formatRoleName, semantic, wall } from '../topology/naming/role-name'\nimport type { BrepEngineApi } from '../brep/engine/primitives'\nimport type { BrepHandle } from '../brep/engine/types'\n\n/**\n * revolve 的 construct 词汇表:`bottom` / `top`(旋转轴两端的平面端面)+ `wall:<i>`。\n * 判定口径见 {@link revolveConstructRoles}。\n */\n\n/** options.axis 的宽松形态(数组或 {x,y,z})。 */\nfunction axisVec(v: unknown): readonly [number, number, number] {\n if (Array.isArray(v) && v.length >= 3 && v.every((n) => typeof n === 'number')) {\n return [v[0]!, v[1]!, v[2]!]\n }\n if (typeof v === 'object' && v !== null && 'x' in (v as object)) {\n const o = v as { x: number; y: number; z: number }\n return [o.x, o.y, o.z]\n }\n return [0, 0, 1]\n}\n\n/**\n * revolve 的 construct 词汇枚举器(与 `extrudeConstructRoles` 同口径,轴来源不同:\n * extrude 从端面法向对差反推,revolve 直接用调用点声明的旋转轴)。\n *\n * @param kernel - the OCCT kernel.\n * @param solid - the revolved solid.\n * @param axis - the revolution axis (call-site declared; default [0,0,1]).\n * @returns role(线格式串)→ hash 子表。\n */\nfunction revolveConstructRoles(\n kernel: BrepEngineApi,\n solid: BrepHandle,\n axisOpt: unknown,\n): Map<string, number[]> {\n const roles = new Map<string, number[]>()\n const faceHandles = kernel.getSubShapes(solid, 'face')\n try {\n const hashes = kernel.subShapeHashes(solid, 'face', 2147483647)\n const [ax0, ax1, ax2] = axisVec(axisOpt)\n const axLen = Math.hypot(ax0, ax1, ax2)\n if (axLen < 1e-9) return roles\n const ax: readonly [number, number, number] = [ax0 / axLen, ax1 / axLen, ax2 / axLen]\n\n const caps: { idx: number; t: number }[] = []\n const isPlaneCap: boolean[] = faceHandles.map((f) => {\n if (kernel.surfaceType(f) !== 'plane') return false\n const uv = kernel.uvBounds(f)\n const n = kernel.surfaceNormal(f, (uv.uMin + uv.uMax) / 2, (uv.vMin + uv.vMax) / 2)\n const len = Math.hypot(n.x, n.y, n.z) || 1\n const cos = Math.abs(n.x * ax[0]! + n.y * ax[1]! + n.z * ax[2]!) / len\n return cos > 0.999\n })\n for (let i = 0; i < faceHandles.length; i++) {\n if (hashes[i] === undefined) continue\n if (isPlaneCap[i]) {\n const c = kernel.getSurfaceCenterOfMass(faceHandles[i]!)\n caps.push({ idx: i, t: c.x * ax[0]! + c.y * ax[1]! + c.z * ax[2]! })\n }\n }\n if (caps.length >= 2) {\n // 常规旋转体:轴两端平面端面 = bottom/top,其余面(含曲面侧面)wall:<i>\n let wallIdx = 0\n for (let i = 0; i < faceHandles.length; i++) {\n const hash = hashes[i]\n if (hash === undefined || isPlaneCap[i]) continue\n roles.set(formatRoleName(wall(wallIdx)), [hash])\n wallIdx++\n }\n caps.sort((p, q) => p.t - q.t)\n roles.set(formatRoleName(semantic('bottom')), [hashes[caps[0]!.idx]!])\n roles.set(formatRoleName(semantic('top')), [hashes[caps[caps.length - 1]!.idx]!])\n } else {\n // GOTCHA(退化形态,2026-09-23):轮廓面在轴平面内(如 XY 草图绕 Z 转)\n // 时产物的面法向全部 ∥ 轴 → caps 判不出两端。此时退化为按枚举序\n // wall:<i> 命名全部面——身份是能力,退化形态不给名字就会重演 nameless\n // shape 缺陷;枚举序稳定(同 extrude 的 wall 序依据)。\n for (let i = 0; i < faceHandles.length; i++) {\n const hash = hashes[i]\n if (hash === undefined) continue\n roles.set(formatRoleName(wall(i)), [hash])\n }\n }\n return roles\n } finally {\n for (const h of faceHandles) {\n try { kernel.release(h) } catch { /* 已释放 */ }\n }\n }\n}\n\n/**\n * 旋转成形:把平面轮廓绕轴旋转(兼容生成投影签名)。\n * @group 特征\n * @inputs 1\n * @async true\n * @qual ok\n * @name revolve\n * @param face - 平面轮廓。type:Shape required:true\n * @param options - 旋转轴/点/角度(透传 vendored 语义)。type:RevolveOptions\n * @returns Shape 旋转体(带链根 roleTable:bottom/top/wall:i)。\n * @example\n * const p1 = await cad.revolve(part0, { axis: [0, 0, 1], at: [0, 0, 0], angle: 6.283185307179586 })\n */\nexport const revolve = defineOp({\n brep: async (face: Shape, options?: { axis?: unknown }) => {\n // vendored 语义经 l3-bridge 三步桥接(与 compatOp 的 adapter 相同步骤,\n // 但在这里执行以便在**同一处**收编产物并建链根 roleTable——compatOp 的\n // 自动 adoptOut 会先登记一次,二次 fromBrep 会让 edgeRef 读到残缺表)。\n const value = unwrapResult(\n await callBrepjs(vendoredRevolve as never, [borrowDeep(face, 0), borrowDeep(options ?? {}, 0)]),\n 'revolve',\n )\n const s = adoptEntity(value, 'revolve') as Shape\n const kernel = getBackends().kernel.brep as BrepEngineApi | null\n const handle = kernel ? (brepOf(s) as BrepHandle | undefined) : undefined\n if (!kernel || !handle) return s\n // E3(Q13 路线①):链根建 roleTable,origin = 语句 StmtId(Phase 1.6 口径)。\n // GOTCHA(2026-09-23):不能对 adoptEntity 的产物再走一次 fromBrep——同语句的\n // registeredStmtId 去重会让第二次登记被吞(探针实测:outputTables 里没有本\n // 语句键)。直接经 runtimeLineage.recordOutput 落语句键表;define-op 包装层\n // 会在 impl 返回后把它传播到 part 键权威位(edgeRef 的读口)。\n const origin = String(getCurrentStmt()?.id ?? '')\n const table = new Map([[origin, revolveConstructRoles(kernel, handle, options?.axis)]])\n // GOTCHA:recordOutput 必须带第 4 参 part——part 键表(outputTablesByPart)\n // 是 op 实现与 edgeRef 解析的权威读口,只落语句键表时 part 键会保持\n // adoptEntity 时登记的空表(探针实测),下游仍报 no role lineage。\n const part = getCurrentStmt()?.outputs?.[0]\n runtimeLineage.recordOutput(origin as never, table, handle, part as never)\n return s\n },\n naming: {\n kind: 'construct',\n newFaces: {\n via: 'explicit',\n vocab: [\n { kind: 'semantic', name: 'top' },\n { kind: 'semantic', name: 'bottom' },\n { kind: 'wall', index: 0 },\n ],\n },\n } as never,\n})\n"]}
@@ -29,6 +29,7 @@
29
29
  /** 生成器可用的投影方式。 */
30
30
  export type ProjectionKind = 'brep-op' | 'query' | 'pure' | 'type' | 'skip' | 'faijs';
31
31
  import type { Provenance } from '../../topology/naming/lineage.js';
32
+ import type { BrepCapabilityName } from '../../cad-runtime/backend-dispatch.js';
32
33
  export type { Provenance } from '../../topology/naming/lineage.js';
33
34
  /** brep-op / query 的时间线消费声明(透传 defineOp 元数据,G3/G4)。 */
34
35
  /**
@@ -94,6 +95,13 @@ export interface ArgSpecEntry {
94
95
  returnType?: string;
95
96
  /** P20: 机器参数名表(按位置顺序),供 dual-form-args resolveArgs 映射对象形态→位置数组。 */
96
97
  params?: string[];
98
+ /**
99
+ * Phase 1(Brep 引擎可切换重构):该 brep-op 所需的内核能力名(`BrepCapabilityName`:
100
+ * 族级布尔 / `BrepEvolutionKind` 真名 / `BrepMethodKind` 真名)。透传给 defineOp,
101
+ * 由 backend-dispatch 能力路由做执行前静态判定。依据 Phase 0 能力映射表
102
+ * (api/surface/capability-map.json)逐条填写。
103
+ */
104
+ capabilities?: BrepCapabilityName[];
97
105
  /** P20: D11 形态分类(A 单名双形态 / B1 单名单形态 / B2 双名)。 */
98
106
  formClass?: FormClass;
99
107
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"arg-spec.d.ts","sourceRoot":"","sources":["../../../src/api/surface/arg-spec.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,kBAAkB;AAClB,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAA;AAErF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAA;AAE/D,YAAY,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAA;AAE/D,uDAAuD;AAEvD;;;GAGG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,8CAA8C;IAC9C,IAAI,EAAE,MAAM,CAAA;IACZ,iDAAiD;IACjD,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,kBAAkB;IAClB,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED;;;;;;GAMG;AACH,MAAM,MAAM,SAAS,GAAG,GAAG,GAAG,IAAI,GAAG,IAAI,CAAA;AAEzC;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,cAAc,CAAA;IACpB,6BAA6B;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,qDAAqD;IACrD,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,qEAAqE;IACrE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;IACvB;;OAEG;IACH,sBAAsB,CAAC,EAAE,MAAM,EAAE,CAAA;IACjC,8GAA8G;IAC9G,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,yFAAyF;IACzF,WAAW,CAAC,EAAE,UAAU,EAAE,CAAA;IAC1B,uNAAuN;IACvN,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,mEAAmE;IACnE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;IACjB,iDAAiD;IACjD,SAAS,CAAC,EAAE,SAAS,CAAA;IACrB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,UAAU,CAAA;CACpB;AAED;;;;GAIG;AACH,eAAO,MAAM,QAAQ,EAAE,YAAY,EAy/GlC,CAAA"}
1
+ {"version":3,"file":"arg-spec.d.ts","sourceRoot":"","sources":["../../../src/api/surface/arg-spec.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,kBAAkB;AAClB,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAA;AAErF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAA;AAC/D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAA;AAE5E,YAAY,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAA;AAE/D,uDAAuD;AAEvD;;;GAGG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,8CAA8C;IAC9C,IAAI,EAAE,MAAM,CAAA;IACZ,iDAAiD;IACjD,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,kBAAkB;IAClB,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED;;;;;;GAMG;AACH,MAAM,MAAM,SAAS,GAAG,GAAG,GAAG,IAAI,GAAG,IAAI,CAAA;AAEzC;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,cAAc,CAAA;IACpB,6BAA6B;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,qDAAqD;IACrD,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,qEAAqE;IACrE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;IACvB;;OAEG;IACH,sBAAsB,CAAC,EAAE,MAAM,EAAE,CAAA;IACjC,8GAA8G;IAC9G,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,yFAAyF;IACzF,WAAW,CAAC,EAAE,UAAU,EAAE,CAAA;IAC1B,uNAAuN;IACvN,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,mEAAmE;IACnE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;IACjB;;;;;OAKG;IACH,YAAY,CAAC,EAAE,kBAAkB,EAAE,CAAA;IACnC,iDAAiD;IACjD,SAAS,CAAC,EAAE,SAAS,CAAA;IACrB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,UAAU,CAAA;CACpB;AAED;;;;GAIG;AACH,eAAO,MAAM,QAAQ,EAAE,YAAY,EA0/GlC,CAAA"}
@@ -41,6 +41,7 @@ export const ARG_SPEC = [
41
41
  name: 'torus',
42
42
  source: 'topology/primitiveFns.js#torus',
43
43
  kind: 'brep-op',
44
+ capabilities: ["dispose", "makeTorus"],
44
45
  args: '(majorRadius: number, minorRadius: number, options?: TorusOptions)',
45
46
  // 构造类:无几何输入(纯数值参数),brepjs 返回裸 ValidSolid(非 Result)。
46
47
  geometryArgs: [],
@@ -54,6 +55,7 @@ export const ARG_SPEC = [
54
55
  name: 'fuse',
55
56
  source: 'topology/booleanFns.js#fuse',
56
57
  kind: 'brep-op',
58
+ capabilities: ["dispose", "fuse", "fuseWithHistory", "isNull"],
57
59
  args: '(a: Shape3D, b: Shape3D, options?: BooleanOptions) -> Result<Shape3D>',
58
60
  // 两个输入都是 faijs Shape → 借入 brepjs handle;第三参 options 透传。
59
61
  geometryArgs: [0, 1],
@@ -1422,7 +1424,7 @@ export const ARG_SPEC = [
1422
1424
  },
1423
1425
  {
1424
1426
  // ---- brep-op:单/多单形状入参 → 单产物收养 ----
1425
- name: 'extrude', source: 'operations/api.js#extrude', kind: 'brep-op', module: 'operations',
1427
+ name: 'extrude', source: 'operations/api.js#extrude', kind: 'brep-op', capabilities: ["dispose", "downcast", "extrude", "isNull"], module: 'operations',
1426
1428
  geometryArgs: [0],
1427
1429
  reason: 'faijs 侧 cad.extrude 由手写平台 op 覆盖(api/extrude.ts:对象形态 + upTo 拉伸到面/到支持体端面)。本投影只作为「长度形态」的引擎被手写 op 委托调用(vendored 是唯一拉伸引擎,既有 cad.extrude(face,[x,y,z]) 语义零漂移),生成模块符号不直接进 cad 命名空间 by design(同 fillet 口径)。',
1428
1430
  args: 'extrude(face: Shape, height: number|Vec3) → Shape|extrude(face: Shape, params: { length? | upTo, normal?, mode?, baseFeature?, offset? }) → Shape',
@@ -1430,35 +1432,35 @@ export const ARG_SPEC = [
1430
1432
  naming: { kind: 'construct', newFaces: { via: 'explicit', vocab: [{ kind: 'semantic', name: 'top' }, { kind: 'semantic', name: 'bottom' }] } },
1431
1433
  },
1432
1434
  {
1433
- name: 'revolve', source: 'operations/api.js#revolve', kind: 'brep-op', module: 'operations',
1435
+ name: 'revolve', source: 'operations/api.js#revolve', kind: 'brep-op', capabilities: ["dispose", "isNull", "revolveVec", "shapeType"], module: 'operations',
1434
1436
  geometryArgs: [0], reason: 'shapeable 面 → Result(Shape3D),brep-op',
1435
1437
  args: 'revolve(face: Shape, options?: RevolveOptions): Shape',
1436
1438
  params: ['face', 'options'], formClass: 'A',
1437
1439
  naming: { kind: 'construct', newFaces: { via: 'explicit', vocab: [{ kind: 'semantic', name: 'top' }, { kind: 'semantic', name: 'bottom' }, { kind: 'wall', index: 0 }] } },
1438
1440
  },
1439
1441
  {
1440
- name: 'sweep', source: 'operations/extrudeFns.js#sweep', kind: 'brep-op', module: 'operations',
1442
+ name: 'sweep', source: 'operations/extrudeFns.js#sweep', kind: 'brep-op', capabilities: ["dispose", "shapeType", "simplePipe", "sweepPipeShell"], module: 'operations',
1441
1443
  geometryArgs: [0, 1], reason: 'wire + spine → Result(Shape3D|tuple),默认单产物,brep-op',
1442
1444
  args: 'sweep(wire: Shape, spine: Shape, config?: SweepOptions, shellMode?: boolean): Shape',
1443
1445
  params: ['wire', 'spine', 'config', 'shellMode'], formClass: 'A',
1444
1446
  naming: { kind: 'kernel', newFaces: { via: 'byAdjacency' } },
1445
1447
  },
1446
1448
  {
1447
- name: 'complexExtrude', source: 'operations/extrudeFns.js#complexExtrude', kind: 'brep-op', module: 'operations',
1449
+ name: 'complexExtrude', source: 'operations/extrudeFns.js#complexExtrude', kind: 'brep-op', capabilities: ["buildExtrusionLaw", "dispose", "shapeType", "simplePipe", "sweepPipeShell"], module: 'operations',
1448
1450
  geometryArgs: [0], reason: 'wire → Result(Shape3D),brep-op',
1449
1451
  args: 'complexExtrude(wire: Shape, center: Vec3, normal: Vec3, profile?: ExtrusionProfile): Shape',
1450
1452
  params: ['wire', 'center', 'normal', 'profile'], formClass: 'A',
1451
1453
  naming: { kind: 'kernel', newFaces: { via: 'byAdjacency' } },
1452
1454
  },
1453
1455
  {
1454
- name: 'twistExtrude', source: 'operations/extrudeFns.js#twistExtrude', kind: 'brep-op', module: 'operations',
1456
+ name: 'twistExtrude', source: 'operations/extrudeFns.js#twistExtrude', kind: 'brep-op', capabilities: ["buildExtrusionLaw", "dispose", "shapeType", "simplePipe", "sweepPipeShell"], module: 'operations',
1455
1457
  geometryArgs: [0], reason: 'wire → Result(Shape3D),brep-op',
1456
1458
  args: 'twistExtrude(wire: Shape, angleDegrees: number, center: Vec3, normal: Vec3): Shape',
1457
1459
  params: ['wire', 'angleDegrees', 'center', 'normal'], formClass: 'A',
1458
1460
  naming: { kind: 'kernel', newFaces: { via: 'byAdjacency' } },
1459
1461
  },
1460
1462
  {
1461
- name: 'linearPattern', source: 'operations/patternFns.js#linearPattern', kind: 'brep-op', module: 'operations',
1463
+ name: 'linearPattern', source: 'operations/patternFns.js#linearPattern', kind: 'brep-op', capabilities: ["dispose", "fuseAll", "hashCode", "isNull", "iterShapes", "linearPattern", "section", "surfaceCenterOfMass", "surfaceNormal", "surfaceType", "uvBounds"], module: 'operations',
1462
1464
  geometryArgs: [0], reason: 'shape → Result(Shape3D),brep-op',
1463
1465
  args: 'linearPattern(shape: Shape, direction: Vec3, count: number, spacing: number): Shape',
1464
1466
  params: ['shape', 'direction', 'count', 'spacing'], formClass: 'A',
@@ -1466,7 +1468,7 @@ export const ARG_SPEC = [
1466
1468
  naming: { kind: 'replicate', k: 0 },
1467
1469
  },
1468
1470
  {
1469
- name: 'circularPattern', source: 'operations/patternFns.js#circularPattern', kind: 'brep-op', module: 'operations',
1471
+ name: 'circularPattern', source: 'operations/patternFns.js#circularPattern', kind: 'brep-op', capabilities: ["circularPattern", "dispose", "fuseAll", "hashCode", "isNull", "iterShapes", "section", "surfaceCenterOfMass", "surfaceNormal", "surfaceType", "uvBounds"], module: 'operations',
1470
1472
  geometryArgs: [0], reason: 'shape → Result(Shape3D),brep-op',
1471
1473
  args: 'circularPattern(shape: Shape, axis: Vec3, count: number, fullAngle?: number, center?: Vec3): Shape',
1472
1474
  params: ['shape', 'axis', 'count', 'fullAngle', 'center'], formClass: 'A',
@@ -1474,7 +1476,7 @@ export const ARG_SPEC = [
1474
1476
  naming: { kind: 'replicate', k: 0 },
1475
1477
  },
1476
1478
  {
1477
- name: 'gridPattern', source: 'operations/patternFns.js#gridPattern', kind: 'brep-op', module: 'operations',
1479
+ name: 'gridPattern', source: 'operations/patternFns.js#gridPattern', kind: 'brep-op', capabilities: ["dispose", "fuseAll", "gridPattern", "hashCode", "isNull", "iterShapes", "linearPattern", "section", "surfaceCenterOfMass", "surfaceNormal", "surfaceType", "uvBounds"], module: 'operations',
1478
1480
  geometryArgs: [0], reason: 'shape → Result(Shape3D),brep-op',
1479
1481
  args: 'gridPattern(shape: Shape, directionX: Vec3, directionY: Vec3, countX: number, countY: number, spacingX: number, spacingY: number): Shape',
1480
1482
  params: ['shape', 'directionX', 'directionY', 'countX', 'countY', 'spacingX', 'spacingY'], formClass: 'A',
@@ -1482,14 +1484,14 @@ export const ARG_SPEC = [
1482
1484
  naming: { kind: 'replicate', k: 0 },
1483
1485
  },
1484
1486
  {
1485
- name: 'roof', source: 'operations/roofFns.js#roof', kind: 'brep-op', module: 'operations',
1487
+ name: 'roof', source: 'operations/roofFns.js#roof', kind: 'brep-op', capabilities: ["buildTriFace", "dispose", "fixShape", "isValid", "sew", "sewAndSolidify"], module: 'operations',
1486
1488
  geometryArgs: [0], reason: 'wire → Result(ValidSolid)→solid,brep-op',
1487
1489
  args: 'roof(wire: Shape, options?: RoofOptions): Shape',
1488
1490
  params: ['wire', 'options'], formClass: 'A',
1489
1491
  naming: { kind: 'kernel', newFaces: { via: 'byAdjacency' } },
1490
1492
  },
1491
1493
  {
1492
- name: 'drill', source: 'operations/compoundOpsFns.js#drill', kind: 'brep-op', module: 'operations',
1494
+ name: 'drill', source: 'operations/compoundOpsFns.js#drill', kind: 'brep-op', capabilities: ["boundingBox", "cut", "cutWithHistory", "dispose", "isNull", "makeCylinder"], module: 'operations',
1493
1495
  geometryArgs: [0], reason: 'Shapeable<Shape3D> → Result<T>,brep-op',
1494
1496
  args: 'drill(shape: Shape, options: DrillOptions): Shape',
1495
1497
  params: ['shape', 'options'], formClass: 'A',
@@ -1497,7 +1499,7 @@ export const ARG_SPEC = [
1497
1499
  naming: { kind: 'kernel', newFaces: { via: 'byAdjacency' } },
1498
1500
  },
1499
1501
  {
1500
- name: 'pocket', source: 'operations/compoundOpsFns.js#pocket', kind: 'brep-op', module: 'operations',
1502
+ name: 'pocket', source: 'operations/compoundOpsFns.js#pocket', kind: 'brep-op', capabilities: ["addHolesInFace", "cut", "cutWithHistory", "dispose", "downcast", "extrude", "isNull", "makeFace", "surfaceCenterOfMass", "surfaceNormal", "surfaceType", "translateWithHistory", "uvBounds"], module: 'operations',
1501
1503
  geometryArgs: [0], reason: 'Shapeable<Shape3D> → Result<T>,brep-op',
1502
1504
  args: 'pocket(shape: Shape, options: PocketOptions): Shape',
1503
1505
  params: ['shape', 'options'], formClass: 'A',
@@ -1505,7 +1507,7 @@ export const ARG_SPEC = [
1505
1507
  naming: { kind: 'kernel', newFaces: { via: 'byAdjacency' } },
1506
1508
  },
1507
1509
  {
1508
- name: 'boss', source: 'operations/compoundOpsFns.js#boss', kind: 'brep-op', module: 'operations',
1510
+ name: 'boss', source: 'operations/compoundOpsFns.js#boss', kind: 'brep-op', capabilities: ["addHolesInFace", "dispose", "downcast", "extrude", "fuse", "fuseWithHistory", "isNull", "makeFace", "surfaceCenterOfMass", "surfaceNormal", "surfaceType", "translateWithHistory", "uvBounds"], module: 'operations',
1509
1511
  geometryArgs: [0], reason: 'Shapeable<Shape3D> → Result<T>,brep-op',
1510
1512
  args: 'boss(shape: Shape, options: BossOptions): Shape',
1511
1513
  params: ['shape', 'options'], formClass: 'A',
@@ -1513,7 +1515,7 @@ export const ARG_SPEC = [
1513
1515
  naming: { kind: 'kernel', newFaces: { via: 'byAdjacency' } },
1514
1516
  },
1515
1517
  {
1516
- name: 'mirrorJoin', source: 'operations/compoundOpsFns.js#mirrorJoin', kind: 'brep-op', module: 'operations',
1518
+ name: 'mirrorJoin', source: 'operations/compoundOpsFns.js#mirrorJoin', kind: 'brep-op', capabilities: ["dispose", "fuse", "fuseWithHistory", "isNull", "mirrorWithHistory"], module: 'operations',
1517
1519
  geometryArgs: [0], reason: 'Shapeable<Shape3D> → Result<T>,brep-op',
1518
1520
  args: 'mirrorJoin(shape: Shape, options?: MirrorJoinOptions): Shape',
1519
1521
  params: ['shape', 'options'], formClass: 'A',
@@ -1521,7 +1523,7 @@ export const ARG_SPEC = [
1521
1523
  naming: { kind: 'replicate', k: 2 },
1522
1524
  },
1523
1525
  {
1524
- name: 'rectangularPattern', source: 'operations/compoundOpsFns.js#rectangularPattern', kind: 'brep-op', module: 'operations',
1526
+ name: 'rectangularPattern', source: 'operations/compoundOpsFns.js#rectangularPattern', kind: 'brep-op', capabilities: ["dispose", "fuse", "fuseAll", "fuseWithHistory", "hashCode", "isNull", "iterShapes", "section", "surfaceCenterOfMass", "surfaceNormal", "surfaceType", "translateWithHistory", "uvBounds"], module: 'operations',
1525
1527
  geometryArgs: [0], reason: 'Shapeable<Shape3D> → Result<T>,brep-op',
1526
1528
  args: 'rectangularPattern(shape: Shape, options: RectangularPatternOptions): Shape',
1527
1529
  params: ['shape', 'options'], formClass: 'A',
@@ -1529,14 +1531,14 @@ export const ARG_SPEC = [
1529
1531
  naming: { kind: 'replicate', k: 0 },
1530
1532
  },
1531
1533
  {
1532
- name: 'thread', source: 'operations/threadFns.js#thread', kind: 'brep-op', module: 'operations',
1534
+ name: 'thread', source: 'operations/threadFns.js#thread', kind: 'brep-op', capabilities: ["dispose", "loftAdvanced", "makeLineEdge", "makeVertex", "makeWireFromMixed", "shapeType"], module: 'operations',
1533
1535
  geometryArgs: [], reason: '仅参数构造 → Result(Shape3D),单产物,brep-op',
1534
1536
  args: 'thread(options: ThreadOptions): Shape',
1535
1537
  params: ['options'], formClass: 'B1',
1536
1538
  naming: { kind: 'kernel', newFaces: { via: 'byAdjacency' } },
1537
1539
  },
1538
1540
  {
1539
- name: 'convexHull', source: 'operations/convexHullFns.js#convexHull', kind: 'brep-op', module: 'operations',
1541
+ name: 'convexHull', source: 'operations/convexHullFns.js#convexHull', kind: 'brep-op', capabilities: ["dispose", "hullFromPoints", "shapeType"], module: 'operations',
1540
1542
  geometryArgs: [], reason: '点集构造 → Result(Solid),单产物,brep-op',
1541
1543
  args: 'convexHull(points: Vec3[]): Shape',
1542
1544
  params: ['points'], formClass: 'A',
@@ -2227,7 +2229,7 @@ export const ARG_SPEC = [
2227
2229
  },
2228
2230
  // 1 × brep-op(构造类:纯数值参数 → Shape3D,无几何输入)
2229
2231
  {
2230
- name: 'makeBaseBox', source: 'sketching/shortcuts.js#makeBaseBox', kind: 'brep-op', module: 'sketching',
2232
+ name: 'makeBaseBox', source: 'sketching/shortcuts.js#makeBaseBox', kind: 'brep-op', capabilities: ["addHolesInFace", "buildEdgeOnSurface", "buildExtrusionLaw", "copyShape", "curveParameters", "curvePointAtParam", "curveTangent", "dispose", "downcast", "extrude", "isNull", "loftAdvanced", "makeFace", "makeFaceOnSurface", "makeVertex", "makeWireFromMixed", "mirror", "revolveVec", "shapeType", "simplePipe", "surfaceType", "sweepPipeShell"], module: 'sketching',
2231
2233
  args: '(xLength: number, yLength: number, zLength: number) -> Shape3D',
2232
2234
  geometryArgs: [],
2233
2235
  returnsResult: false,
@@ -2510,7 +2512,7 @@ export const ARG_SPEC = [
2510
2512
  reason: 'overridden by handwritten api/primitives.ts (cone dual-op, mesh+brep)',
2511
2513
  },
2512
2514
  {
2513
- name: 'ellipsoid', source: 'topology/primitiveFns.js#ellipsoid', kind: 'brep-op',
2515
+ name: 'ellipsoid', source: 'topology/primitiveFns.js#ellipsoid', kind: 'brep-op', capabilities: ["dispose", "makeEllipsoid", "translateWithHistory"],
2514
2516
  geometryArgs: [], returnsResult: false,
2515
2517
  args: 'ellipsoid(rx: number, ry: number, rz: number, options?: EllipsoidOptions): Shape',
2516
2518
  reason: '纯数值整件构造(rx/ry/rz → ValidSolid),brep-op',
@@ -2609,7 +2611,7 @@ export const ARG_SPEC = [
2609
2611
  reason: 'faijs 同名 translate(§5.1 双形态:对象形态手写面覆盖 + v:Vec3 位置形态并入),生成层不重复投影',
2610
2612
  },
2611
2613
  {
2612
- name: 'rotate', source: 'topology/api.js#rotate', kind: 'brep-op',
2614
+ name: 'rotate', source: 'topology/api.js#rotate', kind: 'brep-op', capabilities: ["dispose", "rotateWithHistory"],
2613
2615
  geometryArgs: [0], returnsResult: false,
2614
2616
  args: 'rotate(shape: Shape, angle: number, options?: { at?, axis? }): Shape',
2615
2617
  reason: 'faijs rotate 已更名 rotate_euler(faijs 面只导出 rotate_euler),上游轴角 rotate 空出 → brep-op 进脚本面'
@@ -2625,7 +2627,7 @@ export const ARG_SPEC = [
2625
2627
  reason: 'overridden by handwritten api/transform.ts (scale dual-op, mesh+brep)',
2626
2628
  },
2627
2629
  {
2628
- name: 'mirror', source: 'topology/api.js#mirror', kind: 'brep-op',
2630
+ name: 'mirror', source: 'topology/api.js#mirror', kind: 'brep-op', capabilities: ["dispose", "mirrorWithHistory"],
2629
2631
  geometryArgs: [0], returnsResult: false,
2630
2632
  args: 'mirror(shape: Shape, options?: MirrorOptions): Shape',
2631
2633
  reason: 'faijs 无同名 mirror,整件反射 → brep-op',
@@ -2634,7 +2636,7 @@ export const ARG_SPEC = [
2634
2636
  naming: { kind: 'kernel', newFaces: { via: 'byAdjacency' } },
2635
2637
  },
2636
2638
  {
2637
- name: 'clone', source: 'topology/api.js#clone', kind: 'brep-op',
2639
+ name: 'clone', source: 'topology/api.js#clone', kind: 'brep-op', capabilities: ["copyShape", "dispose"],
2638
2640
  geometryArgs: [0], returnsResult: true,
2639
2641
  args: 'clone(shape: Shape): Shape',
2640
2642
  reason: 'faijs 用 copy(不同名),整件克隆(Result<T>)→ brep-op',
@@ -2643,7 +2645,7 @@ export const ARG_SPEC = [
2643
2645
  naming: { kind: 'identity' },
2644
2646
  },
2645
2647
  {
2646
- name: 'applyMatrix', source: 'topology/api.js#applyMatrix', kind: 'brep-op',
2648
+ name: 'applyMatrix', source: 'topology/api.js#applyMatrix', kind: 'brep-op', capabilities: ["dispose", "generalTransformNonOrthogonal", "generalTransformWithHistory", "hashCode", "iterShapes", "surfaceCenterOfMass", "surfaceNormal", "surfaceType", "uvBounds"],
2647
2649
  geometryArgs: [0], returnsResult: true,
2648
2650
  args: 'applyMatrix(shape: Shape, matrix: unknown): Shape',
2649
2651
  reason: 'faijs 用 applyTransform(不同名),整件矩阵变换 → brep-op',
@@ -2652,16 +2654,15 @@ export const ARG_SPEC = [
2652
2654
  naming: { kind: 'identity' },
2653
2655
  },
2654
2656
  {
2655
- name: 'transformCopy', source: 'topology/api.js#transformCopy', kind: 'brep-op',
2657
+ name: 'transformCopy', source: 'topology/api.js#transformCopy', kind: 'skip',
2656
2658
  geometryArgs: [0], returnsResult: false,
2657
2659
  args: 'transformCopy(shape: Shape, composed: ComposedTransform): Shape',
2658
- reason: 'faijs 无同名,克隆+复合变换 → brep-op',
2660
+ reason: 'scriptFace: ComposedTransform holds a kernel WASM handle — not constructible in .fai.js (no literal/params path), so the script-face op is dead. Covered by clone+translate/rotate chains and locate. TS library surface keeps the plain re-export (non-op).',
2659
2661
  params: ['shape', 'composed'], formClass: 'A',
2660
- scriptFace: true,
2661
2662
  naming: { kind: 'identity' },
2662
2663
  },
2663
2664
  {
2664
- name: 'locate', source: 'topology/api.js#locate', kind: 'brep-op',
2665
+ name: 'locate', source: 'topology/api.js#locate', kind: 'brep-op', capabilities: ["composeTransform", "dispose", "hashCode", "locate"],
2665
2666
  geometryArgs: [0], returnsResult: false,
2666
2667
  args: 'locate(shape: Shape, placement: unknown): Shape',
2667
2668
  reason: 'faijs 无同名,整件定位变换 → brep-op',
@@ -2698,7 +2699,7 @@ export const ARG_SPEC = [
2698
2699
  + '(含 UI ops 与存量迁移)——生成期守卫见 gen-l3-surface.ts(§4.8 触发条件)。',
2699
2700
  },
2700
2701
  {
2701
- name: 'section', source: 'topology/api.js#section', kind: 'brep-op',
2702
+ name: 'section', source: 'topology/api.js#section', kind: 'brep-op', capabilities: ["dispose", "isNull", "section"],
2702
2703
  geometryArgs: [0], returnsResult: true,
2703
2704
  args: 'section(shape: Shape, plane: PlaneInput): Shape',
2704
2705
  params: ['shape', 'plane'], formClass: 'A',
@@ -2709,7 +2710,7 @@ export const ARG_SPEC = [
2709
2710
  reason: '返回 Face 子形状产物,faijs 整件面不承载,skip',
2710
2711
  },
2711
2712
  {
2712
- name: 'split', source: 'topology/api.js#split', kind: 'brep-op',
2713
+ name: 'split', source: 'topology/api.js#split', kind: 'brep-op', capabilities: ["dispose", "isNull", "split"],
2713
2714
  geometryArgs: [0], returnsResult: true,
2714
2715
  args: 'split(shape: Shape, tools: Shape[]): Shape',
2715
2716
  reason: 'faijs split 已更名 fai_split,上游工具切件 split 空出 → brep-op(§5.1 D-SPLIT;tools 暂登记几何首参,数组切件经 faijs 侧适配)',
@@ -2731,14 +2732,14 @@ export const ARG_SPEC = [
2731
2732
  reason: 'faijs 同名 chamfer(§5.1 O-CHAMFER-1:role 取边已保留,上游 Edge 句柄取边形态待处置),生成层不重复投影',
2732
2733
  },
2733
2734
  {
2734
- name: 'shell', source: 'topology/api.js#shell', kind: 'brep-op',
2735
+ name: 'shell', source: 'topology/api.js#shell', kind: 'brep-op', capabilities: ["dispose", "shapeType", "shell", "shellWithHistory"],
2735
2736
  geometryArgs: [0], returnsResult: true,
2736
2737
  args: 'shell(shape: Shape, faces?: Shape[], thickness: number): Shape',
2737
2738
  params: ['shape', 'faces', 'thickness'], formClass: 'A',
2738
2739
  naming: { kind: 'kernel', newFaces: { via: 'byAdjacency' } },
2739
2740
  },
2740
2741
  {
2741
- name: 'offset', source: 'topology/api.js#offset', kind: 'brep-op',
2742
+ name: 'offset', source: 'topology/api.js#offset', kind: 'brep-op', capabilities: ["dispose", "offsetWithHistory", "shapeType"],
2742
2743
  geometryArgs: [0], returnsResult: true,
2743
2744
  args: 'offset(shape: Shape, distance: number): Shape',
2744
2745
  reason: 'faijs 无同名偏置 → brep-op',
@@ -2755,7 +2756,7 @@ export const ARG_SPEC = [
2755
2756
  reason: 'DraftOptions 含 NeutralPlane 等 face 引用,faijs 面引用体系不同,skip',
2756
2757
  },
2757
2758
  {
2758
- name: 'heal', source: 'topology/api.js#heal', kind: 'brep-op',
2759
+ name: 'heal', source: 'topology/api.js#heal', kind: 'brep-op', capabilities: ["dispose", "healFace", "healSolid", "healWire", "isValid", "shapeType"],
2759
2760
  geometryArgs: [0], returnsResult: true,
2760
2761
  args: 'heal(shape: Shape): Shape',
2761
2762
  reason: 'faijs 无同名整件修复 → brep-op',
@@ -2764,7 +2765,7 @@ export const ARG_SPEC = [
2764
2765
  naming: { kind: 'kernel', newFaces: { via: 'byAdjacency' } },
2765
2766
  },
2766
2767
  {
2767
- name: 'simplify', source: 'topology/api.js#simplify', kind: 'brep-op',
2768
+ name: 'simplify', source: 'topology/api.js#simplify', kind: 'brep-op', capabilities: ["dispose", "simplify"],
2768
2769
  geometryArgs: [0], returnsResult: true,
2769
2770
  args: 'simplify(shape: Shape): Shape',
2770
2771
  reason: 'faijs 无同名整件简化 → brep-op',
@@ -3060,7 +3061,7 @@ export const ARG_SPEC = [
3060
3061
  },
3061
3062
  // healingFns:整件修复 brep-op;face/wire 级修复与 shell 组装 skip
3062
3063
  {
3063
- name: 'autoHeal', source: 'topology/healingFns.js#autoHeal', kind: 'brep-op',
3064
+ name: 'autoHeal', source: 'topology/healingFns.js#autoHeal', kind: 'brep-op', capabilities: ["dispose", "fixSelfIntersection", "healFace", "healSolid", "healWire", "isValid", "iterShapes", "sew", "shapeType"],
3064
3065
  geometryArgs: [0], returnsResult: true,
3065
3066
  args: 'autoHeal(shape: Shape, options?: AutoHealOptions): Shape',
3066
3067
  reason: '整件自动修复(Result<Shape>),brep-op',
@@ -3069,7 +3070,7 @@ export const ARG_SPEC = [
3069
3070
  naming: { kind: 'kernel', newFaces: { via: 'byAdjacency' } },
3070
3071
  },
3071
3072
  {
3072
- name: 'fixShape', source: 'topology/healingFns.js#fixShape', kind: 'brep-op',
3073
+ name: 'fixShape', source: 'topology/healingFns.js#fixShape', kind: 'brep-op', capabilities: ["fixShape"],
3073
3074
  geometryArgs: [0], returnsResult: true,
3074
3075
  args: 'fixShape(shape: Shape): Shape',
3075
3076
  reason: '整件修复(Result<Shape>),brep-op',
@@ -3078,7 +3079,7 @@ export const ARG_SPEC = [
3078
3079
  naming: { kind: 'kernel', newFaces: { via: 'byAdjacency' } },
3079
3080
  },
3080
3081
  {
3081
- name: 'healSolid', source: 'topology/healingFns.js#healSolid', kind: 'brep-op',
3082
+ name: 'healSolid', source: 'topology/healingFns.js#healSolid', kind: 'brep-op', capabilities: ["dispose", "healSolid", "isValid", "shapeType"],
3082
3083
  geometryArgs: [0], returnsResult: true,
3083
3084
  args: 'healSolid(solid: Shape): Shape',
3084
3085
  reason: 'Solid 修复(Result<ValidSolid>),brep-op',
@@ -3087,7 +3088,7 @@ export const ARG_SPEC = [
3087
3088
  naming: { kind: 'kernel', newFaces: { via: 'byAdjacency' } },
3088
3089
  },
3089
3090
  {
3090
- name: 'fixSelfIntersection', source: 'topology/healingFns.js#fixSelfIntersection', kind: 'brep-op',
3091
+ name: 'fixSelfIntersection', source: 'topology/healingFns.js#fixSelfIntersection', kind: 'brep-op', capabilities: ["dispose", "fixSelfIntersection", "shapeType"],
3091
3092
  geometryArgs: [0], returnsResult: true,
3092
3093
  args: 'fixSelfIntersection(shape: Shape): Shape',
3093
3094
  params: ['shape'], formClass: 'A',