@faicad/faijs 0.22.2 → 0.29.3

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 (448) hide show
  1. package/LICENSE +202 -28
  2. package/dist/api/api-namespace.d.ts +5 -5
  3. package/dist/api/api-namespace.d.ts.map +1 -1
  4. package/dist/api/api-namespace.js +4 -4
  5. package/dist/api/api-namespace.js.map +1 -1
  6. package/dist/api/assert.d.ts +2 -2
  7. package/dist/api/assert.js +8 -8
  8. package/dist/api/assert.js.map +1 -1
  9. package/dist/api/asset.d.ts +1 -1
  10. package/dist/api/asset.js +2 -2
  11. package/dist/api/asset.js.map +1 -1
  12. package/dist/api/boolean.d.ts +1 -1
  13. package/dist/api/boolean.d.ts.map +1 -1
  14. package/dist/api/boolean.js +128 -16
  15. package/dist/api/boolean.js.map +1 -1
  16. package/dist/api/cadquery-selectors/borrow-bridge.d.ts +14 -0
  17. package/dist/api/cadquery-selectors/borrow-bridge.d.ts.map +1 -0
  18. package/dist/api/cadquery-selectors/borrow-bridge.js +52 -0
  19. package/dist/api/cadquery-selectors/borrow-bridge.js.map +1 -0
  20. package/dist/api/cadquery-selectors/edge.d.ts +40 -0
  21. package/dist/api/cadquery-selectors/edge.d.ts.map +1 -0
  22. package/dist/api/cadquery-selectors/edge.js +70 -0
  23. package/dist/api/cadquery-selectors/edge.js.map +1 -0
  24. package/dist/api/cadquery-selectors/entity.d.ts +121 -0
  25. package/dist/api/cadquery-selectors/entity.d.ts.map +1 -0
  26. package/dist/api/cadquery-selectors/entity.js +167 -0
  27. package/dist/api/cadquery-selectors/entity.js.map +1 -0
  28. package/dist/api/cadquery-selectors/face.d.ts +33 -0
  29. package/dist/api/cadquery-selectors/face.d.ts.map +1 -0
  30. package/dist/api/cadquery-selectors/face.js +353 -0
  31. package/dist/api/cadquery-selectors/face.js.map +1 -0
  32. package/dist/api/cadquery-selectors/grammar.d.ts +50 -0
  33. package/dist/api/cadquery-selectors/grammar.d.ts.map +1 -0
  34. package/dist/api/cadquery-selectors/grammar.js +345 -0
  35. package/dist/api/cadquery-selectors/grammar.js.map +1 -0
  36. package/dist/api/cadquery-selectors/index.d.ts +18 -0
  37. package/dist/api/cadquery-selectors/index.d.ts.map +1 -0
  38. package/dist/api/cadquery-selectors/index.js +17 -0
  39. package/dist/api/cadquery-selectors/index.js.map +1 -0
  40. package/dist/api/cadquery-selectors/predicates.d.ts +76 -0
  41. package/dist/api/cadquery-selectors/predicates.d.ts.map +1 -0
  42. package/dist/api/cadquery-selectors/predicates.js +85 -0
  43. package/dist/api/cadquery-selectors/predicates.js.map +1 -0
  44. package/dist/api/cadquery-selectors/resolve.d.ts +41 -0
  45. package/dist/api/cadquery-selectors/resolve.d.ts.map +1 -0
  46. package/dist/api/cadquery-selectors/resolve.js +243 -0
  47. package/dist/api/cadquery-selectors/resolve.js.map +1 -0
  48. package/dist/api/cadquery-selectors/types.d.ts +96 -0
  49. package/dist/api/cadquery-selectors/types.d.ts.map +1 -0
  50. package/dist/api/cadquery-selectors/types.js +11 -0
  51. package/dist/api/cadquery-selectors/types.js.map +1 -0
  52. package/dist/api/chamfer.d.ts +13 -5
  53. package/dist/api/chamfer.d.ts.map +1 -1
  54. package/dist/api/chamfer.js +63 -7
  55. package/dist/api/chamfer.js.map +1 -1
  56. package/dist/api/compound-geom.d.ts +1 -1
  57. package/dist/api/compound-geom.js +1 -1
  58. package/dist/api/compound-geom.js.map +1 -1
  59. package/dist/api/draft.d.ts +1 -1
  60. package/dist/api/draft.js +1 -1
  61. package/dist/api/draft.js.map +1 -1
  62. package/dist/api/edge-ref.d.ts +1 -1
  63. package/dist/api/edge-ref.d.ts.map +1 -1
  64. package/dist/api/edge-ref.js +11 -3
  65. package/dist/api/edge-ref.js.map +1 -1
  66. package/dist/api/engrave.d.ts +1 -1
  67. package/dist/api/engrave.js +7 -7
  68. package/dist/api/engrave.js.map +1 -1
  69. package/dist/api/extrude.d.ts +6 -1
  70. package/dist/api/extrude.d.ts.map +1 -1
  71. package/dist/api/extrude.js +59 -5
  72. package/dist/api/extrude.js.map +1 -1
  73. package/dist/api/face-ref.d.ts +1 -1
  74. package/dist/api/face-ref.js +1 -1
  75. package/dist/api/face-ref.js.map +1 -1
  76. package/dist/api/feature-repair.d.ts +1 -1
  77. package/dist/api/feature-repair.js +1 -1
  78. package/dist/api/feature-repair.js.map +1 -1
  79. package/dist/api/fillet-variable.d.ts +1 -1
  80. package/dist/api/fillet-variable.js +1 -1
  81. package/dist/api/fillet-variable.js.map +1 -1
  82. package/dist/api/fillet.d.ts +28 -8
  83. package/dist/api/fillet.d.ts.map +1 -1
  84. package/dist/api/fillet.js +64 -9
  85. package/dist/api/fillet.js.map +1 -1
  86. package/dist/api/geom.d.ts +1 -1
  87. package/dist/api/geom.js +1 -1
  88. package/dist/api/geom.js.map +1 -1
  89. package/dist/api/helix.d.ts +1 -1
  90. package/dist/api/helix.js +1 -1
  91. package/dist/api/helix.js.map +1 -1
  92. package/dist/api/import-brep.d.ts +20 -2
  93. package/dist/api/import-brep.d.ts.map +1 -1
  94. package/dist/api/import-brep.js +28 -3
  95. package/dist/api/import-brep.js.map +1 -1
  96. package/dist/api/import-step.d.ts +17 -2
  97. package/dist/api/import-step.d.ts.map +1 -1
  98. package/dist/api/import-step.js +23 -3
  99. package/dist/api/import-step.js.map +1 -1
  100. package/dist/api/index.d.ts +2 -1
  101. package/dist/api/index.d.ts.map +1 -1
  102. package/dist/api/index.js +5 -2
  103. package/dist/api/index.js.map +1 -1
  104. package/dist/api/internal/compat-op.js +1 -1
  105. package/dist/api/internal/compat-op.js.map +1 -1
  106. package/dist/api/internal/mesh-solid-op.d.ts +236 -0
  107. package/dist/api/internal/mesh-solid-op.d.ts.map +1 -0
  108. package/dist/api/internal/mesh-solid-op.js +352 -0
  109. package/dist/api/internal/mesh-solid-op.js.map +1 -0
  110. package/dist/api/internal/svg-asset-resolver.d.ts +1 -1
  111. package/dist/api/internal/svg-asset-resolver.js +1 -1
  112. package/dist/api/internal/svg-asset-resolver.js.map +1 -1
  113. package/dist/api/knurl.d.ts +1 -1
  114. package/dist/api/knurl.js +2 -2
  115. package/dist/api/knurl.js.map +1 -1
  116. package/dist/api/loft.d.ts +1 -1
  117. package/dist/api/loft.js +1 -1
  118. package/dist/api/loft.js.map +1 -1
  119. package/dist/api/measurement/index.d.ts +9 -5
  120. package/dist/api/measurement/index.d.ts.map +1 -1
  121. package/dist/api/measurement/index.js +47 -20
  122. package/dist/api/measurement/index.js.map +1 -1
  123. package/dist/api/pattern.d.ts +5 -3
  124. package/dist/api/pattern.d.ts.map +1 -1
  125. package/dist/api/pattern.js +32 -4
  126. package/dist/api/pattern.js.map +1 -1
  127. package/dist/api/place.d.ts +1 -1
  128. package/dist/api/place.js +1 -1
  129. package/dist/api/place.js.map +1 -1
  130. package/dist/api/primitives.d.ts +1 -1
  131. package/dist/api/primitives.js +2 -2
  132. package/dist/api/primitives.js.map +1 -1
  133. package/dist/api/profile.d.ts +39 -12
  134. package/dist/api/profile.d.ts.map +1 -1
  135. package/dist/api/profile.js +4 -4
  136. package/dist/api/profile.js.map +1 -1
  137. package/dist/api/reconcile.d.ts +1 -1
  138. package/dist/api/reconcile.js +1 -1
  139. package/dist/api/reconcile.js.map +1 -1
  140. package/dist/api/replicate.d.ts.map +1 -1
  141. package/dist/api/replicate.js +122 -1
  142. package/dist/api/replicate.js.map +1 -1
  143. package/dist/api/screw.d.ts +1 -1
  144. package/dist/api/screw.js +3 -3
  145. package/dist/api/screw.js.map +1 -1
  146. package/dist/api/sdf.d.ts +1 -1
  147. package/dist/api/sdf.js +2 -2
  148. package/dist/api/sdf.js.map +1 -1
  149. package/dist/api/section-by-plane.d.ts +1 -1
  150. package/dist/api/section-by-plane.d.ts.map +1 -1
  151. package/dist/api/section-by-plane.js +2 -1
  152. package/dist/api/section-by-plane.js.map +1 -1
  153. package/dist/api/shell.d.ts +11 -4
  154. package/dist/api/shell.d.ts.map +1 -1
  155. package/dist/api/shell.js +53 -7
  156. package/dist/api/shell.js.map +1 -1
  157. package/dist/api/sketch-on-face.d.ts +41 -0
  158. package/dist/api/sketch-on-face.d.ts.map +1 -1
  159. package/dist/api/sketch-on-face.js +100 -1
  160. package/dist/api/sketch-on-face.js.map +1 -1
  161. package/dist/api/sketch-on-plane.d.ts +7 -5
  162. package/dist/api/sketch-on-plane.d.ts.map +1 -1
  163. package/dist/api/sketch-on-plane.js +6 -7
  164. package/dist/api/sketch-on-plane.js.map +1 -1
  165. package/dist/api/split-by-plane.d.ts +1 -1
  166. package/dist/api/split-by-plane.d.ts.map +1 -1
  167. package/dist/api/split-by-plane.js +2 -1
  168. package/dist/api/split-by-plane.js.map +1 -1
  169. package/dist/api/split.d.ts +1 -1
  170. package/dist/api/split.js +2 -2
  171. package/dist/api/split.js.map +1 -1
  172. package/dist/api/sweep.d.ts +1 -1
  173. package/dist/api/sweep.js +1 -1
  174. package/dist/api/sweep.js.map +1 -1
  175. package/dist/api/thicken.d.ts +1 -1
  176. package/dist/api/thicken.js +1 -1
  177. package/dist/api/thicken.js.map +1 -1
  178. package/dist/api/topo-resolve.d.ts +74 -1
  179. package/dist/api/topo-resolve.d.ts.map +1 -1
  180. package/dist/api/topo-resolve.js +180 -2
  181. package/dist/api/topo-resolve.js.map +1 -1
  182. package/dist/api/transform.d.ts +5 -1
  183. package/dist/api/transform.d.ts.map +1 -1
  184. package/dist/api/transform.js +62 -11
  185. package/dist/api/transform.js.map +1 -1
  186. package/dist/api/wire.d.ts +1 -1
  187. package/dist/api/wire.js +1 -1
  188. package/dist/api/wire.js.map +1 -1
  189. package/dist/brep/brep-ops.d.ts +9 -7
  190. package/dist/brep/brep-ops.d.ts.map +1 -1
  191. package/dist/brep/brep-ops.js +23 -24
  192. package/dist/brep/brep-ops.js.map +1 -1
  193. package/dist/brep/brep-topology.d.ts +5 -4
  194. package/dist/brep/brep-topology.d.ts.map +1 -1
  195. package/dist/brep/brep-topology.js +6 -5
  196. package/dist/brep/brep-topology.js.map +1 -1
  197. package/dist/brep/effective-deflection.d.ts +35 -0
  198. package/dist/brep/effective-deflection.d.ts.map +1 -0
  199. package/dist/brep/effective-deflection.js +49 -0
  200. package/dist/brep/effective-deflection.js.map +1 -0
  201. package/dist/brep/engine/adapters/brep-mock.d.ts.map +1 -1
  202. package/dist/brep/engine/adapters/brep-mock.js +27 -0
  203. package/dist/brep/engine/adapters/brep-mock.js.map +1 -1
  204. package/dist/brep/engine/adapters/brepkit.d.ts +18 -0
  205. package/dist/brep/engine/adapters/brepkit.d.ts.map +1 -1
  206. package/dist/brep/engine/adapters/brepkit.js +46 -1
  207. package/dist/brep/engine/adapters/brepkit.js.map +1 -1
  208. package/dist/brep/engine/adapters/occt.d.ts +1 -1
  209. package/dist/brep/engine/adapters/occt.d.ts.map +1 -1
  210. package/dist/brep/engine/adapters/occt.js +3 -1
  211. package/dist/brep/engine/adapters/occt.js.map +1 -1
  212. package/dist/brep/engine/primitives.d.ts +29 -7
  213. package/dist/brep/engine/primitives.d.ts.map +1 -1
  214. package/dist/brep/engine/primitives.js.map +1 -1
  215. package/dist/brep/engine/registry.d.ts +24 -1
  216. package/dist/brep/engine/registry.d.ts.map +1 -1
  217. package/dist/brep/engine/registry.js +24 -0
  218. package/dist/brep/engine/registry.js.map +1 -1
  219. package/dist/brep/engine/types.d.ts +54 -3
  220. package/dist/brep/engine/types.d.ts.map +1 -1
  221. package/dist/brep/engine/types.js +10 -0
  222. package/dist/brep/engine/types.js.map +1 -1
  223. package/dist/brep/export/export-model.d.ts.map +1 -1
  224. package/dist/brep/export/export-model.js +6 -5
  225. package/dist/brep/export/export-model.js.map +1 -1
  226. package/dist/brep/face-evolution.d.ts +1 -1
  227. package/dist/brep/face-evolution.d.ts.map +1 -1
  228. package/dist/brep/face-evolution.js +20 -1
  229. package/dist/brep/face-evolution.js.map +1 -1
  230. package/dist/brep/handle-bridge.d.ts +1 -1
  231. package/dist/brep/handle-bridge.js +1 -1
  232. package/dist/brep/handle-bridge.js.map +1 -1
  233. package/dist/brep/mesh-solid.d.ts +218 -0
  234. package/dist/brep/mesh-solid.d.ts.map +1 -0
  235. package/dist/brep/mesh-solid.js +229 -0
  236. package/dist/brep/mesh-solid.js.map +1 -0
  237. package/dist/brep/text/fontRegistry.d.ts +32 -1
  238. package/dist/brep/text/fontRegistry.d.ts.map +1 -1
  239. package/dist/brep/text/fontRegistry.js +51 -1
  240. package/dist/brep/text/fontRegistry.js.map +1 -1
  241. package/dist/brep/text/text-to-solid.d.ts.map +1 -1
  242. package/dist/brep/text/text-to-solid.js +8 -3
  243. package/dist/brep/text/text-to-solid.js.map +1 -1
  244. package/dist/brepkit-kernel/brepkitKernel.d.ts +18 -2
  245. package/dist/brepkit-kernel/brepkitKernel.d.ts.map +1 -1
  246. package/dist/brepkit-kernel/brepkitKernel.js +449 -123
  247. package/dist/brepkit-kernel/brepkitKernel.js.map +1 -1
  248. package/dist/brepkit-kernel/brepkitWasm.d.ts +8 -0
  249. package/dist/brepkit-kernel/brepkitWasm.d.ts.map +1 -1
  250. package/dist/brepkit-kernel/brepkitWasm.js +10 -0
  251. package/dist/brepkit-kernel/brepkitWasm.js.map +1 -1
  252. package/dist/browser-host/browser-font-provider.d.ts +12 -0
  253. package/dist/browser-host/browser-font-provider.d.ts.map +1 -1
  254. package/dist/browser-host/browser-font-provider.js +25 -0
  255. package/dist/browser-host/browser-font-provider.js.map +1 -1
  256. package/dist/browser.d.ts +6 -3
  257. package/dist/browser.d.ts.map +1 -1
  258. package/dist/browser.js +10 -3
  259. package/dist/browser.js.map +1 -1
  260. package/dist/cad-runtime/backend-dispatch.d.ts +28 -3
  261. package/dist/cad-runtime/backend-dispatch.d.ts.map +1 -1
  262. package/dist/cad-runtime/backend-dispatch.js +119 -4
  263. package/dist/cad-runtime/backend-dispatch.js.map +1 -1
  264. package/dist/cad-runtime/browser-lib-loader.js.map +1 -1
  265. package/dist/cad-runtime/direct-executor.d.ts +15 -3
  266. package/dist/cad-runtime/direct-executor.d.ts.map +1 -1
  267. package/dist/cad-runtime/direct-executor.js +33 -1
  268. package/dist/cad-runtime/direct-executor.js.map +1 -1
  269. package/dist/cad-runtime/ports.d.ts +3 -3
  270. package/dist/cad-runtime/ports.d.ts.map +1 -1
  271. package/dist/cad-runtime/ports.js.map +1 -1
  272. package/dist/cad-runtime/preview-exec.d.ts +4 -4
  273. package/dist/cad-runtime/preview-exec.js +2 -2
  274. package/dist/cad-runtime/preview-exec.js.map +1 -1
  275. package/dist/cad-runtime/runtime.d.ts +42 -7
  276. package/dist/cad-runtime/runtime.d.ts.map +1 -1
  277. package/dist/cad-runtime/runtime.js +68 -5
  278. package/dist/cad-runtime/runtime.js.map +1 -1
  279. package/dist/define-op.d.ts +15 -1
  280. package/dist/define-op.d.ts.map +1 -1
  281. package/dist/define-op.js +10 -1
  282. package/dist/define-op.js.map +1 -1
  283. package/dist/env-agnostic.d.ts +2 -2
  284. package/dist/env-agnostic.d.ts.map +1 -1
  285. package/dist/env-agnostic.js +1 -1
  286. package/dist/env-agnostic.js.map +1 -1
  287. package/dist/geometry2d/adapt.d.ts +39 -4
  288. package/dist/geometry2d/adapt.d.ts.map +1 -1
  289. package/dist/geometry2d/adapt.js +14 -3
  290. package/dist/geometry2d/adapt.js.map +1 -1
  291. package/dist/geometry2d/blueprint.d.ts +2 -2
  292. package/dist/geometry2d/blueprint.js +2 -2
  293. package/dist/geometry2d/blueprint.js.map +1 -1
  294. package/dist/geometry2d/bridge/lift-on-plane.d.ts +18 -8
  295. package/dist/geometry2d/bridge/lift-on-plane.d.ts.map +1 -1
  296. package/dist/geometry2d/bridge/lift-on-plane.js +65 -12
  297. package/dist/geometry2d/bridge/lift-on-plane.js.map +1 -1
  298. package/dist/geometry2d/bridge/plane.d.ts +17 -0
  299. package/dist/geometry2d/bridge/plane.d.ts.map +1 -1
  300. package/dist/geometry2d/bridge/plane.js +22 -0
  301. package/dist/geometry2d/bridge/plane.js.map +1 -1
  302. package/dist/geometry2d/curve2d.d.ts +25 -0
  303. package/dist/geometry2d/curve2d.d.ts.map +1 -1
  304. package/dist/geometry2d/curve2d.js +41 -5
  305. package/dist/geometry2d/curve2d.js.map +1 -1
  306. package/dist/index.d.ts +6 -2
  307. package/dist/index.d.ts.map +1 -1
  308. package/dist/index.js +10 -3
  309. package/dist/index.js.map +1 -1
  310. package/dist/io/bytes-node.d.ts +11 -0
  311. package/dist/io/bytes-node.d.ts.map +1 -0
  312. package/dist/io/bytes-node.js +28 -0
  313. package/dist/io/bytes-node.js.map +1 -0
  314. package/dist/io/bytes.d.ts +33 -0
  315. package/dist/io/bytes.d.ts.map +1 -0
  316. package/dist/io/bytes.js +41 -0
  317. package/dist/io/bytes.js.map +1 -0
  318. package/dist/io/fai-zip/container-read.d.ts +102 -0
  319. package/dist/io/fai-zip/container-read.d.ts.map +1 -0
  320. package/dist/io/fai-zip/container-read.js +305 -0
  321. package/dist/io/fai-zip/container-read.js.map +1 -0
  322. package/dist/io/fai-zip/container-write.d.ts +70 -0
  323. package/dist/io/fai-zip/container-write.d.ts.map +1 -0
  324. package/dist/io/fai-zip/container-write.js +186 -0
  325. package/dist/io/fai-zip/container-write.js.map +1 -0
  326. package/dist/io/fai-zip/container.d.ts +107 -0
  327. package/dist/io/fai-zip/container.d.ts.map +1 -0
  328. package/dist/io/fai-zip/container.js +89 -0
  329. package/dist/io/fai-zip/container.js.map +1 -0
  330. package/dist/io/fai-zip/index.d.ts +18 -0
  331. package/dist/io/fai-zip/index.d.ts.map +1 -0
  332. package/dist/io/fai-zip/index.js +4 -0
  333. package/dist/io/fai-zip/index.js.map +1 -0
  334. package/dist/io/index.d.ts +10 -0
  335. package/dist/io/index.d.ts.map +1 -0
  336. package/dist/io/index.js +13 -0
  337. package/dist/io/index.js.map +1 -0
  338. package/dist/io/zip.d.ts +68 -0
  339. package/dist/io/zip.d.ts.map +1 -0
  340. package/dist/io/zip.js +147 -0
  341. package/dist/io/zip.js.map +1 -0
  342. package/dist/lang/code-to-args.d.ts +1 -1
  343. package/dist/lang/code-to-args.js +1 -1
  344. package/dist/lang/code-to-args.js.map +1 -1
  345. package/dist/lang/statement-summary.d.ts +1 -1
  346. package/dist/lang/statement-summary.js +1 -1
  347. package/dist/lang/statement-summary.js.map +1 -1
  348. package/dist/lang/types.d.ts +1 -1
  349. package/dist/lang/types.js +1 -1
  350. package/dist/lang/types.js.map +1 -1
  351. package/dist/mesh/index.d.ts +2 -1
  352. package/dist/mesh/index.d.ts.map +1 -1
  353. package/dist/mesh/index.js +2 -1
  354. package/dist/mesh/index.js.map +1 -1
  355. package/dist/mesh/io.d.ts +7 -0
  356. package/dist/mesh/io.d.ts.map +1 -1
  357. package/dist/mesh/io.js +14 -17
  358. package/dist/mesh/io.js.map +1 -1
  359. package/dist/mesh/reconcile.d.ts +1 -1
  360. package/dist/mesh/reconcile.js +1 -1
  361. package/dist/mesh/reconcile.js.map +1 -1
  362. package/dist/mesh/rigid-transform.d.ts +3 -3
  363. package/dist/mesh/rigid-transform.js +3 -3
  364. package/dist/mesh/rigid-transform.js.map +1 -1
  365. package/dist/mesh/stl-unit.d.ts +24 -0
  366. package/dist/mesh/stl-unit.d.ts.map +1 -0
  367. package/dist/mesh/stl-unit.js +17 -0
  368. package/dist/mesh/stl-unit.js.map +1 -0
  369. package/dist/mesh/threemf-bambu.d.ts +142 -0
  370. package/dist/mesh/threemf-bambu.d.ts.map +1 -0
  371. package/dist/mesh/threemf-bambu.js +334 -0
  372. package/dist/mesh/threemf-bambu.js.map +1 -0
  373. package/dist/mesh/threemf-loader.d.ts +42 -7
  374. package/dist/mesh/threemf-loader.d.ts.map +1 -1
  375. package/dist/mesh/threemf-loader.js +565 -100
  376. package/dist/mesh/threemf-loader.js.map +1 -1
  377. package/dist/mesh/threemf-view.d.ts +71 -0
  378. package/dist/mesh/threemf-view.d.ts.map +1 -0
  379. package/dist/mesh/threemf-view.js +100 -0
  380. package/dist/mesh/threemf-view.js.map +1 -0
  381. package/dist/node-host/cli.d.ts +44 -6
  382. package/dist/node-host/cli.d.ts.map +1 -1
  383. package/dist/node-host/cli.js +76 -26
  384. package/dist/node-host/cli.js.map +1 -1
  385. package/dist/node-host/font-family-index.d.ts +93 -0
  386. package/dist/node-host/font-family-index.d.ts.map +1 -0
  387. package/dist/node-host/font-family-index.js +273 -0
  388. package/dist/node-host/font-family-index.js.map +1 -0
  389. package/dist/node-host/fs-asset-resolver.d.ts +8 -3
  390. package/dist/node-host/fs-asset-resolver.d.ts.map +1 -1
  391. package/dist/node-host/fs-asset-resolver.js +13 -5
  392. package/dist/node-host/fs-asset-resolver.js.map +1 -1
  393. package/dist/node-host/index.d.ts +8 -0
  394. package/dist/node-host/index.d.ts.map +1 -1
  395. package/dist/node-host/index.js +1 -0
  396. package/dist/node-host/index.js.map +1 -1
  397. package/dist/node-host/node-font-provider.d.ts +28 -0
  398. package/dist/node-host/node-font-provider.d.ts.map +1 -1
  399. package/dist/node-host/node-font-provider.js +49 -0
  400. package/dist/node-host/node-font-provider.js.map +1 -1
  401. package/dist/node.d.ts +1 -0
  402. package/dist/node.d.ts.map +1 -1
  403. package/dist/node.js +1 -0
  404. package/dist/node.js.map +1 -1
  405. package/dist/occt-kernel/occt-primitives.d.ts.map +1 -1
  406. package/dist/occt-kernel/occt-primitives.js +35 -2
  407. package/dist/occt-kernel/occt-primitives.js.map +1 -1
  408. package/dist/occt-kernel/occtKernel.d.ts +18 -13
  409. package/dist/occt-kernel/occtKernel.d.ts.map +1 -1
  410. package/dist/occt-kernel/occtKernel.js +18 -31
  411. package/dist/occt-kernel/occtKernel.js.map +1 -1
  412. package/dist/occt-kernel/stepColorParser.d.ts +18 -0
  413. package/dist/occt-kernel/stepColorParser.d.ts.map +1 -1
  414. package/dist/occt-kernel/stepColorParser.js +38 -0
  415. package/dist/occt-kernel/stepColorParser.js.map +1 -1
  416. package/dist/occt-kernel/topologyExt.d.ts +1 -1
  417. package/dist/occt-kernel/topologyExt.d.ts.map +1 -1
  418. package/dist/occt-kernel/topologyExt.js +4 -5
  419. package/dist/occt-kernel/topologyExt.js.map +1 -1
  420. package/dist/primitives/text/cjk-font.d.ts +2 -15
  421. package/dist/primitives/text/cjk-font.d.ts.map +1 -1
  422. package/dist/primitives/text/cjk-font.js +13 -1
  423. package/dist/primitives/text/cjk-font.js.map +1 -1
  424. package/dist/runtime-state.d.ts +85 -9
  425. package/dist/runtime-state.d.ts.map +1 -1
  426. package/dist/runtime-state.js +72 -2
  427. package/dist/runtime-state.js.map +1 -1
  428. package/dist/sdk.d.ts +3 -3
  429. package/dist/sdk.d.ts.map +1 -1
  430. package/dist/sdk.js +5 -5
  431. package/dist/sdk.js.map +1 -1
  432. package/dist/shape.d.ts +97 -2
  433. package/dist/shape.d.ts.map +1 -1
  434. package/dist/shape.js +126 -1
  435. package/dist/shape.js.map +1 -1
  436. package/dist/topology/naming/lineage.d.ts +6 -0
  437. package/dist/topology/naming/lineage.d.ts.map +1 -1
  438. package/dist/topology/naming/lineage.js +8 -0
  439. package/dist/topology/naming/lineage.js.map +1 -1
  440. package/dist/topology/naming/resolve-edge.d.ts +20 -1
  441. package/dist/topology/naming/resolve-edge.d.ts.map +1 -1
  442. package/dist/topology/naming/resolve-edge.js +54 -20
  443. package/dist/topology/naming/resolve-edge.js.map +1 -1
  444. package/dist/weapp.d.ts +6 -2
  445. package/dist/weapp.d.ts.map +1 -1
  446. package/dist/weapp.js +7 -1
  447. package/dist/weapp.js.map +1 -1
  448. package/package.json +18 -2
package/dist/shape.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * stdlib shape — 类型化构造器 + 身份槽
2
+ * api shape — 类型化构造器 + 身份槽
3
3
  *
4
4
  *
5
5
  * 变更要点:
@@ -32,7 +32,7 @@ export interface CompoundShape {
32
32
  export interface CurveShape extends Shape {
33
33
  kind: 'curve';
34
34
  }
35
- /** A shape that the stdlib exports as a finished result. */
35
+ /** A shape that the api layer exports as a finished result. */
36
36
  export type StdShape = SolidShape | CompoundShape | CurveShape;
37
37
  /**
38
38
  * 实体 Shape 构造器:mesh 产物必须经此创建。
@@ -77,6 +77,101 @@ export declare function fromBrep(mesh: Shape, holder: BrepHolder): SolidShape;
77
77
  * @returns the created curve shape with the BREP handle attached.
78
78
  */
79
79
  export declare function fromBrepCurve(mesh: Shape, holder: BrepHolder): CurveShape;
80
+ /**
81
+ * 网格实体产物的构造器:与 `fromBrep` 对称,登记网格实体句柄(近似链)而非
82
+ * BREP 句柄(精度链)。
83
+ *
84
+ * ```ts
85
+ * return fromMeshSolid(displayMesh, { meshSolid: result.solid })
86
+ * ```
87
+ *
88
+ * 与 `fromBrep` 的三点差别(方案 §3.2):
89
+ * 1. 写 `slot.meshSolid`,**不写** `slot.solid`——网格零件永不进 BREP 链;
90
+ * 2. 不登记函数 BREP 域(`registerFunctionBrep`)——句柄所有权在
91
+ * `MeshSolidRegistry`,按 BREP 内核释放是错的(可能是另一个内核);
92
+ * 3. 不旁挂 roleTable(近似拓扑不给语义 role——role 是 BREP 真拓扑的专有能力)。
93
+ *
94
+ * @param mesh - the mesh shape to wrap as a solid (display mesh).
95
+ * @param holder - the mesh-solid holder providing the handle identity.
96
+ * @returns the created solid shape carrying the mesh-solid slot.
97
+ */
98
+ export declare function fromMeshSolid(mesh: Shape, holder: MeshSolidHolder): SolidShape;
99
+ /** 网格实体句柄容器(与 `BrepHolder` 对称;类型为 unknown 以保持零依赖)。 */
100
+ export interface MeshSolidHolder {
101
+ /** 网格实体句柄的**身份**(句柄本体在 `MeshSolidRegistry`)。 */
102
+ meshSolid: unknown;
103
+ }
104
+ /**
105
+ * 网格链**面**产物的构造器(方案 2026-10-01 §4 Phase 3)。与 `fromBrep` 的
106
+ * 面产物对称:BREP 侧 `sketchOnFace` 返回 `fromBrep(solidToShape(kernel, face),
107
+ * { solid: face })`,这里返回 `fromMeshFace(meshShape(face), { meshFace: face })`。
108
+ *
109
+ * `kind` 沿用 `'solid'`(不是 `'shape2d'`):与 BREP 侧的面 Shape 保持同一形态,
110
+ * 好让 `extrude` 的 `isCurveShape` 预检在两条链上行为一致——面不是 1D 曲线,
111
+ * 不该被面消费 op 当成曲线拒掉。
112
+ *
113
+ * @param mesh - the face's display mesh (its own tessellation).
114
+ * @param holder - the mesh-face holder providing the handle identity.
115
+ * @returns the created shape carrying the mesh-face slot.
116
+ */
117
+ export declare function fromMeshFace(mesh: Shape, holder: MeshFaceHolder): SolidShape;
118
+ /** 网格链面句柄容器(与 `MeshSolidHolder` 对称;类型为 unknown 以保持零依赖)。 */
119
+ export interface MeshFaceHolder {
120
+ /** 网格链面句柄的**身份**。 */
121
+ meshFace: unknown;
122
+ }
123
+ /**
124
+ * 把网格实体句柄登记到已构造的 Shape。
125
+ *
126
+ * 互斥红线:该 Shape 已有 BREP 句柄或网格链面句柄时**直接抛错**——一个 Shape
127
+ * 同时声称两种链身份是设计缺陷,不能静默覆盖任何一侧。
128
+ *
129
+ * @param s - the already-constructed shape.
130
+ * @param meshSolid - the mesh solid handle.
131
+ * @throws {Error} `E_SHAPE_SLOT_EXCLUSIVE` when the shape already carries another chain identity.
132
+ */
133
+ export declare function attachMeshSolid(s: Shape, meshSolid: unknown): void;
134
+ /**
135
+ * 把网格链**面**句柄登记到已构造的 Shape。
136
+ *
137
+ * 与 `attachMeshSolid` 同一条互斥红线:已有任意另一种链身份即抛错。
138
+ *
139
+ * @param s - the already-constructed shape.
140
+ * @param meshFace - the mesh-chain face handle.
141
+ * @throws {Error} `E_SHAPE_SLOT_EXCLUSIVE` when the shape already carries another chain identity.
142
+ */
143
+ export declare function attachMeshFace(s: Shape, meshFace: unknown): void;
144
+ /**
145
+ * 该 Shape 是否携带网格链面(`sketchOnFace` 在近似拓扑面上的产物)。
146
+ *
147
+ * @param shape - the shape to test.
148
+ * @returns true if the shape carries a mesh-chain face handle.
149
+ */
150
+ export declare function hasMeshFace(shape: Shape): boolean;
151
+ /**
152
+ * 读取该 Shape 的网格链面句柄(无则 undefined)。
153
+ *
154
+ * @param shape - the shape whose mesh-chain face handle to read.
155
+ * @returns the mesh-chain face handle, or undefined if none.
156
+ */
157
+ export declare function meshFaceOf(shape: Shape): unknown | undefined;
158
+ /**
159
+ * 该 Shape 是否携带网格实体(网格零件)。引擎分派与 UI 查询用。
160
+ *
161
+ * 与 `hasBrep` 互斥:正常路径下二者不可能同时为真(`attachMeshSolid` 已经把
162
+ * 互斥钉在写入侧,`assertShapeSlotExclusive` 在分派前再兜一层)。
163
+ *
164
+ * @param shape - the shape to test.
165
+ * @returns true if the shape carries a mesh solid handle.
166
+ */
167
+ export declare function hasMeshSolid(shape: Shape): boolean;
168
+ /**
169
+ * 读取该 Shape 的网格实体句柄(无则 undefined)。
170
+ *
171
+ * @param shape - the shape whose mesh solid handle to read.
172
+ * @returns the mesh solid handle, or undefined if none.
173
+ */
174
+ export declare function meshSolidOf(shape: Shape): unknown | undefined;
80
175
  /** BREP 句柄 + 面演化 + 拓扑命名 RoleTable(对应 OCCT 的 ShapeHandle)。类型为 unknown 以保持零依赖。 */
81
176
  export interface BrepHolder {
82
177
  solid: unknown;
@@ -1 +1 @@
1
- {"version":3,"file":"shape.d.ts","sourceRoot":"","sources":["../src/shape.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,cAAc,CAAA;AACzC,OAAO,EAAiE,KAAK,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAM/G,kDAAkD;AAClD,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,OAAO,GAAG,UAAU,CAAA;AAElE,oDAAoD;AACpD,MAAM,WAAW,UAAW,SAAQ,KAAK;IACvC,IAAI,EAAE,OAAO,CAAA;CACd;AAED,6DAA6D;AAC7D,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,UAAU,CAAA;IAChB,QAAQ,EAAE,KAAK,EAAE,CAAA;CAClB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,UAAW,SAAQ,KAAK;IACvC,IAAI,EAAE,OAAO,CAAA;CACd;AAED,4DAA4D;AAC5D,MAAM,MAAM,QAAQ,GAAG,UAAU,GAAG,aAAa,GAAG,UAAU,CAAA;AAE9D;;;;;GAKG;AACH,wBAAgB,KAAK,CAAC,IAAI,EAAE,KAAK,GAAG,UAAU,CAI7C;AAED;;;;;;;;GAQG;AACH,wBAAgB,KAAK,CAAC,IAAI,EAAE,KAAK,GAAG,UAAU,CAI7C;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,GAAG,UAAU,CAIpE;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,GAAG,UAAU,CAIzE;AAoCD,gFAAgF;AAChF,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,OAAO,CAAA;IACd,aAAa,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAA;IACrC;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,KAAK,EAAE,GAAG,aAAa,CAIzD;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,KAAK,CAE9C;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,aAAa,CAEzD;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,aAAa,CAI7D;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,UAAU,CAExD;AAID,YAAY,EAAE,SAAS,EAAE,CAAA;AAEzB;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAE5D;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAQnD;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAGjE;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAE7C;AAED;;;;;GAKG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,GAAG,SAAS,CAExD;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,EAAE,CAEtD"}
1
+ {"version":3,"file":"shape.d.ts","sourceRoot":"","sources":["../src/shape.ts"],"names":[],"mappings":"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"}
package/dist/shape.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * stdlib shape — 类型化构造器 + 身份槽
2
+ * api shape — 类型化构造器 + 身份槽
3
3
  *
4
4
  *
5
5
  * 变更要点:
@@ -71,6 +71,126 @@ export function fromBrepCurve(mesh, holder) {
71
71
  attachBrep(s, holder);
72
72
  return s;
73
73
  }
74
+ /**
75
+ * 网格实体产物的构造器:与 `fromBrep` 对称,登记网格实体句柄(近似链)而非
76
+ * BREP 句柄(精度链)。
77
+ *
78
+ * ```ts
79
+ * return fromMeshSolid(displayMesh, { meshSolid: result.solid })
80
+ * ```
81
+ *
82
+ * 与 `fromBrep` 的三点差别(方案 §3.2):
83
+ * 1. 写 `slot.meshSolid`,**不写** `slot.solid`——网格零件永不进 BREP 链;
84
+ * 2. 不登记函数 BREP 域(`registerFunctionBrep`)——句柄所有权在
85
+ * `MeshSolidRegistry`,按 BREP 内核释放是错的(可能是另一个内核);
86
+ * 3. 不旁挂 roleTable(近似拓扑不给语义 role——role 是 BREP 真拓扑的专有能力)。
87
+ *
88
+ * @param mesh - the mesh shape to wrap as a solid (display mesh).
89
+ * @param holder - the mesh-solid holder providing the handle identity.
90
+ * @returns the created solid shape carrying the mesh-solid slot.
91
+ */
92
+ export function fromMeshSolid(mesh, holder) {
93
+ const s = solid(mesh);
94
+ attachMeshSolid(s, holder.meshSolid);
95
+ return s;
96
+ }
97
+ /**
98
+ * 网格链**面**产物的构造器(方案 2026-10-01 §4 Phase 3)。与 `fromBrep` 的
99
+ * 面产物对称:BREP 侧 `sketchOnFace` 返回 `fromBrep(solidToShape(kernel, face),
100
+ * { solid: face })`,这里返回 `fromMeshFace(meshShape(face), { meshFace: face })`。
101
+ *
102
+ * `kind` 沿用 `'solid'`(不是 `'shape2d'`):与 BREP 侧的面 Shape 保持同一形态,
103
+ * 好让 `extrude` 的 `isCurveShape` 预检在两条链上行为一致——面不是 1D 曲线,
104
+ * 不该被面消费 op 当成曲线拒掉。
105
+ *
106
+ * @param mesh - the face's display mesh (its own tessellation).
107
+ * @param holder - the mesh-face holder providing the handle identity.
108
+ * @returns the created shape carrying the mesh-face slot.
109
+ */
110
+ export function fromMeshFace(mesh, holder) {
111
+ const s = solid(mesh);
112
+ attachMeshFace(s, holder.meshFace);
113
+ return s;
114
+ }
115
+ /**
116
+ * 把网格实体句柄登记到已构造的 Shape。
117
+ *
118
+ * 互斥红线:该 Shape 已有 BREP 句柄或网格链面句柄时**直接抛错**——一个 Shape
119
+ * 同时声称两种链身份是设计缺陷,不能静默覆盖任何一侧。
120
+ *
121
+ * @param s - the already-constructed shape.
122
+ * @param meshSolid - the mesh solid handle.
123
+ * @throws {Error} `E_SHAPE_SLOT_EXCLUSIVE` when the shape already carries another chain identity.
124
+ */
125
+ export function attachMeshSolid(s, meshSolid) {
126
+ const state = getRuntimeState();
127
+ const slot = state.slots.get(s) ?? {};
128
+ if (slot.solid !== undefined) {
129
+ throw new Error('E_SHAPE_SLOT_EXCLUSIVE: shape already carries a BREP handle — a shape is either on the precision chain or the mesh chain, never both');
130
+ }
131
+ if (slot.meshFace !== undefined) {
132
+ throw new Error('E_SHAPE_SLOT_EXCLUSIVE: shape already carries a mesh-chain face handle — a shape is either a mesh solid or a mesh-chain face, never both');
133
+ }
134
+ slot.meshSolid = meshSolid;
135
+ state.slots.set(s, slot);
136
+ }
137
+ /**
138
+ * 把网格链**面**句柄登记到已构造的 Shape。
139
+ *
140
+ * 与 `attachMeshSolid` 同一条互斥红线:已有任意另一种链身份即抛错。
141
+ *
142
+ * @param s - the already-constructed shape.
143
+ * @param meshFace - the mesh-chain face handle.
144
+ * @throws {Error} `E_SHAPE_SLOT_EXCLUSIVE` when the shape already carries another chain identity.
145
+ */
146
+ export function attachMeshFace(s, meshFace) {
147
+ const state = getRuntimeState();
148
+ const slot = state.slots.get(s) ?? {};
149
+ if (slot.solid !== undefined || slot.meshSolid !== undefined) {
150
+ throw new Error('E_SHAPE_SLOT_EXCLUSIVE: shape already carries a BREP or mesh-solid handle — a mesh-chain face is its own identity');
151
+ }
152
+ slot.meshFace = meshFace;
153
+ state.slots.set(s, slot);
154
+ }
155
+ /**
156
+ * 该 Shape 是否携带网格链面(`sketchOnFace` 在近似拓扑面上的产物)。
157
+ *
158
+ * @param shape - the shape to test.
159
+ * @returns true if the shape carries a mesh-chain face handle.
160
+ */
161
+ export function hasMeshFace(shape) {
162
+ return getRuntimeState().slots.get(shape)?.meshFace !== undefined;
163
+ }
164
+ /**
165
+ * 读取该 Shape 的网格链面句柄(无则 undefined)。
166
+ *
167
+ * @param shape - the shape whose mesh-chain face handle to read.
168
+ * @returns the mesh-chain face handle, or undefined if none.
169
+ */
170
+ export function meshFaceOf(shape) {
171
+ return getRuntimeState().slots.get(shape)?.meshFace;
172
+ }
173
+ /**
174
+ * 该 Shape 是否携带网格实体(网格零件)。引擎分派与 UI 查询用。
175
+ *
176
+ * 与 `hasBrep` 互斥:正常路径下二者不可能同时为真(`attachMeshSolid` 已经把
177
+ * 互斥钉在写入侧,`assertShapeSlotExclusive` 在分派前再兜一层)。
178
+ *
179
+ * @param shape - the shape to test.
180
+ * @returns true if the shape carries a mesh solid handle.
181
+ */
182
+ export function hasMeshSolid(shape) {
183
+ return getRuntimeState().slots.get(shape)?.meshSolid !== undefined;
184
+ }
185
+ /**
186
+ * 读取该 Shape 的网格实体句柄(无则 undefined)。
187
+ *
188
+ * @param shape - the shape whose mesh solid handle to read.
189
+ * @returns the mesh solid handle, or undefined if none.
190
+ */
191
+ export function meshSolidOf(shape) {
192
+ return getRuntimeState().slots.get(shape)?.meshSolid;
193
+ }
74
194
  /**
75
195
  * 把 BREP 句柄登记到已构造的 Shape(由 `solid` / `curve` 产出)。
76
196
  *
@@ -85,6 +205,11 @@ export function fromBrepCurve(mesh, holder) {
85
205
  function attachBrep(s, holder) {
86
206
  const state = getRuntimeState();
87
207
  const slot = state.slots.get(s) ?? {};
208
+ if (slot.meshSolid !== undefined || slot.meshFace !== undefined) {
209
+ // 互斥红线的另一侧:网格链产物不得再被登记成 BREP 实体(一个 Shape 只能
210
+ // 在精度链或网格链之一上)。
211
+ throw new Error('E_SHAPE_SLOT_EXCLUSIVE: shape already carries a mesh-chain handle — a shape is either on the precision chain or the mesh chain, never both');
212
+ }
88
213
  slot.solid = holder.solid;
89
214
  if (holder.faceEvolution)
90
215
  slot.faceEvolution = holder.faceEvolution;
package/dist/shape.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"shape.js","sourceRoot":"","sources":["../src/shape.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * stdlib shape — 类型化构造器 + 身份槽\n *\n *\n * 变更要点:\n * - 身份表(created / slots / shapeToName)改读全局锚点 runtime-state,\n * 使\"两份 faijs 代码\"共享同一份状态(解决 Shape 身份孤岛)。\n * - 新增 fromBrep(mesh, holder):BREP 产物一次登记句柄与面演化,\n * 库函数不再手动登记(P2 落地)。\n * - 新增 hasBrep / brepOf:引擎侧判定\"某 Shape 是否在 BREP 链上\"。\n */\n\nimport type { Shape } from './mesh/types'\nimport { getRuntimeState, registerFunctionBrep, nameOf, getCurrentStmt, type ShapeSlot } from './runtime-state'\nimport { asStmtId } from './identity'\nimport { runtimeLineage } from './topology/naming/lineage'\n\n// ── Shape 构造器 ──\n\n/** Discriminator for the concrete shape kinds. */\nexport type ShapeKind = 'solid' | 'shape2d' | 'curve' | 'compound'\n\n/** A solid mesh shape produced by a constructor. */\nexport interface SolidShape extends Shape {\n kind: 'solid'\n}\n\n/** A structural compound grouping a list of child shapes. */\nexport interface CompoundShape {\n kind: 'compound'\n children: Shape[]\n}\n\n/**\n * 1D 曲线 Shape(wire / helix / edge-loop 等无三角载荷的 1D 几何)。\n *\n * `kind: 'curve'` 表达「无三角载荷」,与 `'solid'` 对称(见 `curve()` /\n * `fromBrepCurve()`)。执行链路照走 `solidToShape`(wire → 空 0/0 载荷,不抛),\n * 显示经 `wireframe`。\n */\nexport interface CurveShape extends Shape {\n kind: 'curve'\n}\n\n/** A shape that the stdlib exports as a finished result. */\nexport type StdShape = SolidShape | CompoundShape | CurveShape\n\n/**\n * 实体 Shape 构造器:mesh 产物必须经此创建。\n *\n * @param mesh - the mesh shape to wrap as a solid.\n * @returns the created solid shape.\n */\nexport function solid(mesh: Shape): SolidShape {\n const s: SolidShape = { ...mesh, kind: 'solid' }\n getRuntimeState().created.add(s)\n return s\n}\n\n/**\n * 1D 曲线 Shape 构造器(wire / helix / edge-loop 等 1D 产物)。\n *\n * 与 `solid` 对称:登记到 identity 表(供 `isShape` 识别),`kind` 设为 `'curve'`\n * 以表达「无三角载荷的 1D 几何」(执行链路照走 `solidToShape`,显示经 `wireframe`)。\n *\n * @param mesh - the mesh payload (positions/indices) to wrap as a curve.\n * @returns the created curve shape.\n */\nexport function curve(mesh: Shape): CurveShape {\n const s: CurveShape = { ...mesh, kind: 'curve' }\n getRuntimeState().created.add(s)\n return s\n}\n\n/**\n * BREP 产物构造器:同时登记 mesh 与 OCCT 句柄(+ 可选面演化)。\n *\n * 库函数用它替代 `solid(mesh)` + 手动登记句柄两步行:\n * ```ts\n * return fromBrep(solidToShape(kernel, resultSolid), {\n * solid: resultSolid,\n * faceEvolution: identityEvolution(kernel, resultSolid),\n * })\n * ```\n *\n * @param mesh - the mesh shape to register.\n * @param holder - the BREP holder providing the OCCT handle and optional face evolution.\n * @returns the created solid shape with the BREP handle attached.\n */\nexport function fromBrep(mesh: Shape, holder: BrepHolder): SolidShape {\n const s = solid(mesh)\n attachBrep(s, holder)\n return s\n}\n\n/**\n * 1D 曲线产物的 BREP 登记构造器:与 `fromBrep` 对称,但 `kind` 取 `'curve'`\n * (维持既有「有无三角载荷」语义——1D 几何无三角载荷,不得报 `'solid'`)。\n * 登记逻辑与 `fromBrep` 共用 `attachBrep`,保证两种形态走同一份身份/血缘/释放语义。\n *\n * @param mesh - the mesh payload (positions/indices) to wrap as a curve.\n * @param holder - the BREP holder providing the OCCT handle and optional face evolution.\n * @returns the created curve shape with the BREP handle attached.\n */\nexport function fromBrepCurve(mesh: Shape, holder: BrepHolder): CurveShape {\n const s = curve(mesh)\n attachBrep(s, holder)\n return s\n}\n\n/**\n * 把 BREP 句柄登记到已构造的 Shape(由 `solid` / `curve` 产出)。\n *\n * 集中 brep 登记的四步(identity 槽登记已由构造器完成;此处只补:① 身份槽挂载\n * 句柄 / ② 血缘图语句键旁挂 roleTable / ③ 函数 BREP 域登记)。供 `fromBrep` /\n * `fromBrepCurve` 共用——禁止绕开本函数手写登记(否则等于复制一整套身份、血缘与\n * 释放语义)。\n *\n * @param s - the already-constructed shape (solid or curve).\n * @param holder - the BREP holder to attach.\n */\nfunction attachBrep(s: Shape, holder: BrepHolder): void {\n const state = getRuntimeState()\n const slot = state.slots.get(s) ?? {}\n slot.solid = holder.solid\n if (holder.faceEvolution) slot.faceEvolution = holder.faceEvolution\n // 1.10 前置③:roleTable **不再写 slot**(字段已删)——权威落点是下方血缘图\n // 旁挂(语句键 + part 键),解析缓存 miss 由回走重算恢复。\n state.slots.set(s, slot)\n // 1.10 前置③:roleTable 权威旁挂(**语句键**)在血缘图。part 键的记录在\n // define-op.wrapped(impl 返回后 anchor.outputs 名字已定)——此处 shape 还未\n // 被 executor 命名,nameOf(s) 为 undefined,不能在这里记 part 键。\n const stmt = getCurrentStmt()\n if (stmt && (holder.roleTable || holder.solid !== undefined)) {\n runtimeLineage.recordOutput(\n asStmtId(stmt.id),\n holder.roleTable as ReadonlyMap<string, ReadonlyMap<string, readonly number[]>> | undefined,\n holder.solid,\n )\n }\n // 函数 BREP 域(§5.6):函数体内 op 产生的新句柄登记到当前域,函数返回后统一释放\n registerFunctionBrep(holder.solid)\n}\n\n/** BREP 句柄 + 面演化 + 拓扑命名 RoleTable(对应 OCCT 的 ShapeHandle)。类型为 unknown 以保持零依赖。 */\nexport interface BrepHolder {\n solid: unknown\n faceEvolution?: Map<number, number[]>\n /**\n * 1.10 前置③:产形 op 交付 role 表的唯一入口。fromBrep 把它**旁挂到血缘图**\n * (语句键 + part 键);slot 侧的缓存存储已删(ShapeSlot 不再有该字段)。\n */\n roleTable?: unknown\n}\n\n/**\n * compound Shape 构造器:结构(层级)而非新几何。\n *\n * @param children - the child shapes to group.\n * @returns the created compound shape.\n */\nexport function compound(children: Shape[]): CompoundShape {\n const c: CompoundShape = { kind: 'compound', children }\n getRuntimeState().created.add(c)\n return c\n}\n\n/**\n * 是否为构造器产物(终端判定与 compound 检测的依据)。\n *\n * @param v - the value to test.\n * @returns true if the value was created by a shape constructor.\n */\nexport function isShape(v: unknown): v is Shape {\n return !!v && typeof v === 'object' && getRuntimeState().created.has(v)\n}\n\n/**\n * Returns true if the value is a strict compound shape created by a constructor.\n *\n * @param v - the value to test.\n * @returns true if the value is a strict compound shape.\n */\nexport function isCompound(v: unknown): v is CompoundShape {\n return isShape(v) && (v as { kind?: string }).kind === 'compound'\n}\n\n/**\n * 结构判定:是否为 compound 形态(keep-syntax §5.3 D5,对任意库函数零要求)。\n * 引擎内部的终端/消费判定用结构判定;SDK 公开的 isShape/isCompound 保持 WeakSet 严格。\n *\n * @param v - the value to test.\n * @returns true if the value has compound shape structure.\n */\nexport function isCompoundLike(v: unknown): v is CompoundShape {\n return !!v && typeof v === 'object'\n && (v as { kind?: string }).kind === 'compound'\n && Array.isArray((v as { children?: unknown }).children)\n}\n\n/**\n * 1D 曲线判定(1D 判别位,Phase 3):`kind === 'curve'`。\n *\n * 面消费 op(extrude / revolve / sweep 等)用它做**执行前**输入维度预检——\n * 1D 产物(wire / helix / sketch as:'wire')喂给面 op 时必须是明确的预检失败,\n * 不得落进内核深层才报「操作失败」。与 SDK 的 WeakSet 严格 `isShape` 不同,\n * 本判定是结构判定(与 `isCompoundLike` 同族),对跨库产物零要求。\n *\n * @param v - the value to test.\n * @returns true when the value is a 1D curve shape.\n */\nexport function isCurveShape(v: unknown): v is CurveShape {\n return !!v && typeof v === 'object' && (v as { kind?: string }).kind === 'curve'\n}\n\n// ── 身份槽 ──\n\nexport type { ShapeSlot }\n\n/**\n * 读取 Shape 的身份槽(无则 undefined)。\n *\n * @param shape - the shape whose slot to read.\n * @returns the identity slot, or undefined if none is registered.\n */\nexport function getSlot(shape: object): ShapeSlot | undefined {\n return getRuntimeState().slots.get(shape)\n}\n\n/**\n * 读取或创建 Shape 的身份槽。\n *\n * @param shape - the shape whose slot to read or create.\n * @returns the shape's identity slot.\n */\nexport function ensureSlot(shape: object): ShapeSlot {\n const state = getRuntimeState()\n let slot = state.slots.get(shape)\n if (!slot) {\n slot = {}\n state.slots.set(shape, slot)\n }\n return slot\n}\n\n/**\n * 读输入 Shape 的 roleTable(op 实现读**输入**表的唯一读口,1.10 前置③)。\n *\n * 语义 = 旧 `getSlot(shape)?.roleTable`:权威落点在血缘图的 part 键旁挂\n * (上一条语句 fromBrep 时记录),slot 缓存字段已删除。未记录 → undefined\n * (mesh 产物 / 无命名)。\n *\n * @param shape - the input shape whose role table to read.\n * @returns the role table (unknown — callers assert their table type), or undefined.\n */\nexport function inputRoleTable(shape: object): unknown | undefined {\n const name = nameOf(shape)\n return name ? runtimeLineage.tableOfPart(name) : undefined\n}\n\n/**\n * 该 Shape 是否在 BREP 链上(有 OCCT 句柄)。引擎分派与 UI 查询用。\n *\n * @param shape - the shape to test.\n * @returns true if the shape has an attached OCCT handle.\n */\nexport function hasBrep(shape: Shape): boolean {\n return getRuntimeState().slots.get(shape)?.solid !== undefined\n}\n\n/**\n * 读取该 Shape 的 OCCT 句柄(无则 undefined)。库函数用前必须判空。\n *\n * @param shape - the shape whose handle to read.\n * @returns the OCCT handle, or undefined if none.\n */\nexport function brepOf(shape: Shape): unknown | undefined {\n return getRuntimeState().slots.get(shape)?.solid\n}\n\n/**\n * nameOf 批量版:Shape[] → 成员名(装配 memberNames,P6 替代读 IR)。\n *\n * @param shapes - the shapes to name.\n * @returns the member names, one per shape (empty string when unnamed).\n */\nexport function nameOfShapes(shapes: Shape[]): string[] {\n return shapes.map((s) => String(nameOf(s) ?? ''))\n}\n"]}
1
+ {"version":3,"file":"shape.js","sourceRoot":"","sources":["../src/shape.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * api shape — 类型化构造器 + 身份槽\n *\n *\n * 变更要点:\n * - 身份表(created / slots / shapeToName)改读全局锚点 runtime-state,\n * 使\"两份 faijs 代码\"共享同一份状态(解决 Shape 身份孤岛)。\n * - 新增 fromBrep(mesh, holder):BREP 产物一次登记句柄与面演化,\n * 库函数不再手动登记(P2 落地)。\n * - 新增 hasBrep / brepOf:引擎侧判定\"某 Shape 是否在 BREP 链上\"。\n */\n\nimport type { Shape } from './mesh/types'\nimport { getRuntimeState, registerFunctionBrep, nameOf, getCurrentStmt, type ShapeSlot } from './runtime-state'\nimport { asStmtId } from './identity'\nimport { runtimeLineage } from './topology/naming/lineage'\n\n// ── Shape 构造器 ──\n\n/** Discriminator for the concrete shape kinds. */\nexport type ShapeKind = 'solid' | 'shape2d' | 'curve' | 'compound'\n\n/** A solid mesh shape produced by a constructor. */\nexport interface SolidShape extends Shape {\n kind: 'solid'\n}\n\n/** A structural compound grouping a list of child shapes. */\nexport interface CompoundShape {\n kind: 'compound'\n children: Shape[]\n}\n\n/**\n * 1D 曲线 Shape(wire / helix / edge-loop 等无三角载荷的 1D 几何)。\n *\n * `kind: 'curve'` 表达「无三角载荷」,与 `'solid'` 对称(见 `curve()` /\n * `fromBrepCurve()`)。执行链路照走 `solidToShape`(wire → 空 0/0 载荷,不抛),\n * 显示经 `wireframe`。\n */\nexport interface CurveShape extends Shape {\n kind: 'curve'\n}\n\n/** A shape that the api layer exports as a finished result. */\nexport type StdShape = SolidShape | CompoundShape | CurveShape\n\n/**\n * 实体 Shape 构造器:mesh 产物必须经此创建。\n *\n * @param mesh - the mesh shape to wrap as a solid.\n * @returns the created solid shape.\n */\nexport function solid(mesh: Shape): SolidShape {\n const s: SolidShape = { ...mesh, kind: 'solid' }\n getRuntimeState().created.add(s)\n return s\n}\n\n/**\n * 1D 曲线 Shape 构造器(wire / helix / edge-loop 等 1D 产物)。\n *\n * 与 `solid` 对称:登记到 identity 表(供 `isShape` 识别),`kind` 设为 `'curve'`\n * 以表达「无三角载荷的 1D 几何」(执行链路照走 `solidToShape`,显示经 `wireframe`)。\n *\n * @param mesh - the mesh payload (positions/indices) to wrap as a curve.\n * @returns the created curve shape.\n */\nexport function curve(mesh: Shape): CurveShape {\n const s: CurveShape = { ...mesh, kind: 'curve' }\n getRuntimeState().created.add(s)\n return s\n}\n\n/**\n * BREP 产物构造器:同时登记 mesh 与 OCCT 句柄(+ 可选面演化)。\n *\n * 库函数用它替代 `solid(mesh)` + 手动登记句柄两步行:\n * ```ts\n * return fromBrep(solidToShape(kernel, resultSolid), {\n * solid: resultSolid,\n * faceEvolution: identityEvolution(kernel, resultSolid),\n * })\n * ```\n *\n * @param mesh - the mesh shape to register.\n * @param holder - the BREP holder providing the OCCT handle and optional face evolution.\n * @returns the created solid shape with the BREP handle attached.\n */\nexport function fromBrep(mesh: Shape, holder: BrepHolder): SolidShape {\n const s = solid(mesh)\n attachBrep(s, holder)\n return s\n}\n\n/**\n * 1D 曲线产物的 BREP 登记构造器:与 `fromBrep` 对称,但 `kind` 取 `'curve'`\n * (维持既有「有无三角载荷」语义——1D 几何无三角载荷,不得报 `'solid'`)。\n * 登记逻辑与 `fromBrep` 共用 `attachBrep`,保证两种形态走同一份身份/血缘/释放语义。\n *\n * @param mesh - the mesh payload (positions/indices) to wrap as a curve.\n * @param holder - the BREP holder providing the OCCT handle and optional face evolution.\n * @returns the created curve shape with the BREP handle attached.\n */\nexport function fromBrepCurve(mesh: Shape, holder: BrepHolder): CurveShape {\n const s = curve(mesh)\n attachBrep(s, holder)\n return s\n}\n\n/**\n * 网格实体产物的构造器:与 `fromBrep` 对称,登记网格实体句柄(近似链)而非\n * BREP 句柄(精度链)。\n *\n * ```ts\n * return fromMeshSolid(displayMesh, { meshSolid: result.solid })\n * ```\n *\n * 与 `fromBrep` 的三点差别(方案 §3.2):\n * 1. 写 `slot.meshSolid`,**不写** `slot.solid`——网格零件永不进 BREP 链;\n * 2. 不登记函数 BREP 域(`registerFunctionBrep`)——句柄所有权在\n * `MeshSolidRegistry`,按 BREP 内核释放是错的(可能是另一个内核);\n * 3. 不旁挂 roleTable(近似拓扑不给语义 role——role 是 BREP 真拓扑的专有能力)。\n *\n * @param mesh - the mesh shape to wrap as a solid (display mesh).\n * @param holder - the mesh-solid holder providing the handle identity.\n * @returns the created solid shape carrying the mesh-solid slot.\n */\nexport function fromMeshSolid(mesh: Shape, holder: MeshSolidHolder): SolidShape {\n const s = solid(mesh)\n attachMeshSolid(s, holder.meshSolid)\n return s\n}\n\n/** 网格实体句柄容器(与 `BrepHolder` 对称;类型为 unknown 以保持零依赖)。 */\nexport interface MeshSolidHolder {\n /** 网格实体句柄的**身份**(句柄本体在 `MeshSolidRegistry`)。 */\n meshSolid: unknown\n}\n\n/**\n * 网格链**面**产物的构造器(方案 2026-10-01 §4 Phase 3)。与 `fromBrep` 的\n * 面产物对称:BREP 侧 `sketchOnFace` 返回 `fromBrep(solidToShape(kernel, face),\n * { solid: face })`,这里返回 `fromMeshFace(meshShape(face), { meshFace: face })`。\n *\n * `kind` 沿用 `'solid'`(不是 `'shape2d'`):与 BREP 侧的面 Shape 保持同一形态,\n * 好让 `extrude` 的 `isCurveShape` 预检在两条链上行为一致——面不是 1D 曲线,\n * 不该被面消费 op 当成曲线拒掉。\n *\n * @param mesh - the face's display mesh (its own tessellation).\n * @param holder - the mesh-face holder providing the handle identity.\n * @returns the created shape carrying the mesh-face slot.\n */\nexport function fromMeshFace(mesh: Shape, holder: MeshFaceHolder): SolidShape {\n const s = solid(mesh)\n attachMeshFace(s, holder.meshFace)\n return s\n}\n\n/** 网格链面句柄容器(与 `MeshSolidHolder` 对称;类型为 unknown 以保持零依赖)。 */\nexport interface MeshFaceHolder {\n /** 网格链面句柄的**身份**。 */\n meshFace: unknown\n}\n\n/**\n * 把网格实体句柄登记到已构造的 Shape。\n *\n * 互斥红线:该 Shape 已有 BREP 句柄或网格链面句柄时**直接抛错**——一个 Shape\n * 同时声称两种链身份是设计缺陷,不能静默覆盖任何一侧。\n *\n * @param s - the already-constructed shape.\n * @param meshSolid - the mesh solid handle.\n * @throws {Error} `E_SHAPE_SLOT_EXCLUSIVE` when the shape already carries another chain identity.\n */\nexport function attachMeshSolid(s: Shape, meshSolid: unknown): void {\n const state = getRuntimeState()\n const slot = state.slots.get(s) ?? {}\n if (slot.solid !== undefined) {\n throw new Error(\n 'E_SHAPE_SLOT_EXCLUSIVE: shape already carries a BREP handle — a shape is either on the precision chain or the mesh chain, never both',\n )\n }\n if (slot.meshFace !== undefined) {\n throw new Error(\n 'E_SHAPE_SLOT_EXCLUSIVE: shape already carries a mesh-chain face handle — a shape is either a mesh solid or a mesh-chain face, never both',\n )\n }\n slot.meshSolid = meshSolid\n state.slots.set(s, slot)\n}\n\n/**\n * 把网格链**面**句柄登记到已构造的 Shape。\n *\n * 与 `attachMeshSolid` 同一条互斥红线:已有任意另一种链身份即抛错。\n *\n * @param s - the already-constructed shape.\n * @param meshFace - the mesh-chain face handle.\n * @throws {Error} `E_SHAPE_SLOT_EXCLUSIVE` when the shape already carries another chain identity.\n */\nexport function attachMeshFace(s: Shape, meshFace: unknown): void {\n const state = getRuntimeState()\n const slot = state.slots.get(s) ?? {}\n if (slot.solid !== undefined || slot.meshSolid !== undefined) {\n throw new Error(\n 'E_SHAPE_SLOT_EXCLUSIVE: shape already carries a BREP or mesh-solid handle — a mesh-chain face is its own identity',\n )\n }\n slot.meshFace = meshFace\n state.slots.set(s, slot)\n}\n\n/**\n * 该 Shape 是否携带网格链面(`sketchOnFace` 在近似拓扑面上的产物)。\n *\n * @param shape - the shape to test.\n * @returns true if the shape carries a mesh-chain face handle.\n */\nexport function hasMeshFace(shape: Shape): boolean {\n return getRuntimeState().slots.get(shape)?.meshFace !== undefined\n}\n\n/**\n * 读取该 Shape 的网格链面句柄(无则 undefined)。\n *\n * @param shape - the shape whose mesh-chain face handle to read.\n * @returns the mesh-chain face handle, or undefined if none.\n */\nexport function meshFaceOf(shape: Shape): unknown | undefined {\n return getRuntimeState().slots.get(shape)?.meshFace\n}\n\n/**\n * 该 Shape 是否携带网格实体(网格零件)。引擎分派与 UI 查询用。\n *\n * 与 `hasBrep` 互斥:正常路径下二者不可能同时为真(`attachMeshSolid` 已经把\n * 互斥钉在写入侧,`assertShapeSlotExclusive` 在分派前再兜一层)。\n *\n * @param shape - the shape to test.\n * @returns true if the shape carries a mesh solid handle.\n */\nexport function hasMeshSolid(shape: Shape): boolean {\n return getRuntimeState().slots.get(shape)?.meshSolid !== undefined\n}\n\n/**\n * 读取该 Shape 的网格实体句柄(无则 undefined)。\n *\n * @param shape - the shape whose mesh solid handle to read.\n * @returns the mesh solid handle, or undefined if none.\n */\nexport function meshSolidOf(shape: Shape): unknown | undefined {\n return getRuntimeState().slots.get(shape)?.meshSolid\n}\n\n/**\n * 把 BREP 句柄登记到已构造的 Shape(由 `solid` / `curve` 产出)。\n *\n * 集中 brep 登记的四步(identity 槽登记已由构造器完成;此处只补:① 身份槽挂载\n * 句柄 / ② 血缘图语句键旁挂 roleTable / ③ 函数 BREP 域登记)。供 `fromBrep` /\n * `fromBrepCurve` 共用——禁止绕开本函数手写登记(否则等于复制一整套身份、血缘与\n * 释放语义)。\n *\n * @param s - the already-constructed shape (solid or curve).\n * @param holder - the BREP holder to attach.\n */\nfunction attachBrep(s: Shape, holder: BrepHolder): void {\n const state = getRuntimeState()\n const slot = state.slots.get(s) ?? {}\n if (slot.meshSolid !== undefined || slot.meshFace !== undefined) {\n // 互斥红线的另一侧:网格链产物不得再被登记成 BREP 实体(一个 Shape 只能\n // 在精度链或网格链之一上)。\n throw new Error(\n 'E_SHAPE_SLOT_EXCLUSIVE: shape already carries a mesh-chain handle — a shape is either on the precision chain or the mesh chain, never both',\n )\n }\n slot.solid = holder.solid\n if (holder.faceEvolution) slot.faceEvolution = holder.faceEvolution\n // 1.10 前置③:roleTable **不再写 slot**(字段已删)——权威落点是下方血缘图\n // 旁挂(语句键 + part 键),解析缓存 miss 由回走重算恢复。\n state.slots.set(s, slot)\n // 1.10 前置③:roleTable 权威旁挂(**语句键**)在血缘图。part 键的记录在\n // define-op.wrapped(impl 返回后 anchor.outputs 名字已定)——此处 shape 还未\n // 被 executor 命名,nameOf(s) 为 undefined,不能在这里记 part 键。\n const stmt = getCurrentStmt()\n if (stmt && (holder.roleTable || holder.solid !== undefined)) {\n runtimeLineage.recordOutput(\n asStmtId(stmt.id),\n holder.roleTable as ReadonlyMap<string, ReadonlyMap<string, readonly number[]>> | undefined,\n holder.solid,\n )\n }\n // 函数 BREP 域(§5.6):函数体内 op 产生的新句柄登记到当前域,函数返回后统一释放\n registerFunctionBrep(holder.solid)\n}\n\n/** BREP 句柄 + 面演化 + 拓扑命名 RoleTable(对应 OCCT 的 ShapeHandle)。类型为 unknown 以保持零依赖。 */\nexport interface BrepHolder {\n solid: unknown\n faceEvolution?: Map<number, number[]>\n /**\n * 1.10 前置③:产形 op 交付 role 表的唯一入口。fromBrep 把它**旁挂到血缘图**\n * (语句键 + part 键);slot 侧的缓存存储已删(ShapeSlot 不再有该字段)。\n */\n roleTable?: unknown\n}\n\n/**\n * compound Shape 构造器:结构(层级)而非新几何。\n *\n * @param children - the child shapes to group.\n * @returns the created compound shape.\n */\nexport function compound(children: Shape[]): CompoundShape {\n const c: CompoundShape = { kind: 'compound', children }\n getRuntimeState().created.add(c)\n return c\n}\n\n/**\n * 是否为构造器产物(终端判定与 compound 检测的依据)。\n *\n * @param v - the value to test.\n * @returns true if the value was created by a shape constructor.\n */\nexport function isShape(v: unknown): v is Shape {\n return !!v && typeof v === 'object' && getRuntimeState().created.has(v)\n}\n\n/**\n * Returns true if the value is a strict compound shape created by a constructor.\n *\n * @param v - the value to test.\n * @returns true if the value is a strict compound shape.\n */\nexport function isCompound(v: unknown): v is CompoundShape {\n return isShape(v) && (v as { kind?: string }).kind === 'compound'\n}\n\n/**\n * 结构判定:是否为 compound 形态(keep-syntax §5.3 D5,对任意库函数零要求)。\n * 引擎内部的终端/消费判定用结构判定;SDK 公开的 isShape/isCompound 保持 WeakSet 严格。\n *\n * @param v - the value to test.\n * @returns true if the value has compound shape structure.\n */\nexport function isCompoundLike(v: unknown): v is CompoundShape {\n return !!v && typeof v === 'object'\n && (v as { kind?: string }).kind === 'compound'\n && Array.isArray((v as { children?: unknown }).children)\n}\n\n/**\n * 1D 曲线判定(1D 判别位,Phase 3):`kind === 'curve'`。\n *\n * 面消费 op(extrude / revolve / sweep 等)用它做**执行前**输入维度预检——\n * 1D 产物(wire / helix / sketch as:'wire')喂给面 op 时必须是明确的预检失败,\n * 不得落进内核深层才报「操作失败」。与 SDK 的 WeakSet 严格 `isShape` 不同,\n * 本判定是结构判定(与 `isCompoundLike` 同族),对跨库产物零要求。\n *\n * @param v - the value to test.\n * @returns true when the value is a 1D curve shape.\n */\nexport function isCurveShape(v: unknown): v is CurveShape {\n return !!v && typeof v === 'object' && (v as { kind?: string }).kind === 'curve'\n}\n\n// ── 身份槽 ──\n\nexport type { ShapeSlot }\n\n/**\n * 读取 Shape 的身份槽(无则 undefined)。\n *\n * @param shape - the shape whose slot to read.\n * @returns the identity slot, or undefined if none is registered.\n */\nexport function getSlot(shape: object): ShapeSlot | undefined {\n return getRuntimeState().slots.get(shape)\n}\n\n/**\n * 读取或创建 Shape 的身份槽。\n *\n * @param shape - the shape whose slot to read or create.\n * @returns the shape's identity slot.\n */\nexport function ensureSlot(shape: object): ShapeSlot {\n const state = getRuntimeState()\n let slot = state.slots.get(shape)\n if (!slot) {\n slot = {}\n state.slots.set(shape, slot)\n }\n return slot\n}\n\n/**\n * 读输入 Shape 的 roleTable(op 实现读**输入**表的唯一读口,1.10 前置③)。\n *\n * 语义 = 旧 `getSlot(shape)?.roleTable`:权威落点在血缘图的 part 键旁挂\n * (上一条语句 fromBrep 时记录),slot 缓存字段已删除。未记录 → undefined\n * (mesh 产物 / 无命名)。\n *\n * @param shape - the input shape whose role table to read.\n * @returns the role table (unknown — callers assert their table type), or undefined.\n */\nexport function inputRoleTable(shape: object): unknown | undefined {\n const name = nameOf(shape)\n return name ? runtimeLineage.tableOfPart(name) : undefined\n}\n\n/**\n * 该 Shape 是否在 BREP 链上(有 OCCT 句柄)。引擎分派与 UI 查询用。\n *\n * @param shape - the shape to test.\n * @returns true if the shape has an attached OCCT handle.\n */\nexport function hasBrep(shape: Shape): boolean {\n return getRuntimeState().slots.get(shape)?.solid !== undefined\n}\n\n/**\n * 读取该 Shape 的 OCCT 句柄(无则 undefined)。库函数用前必须判空。\n *\n * @param shape - the shape whose handle to read.\n * @returns the OCCT handle, or undefined if none.\n */\nexport function brepOf(shape: Shape): unknown | undefined {\n return getRuntimeState().slots.get(shape)?.solid\n}\n\n/**\n * nameOf 批量版:Shape[] → 成员名(装配 memberNames,P6 替代读 IR)。\n *\n * @param shapes - the shapes to name.\n * @returns the member names, one per shape (empty string when unnamed).\n */\nexport function nameOfShapes(shapes: Shape[]): string[] {\n return shapes.map((s) => String(nameOf(s) ?? ''))\n}\n"]}
@@ -302,6 +302,12 @@ export declare class LineageGraph {
302
302
  nodeConsuming(part: PartName): LineageNode | undefined;
303
303
  /** 已登记的语句数。 */
304
304
  get size(): number;
305
+ /**
306
+ * 全部已登记语句 id(回走恢复需遍历候选 origin 时用)。
307
+ *
308
+ * @returns the registered statement ids.
309
+ */
310
+ stmtIds(): StmtId[];
305
311
  /** 清空(每次执行开始时调用——一次执行内 `StmtId` 稳定)。 */
306
312
  clear(): void;
307
313
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"lineage.d.ts","sourceRoot":"","sources":["../../../src/topology/naming/lineage.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"lineage.d.ts","sourceRoot":"","sources":["../../../src/topology/naming/lineage.ts"],"names":[],"mappings":"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"}
@@ -319,6 +319,14 @@ export class LineageGraph {
319
319
  get size() {
320
320
  return this.nodes.size;
321
321
  }
322
+ /**
323
+ * 全部已登记语句 id(回走恢复需遍历候选 origin 时用)。
324
+ *
325
+ * @returns the registered statement ids.
326
+ */
327
+ stmtIds() {
328
+ return [...this.nodes.keys()];
329
+ }
322
330
  /** 清空(每次执行开始时调用——一次执行内 `StmtId` 稳定)。 */
323
331
  clear() {
324
332
  this.nodes.clear();
@@ -1 +1 @@
1
- {"version":3,"file":"lineage.js","sourceRoot":"","sources":["../../../src/topology/naming/lineage.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * lineage.ts — 血缘图登记(计划 §4.3)。\n *\n * 每个 op 执行完登记一条 `LineageNode`:**谁(`StmtId`)用什么 op、吃了哪些\n * part、产出哪些 part、属哪个 provenance 类别**。两张表:\n *\n * | 表 | 键 → 值 | 用途 |\n * |---|---|---|\n * | `lineage` | `StmtId` → `LineageNode` | 从身份原点沿 DAG 前进 |\n * | `partToStmt` | `PartName` → `StmtId` | 从 part 名字反查是哪条语句造的 |\n *\n * ## 为什么这一层必须存在\n *\n * 现状把身份表达成 **hash**(`face-evolution.ts` 的内存指针哈希),于是每次查询都在\n * 付「对齐 hash」的利息:谁改了几何,谁的 hash 就变,身份就断。正确形态是\n * `(StmtId, RoleName)` 的**因果坐标**——`StmtId` 说「哪条语句产生」,`RoleName` 说\n * 「那条语句把它当作什么」。因果坐标不随几何变化,**也不需要知道中间过了几个 op**。\n *\n * ## 登记口只能有一个(但调用点有两个)\n *\n * 手写 op 走 `wrapBrepOne`(`define-op.ts`),生成投影走 `compatOp`\n * (`api/internal/compat-op.ts`)——**两条路径都必须登记**,否则 42 条投影永远无名。\n * 但两条路径共用一个 `register()`,规则才只有一处。\n *\n * ## 三条硬规则(这是「未来漏洞最少」的核心)\n *\n * | # | 规则 | 违反时 |\n * |---|---|---|\n * | **N1** | inputs 里任一 Shape 查不到 `PartName` → 报错 | `E_TOPO_UNTRACKED_INPUT` |\n * | **N2** | 当前语句锚点缺失,或与声明的 `stmt` 不符 → 报错 | `E_TOPO_NO_ANCHOR` |\n * | **N3** | 同一 `StmtId` 重复登记且**身份内容**不同 → 报错 | `E_TOPO_DUPLICATE_STMT` |\n *\n * **N1 为什么必须是错误而不是\"默认成链根\"**:op 内部常临时造 Shape(中间产物、\n * 工具件)。若给它们默认一个 origin,「看起来对但语义错」的身份就诞生了——\n * 引用能解析成功,但解析到**别的面**。这类错误不会在测试里暴露(测试用的参数恰好\n * 让两者重合),只会在用户改参数、改尺寸时暴露。**宁可在执行期就炸。**\n *\n * **N2 为什么现在才敢做**:它依赖 `getCurrentStmt()` 是\"当前语句的权威读法\"。\n * 这一点由约束 **C1(禁止并发多 runtime)** 保证(见 §4.7.1)——不是\"全局态凑合能用\"。\n *\n * ## 依赖注入,不读全局\n *\n * `register()` 收一个 `LineageDeps`(`nameOf` / `currentStmt`)而不是 import\n * `runtime-state`。理由有两条:其一,`topology/` 现有模块(如 `roles.ts`)都是\n * \"把依赖当参数\"的风格,读全局会破坏它;其二,N1/N2/N3 的测试不想去摆弄全局态。\n */\n\nimport type { PartName, StmtId } from '../../identity'\nimport type { HashEvolution } from '../../brep/face-evolution'\nimport { type RoleName } from './role-name'\n\n// ── provenance 类别(封闭,计划 §4.4)──\n\n/**\n * 新造面的获取方式(只有 `kernel` / `construct` 需要)。\n *\n * - `byAdjacency`:靠结果形状与输入的**邻接关系**推出哪个面是新造的\n * (布尔/倒角等:新面必然与已知面相邻,而幸存面有自己的坐标)\n * - `explicit`:op 直接给出词汇表(构造类:底面 = profile、侧面 i = 第 i 条边扫掠)\n *\n * ⚠️ **不能靠内核的 `generated` 桶**(Phase 0.4 实测):它与 `modified` 同构分段、\n * 键集相同,值是各输入面派生的**中间形**——`cut` 里 12 个 hash 结果里 0 存活,\n * `fillet`/`fuse` 里整桶为空。故 `byAdjacency` / `explicit` 是**必填**。\n */\nexport type NewFaceRule =\n | { readonly via: 'byAdjacency' }\n | { readonly via: 'explicit'; readonly vocab: readonly RoleName[] }\n\n/**\n * 六个 provenance 类别(计划 §4.4,封闭集)。\n *\n * **继承面的处置完全由类别决定,op 不写**;只有 `construct` 和 `kernel` 会造新面,\n * 才有词汇这一项 ⇒ `identity` / `subdivide` / `replicate(k)` **零声明**。\n *\n * 本表是**类别归属**,不是接线状态(例:`sweep` 属 `construct` 类但未接线,见 §1 D10)。\n */\nexport type Provenance =\n /** 内核给历史:boolean / fillet / chamfer / shell / offset / 刚体变换 */\n | { readonly kind: 'kernel'; readonly newFaces: NewFaceRule }\n /** 输出面 ↔ 输入的构造规则:extrude / revolve / sweep / loft / primitives / sketch / import_brep */\n | { readonly kind: 'construct'; readonly newFaces: Extract<NewFaceRule, { via: 'explicit' }> }\n /** 1:1,第 i 面 → 第 i 面:copy / place / clone / locate / applyMatrix */\n | { readonly kind: 'identity' }\n /** 每输入面 → 若干片:split / section */\n | { readonly kind: 'subdivide' }\n /** 第 k 份第 i 面 ← 第 i 面:linearPattern / circularPattern / gridPattern / rectangularPattern / mirrorJoin */\n | { readonly kind: 'replicate'; readonly k: number }\n /** 显式记账:算不出来。应趋近于 0;审计测试必须列出全部并给出理由 */\n | { readonly kind: 'unmodeled'; readonly reason: string }\n\n/** `Provenance` 的类别标签(封闭六值)。 */\nexport type ProvenanceKind = Provenance['kind']\n\n/** 六个类别标签,供审计测试枚举(新增类别必须同步此处)。 */\nexport const PROVENANCE_KINDS = [\n 'kernel',\n 'construct',\n 'identity',\n 'subdivide',\n 'replicate',\n 'unmodeled',\n] as const\n\n/**\n * 演化记录(`kind='kernel'` 时执行期补挂)。\n *\n * 两种形态并存(1.10 前置①实测):\n * - **序号键**(`slot.faceEvolution` 的实际存储形态,`Map<ordinal, ordinal[]>`):\n * boolean/fillet/chamfer 走 `decodeEvolution`(逐句柄 hashCode),copy/transform/place\n * 走 `identityEvolution`(恒等)。回走推进 identity 类与\"序号不变\"的 kernel 路径用它。\n * - **哈希键**(`HashEvolution`,`decodeHashEvolution` 的输出):只在 booleanWithRoleTable\n * 等组合函数内部瞬时存在,不落 slot。回走按哈希集合推进时用它。\n */\nexport type EvolutionRecord = Map<number, number[]> | HashEvolution\n\n/**\n * 判断演化记录是否为哈希键形态(`HashEvolution` 有 `modified`/`deleted` 字段)。\n *\n * @param e - the evolution record to test.\n * @returns true when the record is the hash-key form (`HashEvolution`).\n */\nexport function isHashEvolution(e: EvolutionRecord): e is HashEvolution {\n return 'modified' in e && 'deleted' in e\n}\n\n/**\n * 血缘图的一个节点 = 一条语句的登记记录。\n *\n * `inputs`/`outputs` 是 `PartName`(不是 Shape):Shape 是执行期的活对象,\n * 身份层必须只留**可序列化、可比较**的东西,否则节点会随 arena 释放而失去意义。\n */\nexport interface LineageNode {\n /** 该语句的 id(`ExecutionAnchor.id`),全局唯一。 */\n readonly stmt: StmtId\n /** op 名(如 `cad.fillet`)——用于报错信息与审计。 */\n readonly op: string\n /** 输入 part 名(`inputs.map(nameOf)` 的结果,已保证全部有名字)。 */\n readonly inputs: readonly PartName[]\n /** 产出 part 名(至少一个)。 */\n readonly outputs: readonly PartName[]\n /** provenance 类别 + 该类别的载荷。 */\n readonly provenance: Provenance\n /** `kind='kernel'` 时执行期记录的 hash 演化(`attachEvolution` 事后补上)。 */\n readonly evolution?: EvolutionRecord\n}\n\n/**\n * 登记入参(尚未解析成 `PartName` 的形态)。\n *\n * `inputs` 故意收 **Shape 句柄**而不是 `PartName`:N1 的判据就是\n * \"这个 Shape 有没有名字\",若调用方先自己 map 成名字,就正好把\n * \"查不到名字\"这一步跳过/默认了——那正是 N1 要防的。\n */\nexport interface LineageDraft {\n /** 声明本条语句的 id(N2 会与当前锚点核对)。 */\n readonly stmt: StmtId\n /** op 名。 */\n readonly op: string\n /** 输入 Shape 句柄(N1 在 register 内解析)。 */\n readonly inputs: readonly object[]\n /** 产出 part 名(非空;调用方从锚点/nameOf 拿到)。 */\n readonly outputs: readonly [PartName, ...PartName[]]\n /** provenance 类别 + 载荷。 */\n readonly provenance: Provenance\n}\n\n/** 登记所需的外部读口(由调用点注入,见文件头「依赖注入」)。 */\nexport interface LineageDeps {\n /** Shape → PartName(`runtime-state` 的 `nameOf`)。 */\n readonly nameOf: (shape: object) => PartName | undefined\n /** 当前执行语句锚点(`runtime-state` 的 `getCurrentStmt`)。 */\n readonly currentStmt: () => { readonly id: string } | undefined\n}\n\n// ── 错误 ──\n\n/** 血缘登记错误码(三条规则 N1/N2/N3)。 */\nexport type LineageErrorCode = 'E_TOPO_UNTRACKED_INPUT' | 'E_TOPO_NO_ANCHOR' | 'E_TOPO_DUPLICATE_STMT'\n\n/** 血缘登记失败。带稳定错误码,禁止静默兜底。 */\nexport class LineageError extends Error {\n /** 稳定错误码(宿主/args 校验按码识别)。 */\n readonly code: LineageErrorCode\n /** 出错的语句 id(若能确定)。 */\n readonly stmt?: string\n\n /**\n * @param code - the stable error code.\n * @param message - what went wrong, with the offending statement named.\n * @param stmt - the statement id, when known.\n */\n constructor(code: LineageErrorCode, message: string, stmt?: string) {\n super(message)\n this.name = 'LineageError'\n this.code = code\n this.stmt = stmt\n }\n}\n\n// ── 结构化比较(不引 node:util——topology/ 要能进浏览器构建)──\n\n/**\n * 两个 `RoleName` 是否相等(按值、递归)。\n *\n * 手写而不是 `JSON.stringify` 比较:键序会随写字面量的顺序变化\n * (`{index, op}` 与 `{op, index}` 是同一个值、不同的 JSON),\n * 而这两个函数是 N3「内容不同才报错」的判据——键序敏感会**误报冲突**。\n *\n * @param a - one role name.\n * @param b - the other role name.\n * @returns true when the two roles are structurally identical.\n */\nexport function roleNameEquals(a: RoleName, b: RoleName): boolean {\n switch (a.kind) {\n case 'semantic':\n return b.kind === 'semantic' && a.name === b.name\n case 'wall':\n return b.kind === 'wall' && a.index === b.index\n case 'imported':\n return b.kind === 'imported' && a.index === b.index\n case 'generated':\n return b.kind === 'generated' && a.op === b.op && a.index === b.index\n case 'hole':\n return b.kind === 'hole' && a.index === b.index && roleNameEquals(a.inner, b.inner)\n case 'replica':\n return b.kind === 'replica' && a.k === b.k && roleNameEquals(a.inner, b.inner)\n case 'splinter':\n return b.kind === 'splinter' && a.index === b.index && roleNameEquals(a.inner, b.inner)\n }\n}\n\n/**\n * 两条新造面规则是否相等(词汇表**逐项按序**比较——顺序是构造语义的一部分:\n * 侧面 i 对应第 i 条 profile 边,重排就是换了一个 role)。\n *\n * @param a - one rule.\n * @param b - the other rule.\n * @returns true when the two rules are structurally identical.\n */\nexport function newFaceRuleEquals(a: NewFaceRule, b: NewFaceRule): boolean {\n if (a.via === 'byAdjacency') return b.via === 'byAdjacency'\n if (b.via !== 'explicit') return false\n if (a.vocab.length !== b.vocab.length) return false\n for (let i = 0; i < a.vocab.length; i++) {\n if (!roleNameEquals(a.vocab[i], b.vocab[i])) return false\n }\n return true\n}\n\n/**\n * 两个 `Provenance` 是否相等(按值)。\n *\n * @param a - one provenance.\n * @param b - the other provenance.\n * @returns true when they are structurally identical.\n */\nexport function provenanceEquals(a: Provenance, b: Provenance): boolean {\n switch (a.kind) {\n case 'identity':\n return b.kind === 'identity'\n case 'subdivide':\n return b.kind === 'subdivide'\n case 'replicate':\n return b.kind === 'replicate' && a.k === b.k\n case 'unmodeled':\n return b.kind === 'unmodeled' && a.reason === b.reason\n case 'kernel':\n return b.kind === 'kernel' && newFaceRuleEquals(a.newFaces, b.newFaces)\n case 'construct':\n return b.kind === 'construct' && newFaceRuleEquals(a.newFaces, b.newFaces)\n }\n}\n\n/** 两个字符串数组是否逐项相等。 */\nfunction sameNames(a: readonly PartName[], b: readonly PartName[]): boolean {\n return a.length === b.length && a.every((x, i) => x === b[i])\n}\n\n// ── 血缘图 ──\n\n/**\n * 血缘图:两张表 + 一个登记函数。\n *\n * 实例化而非全局单例,是为了让 N1/N2/N3 的测试各用各的图、互不污染;\n * 执行期由 `runtime-state` 侧持有唯一实例(C1 保证单 runtime,不存在两图并存)。\n */\nexport class LineageGraph {\n private readonly nodes = new Map<StmtId, LineageNode>()\n private readonly partOwner = new Map<PartName, StmtId>()\n /**\n * 执行期旁挂:语句输出 part 的 roleTable(1.10 前置③)。\n *\n * 回走锚定需要 root 语句的「origin→role→hash[]」表;它本来只存在\n * `slot.roleTable`(解析缓存)里,删字段后唯一落点就是这里。\n * 不进 `LineageNode`(节点是身份数据,N3 比较不含它)。\n */\n private readonly outputTables = new Map<StmtId, ReadonlyMap<string, ReadonlyMap<string, readonly number[]>>>()\n /**\n * 执行期旁挂:语句输出 part 的 BREP 句柄(回走锚定/落地做 ordinal↔hash 换算用)。\n * 句柄是活对象不进节点;随 `clear()` 一起清(句柄生命周期由 solidCache 管)。\n */\n private readonly outputHandles = new Map<StmtId, unknown>()\n /**\n * 执行期旁挂:**part 名键**的 roleTable(1.10 前置③,op 读输入表用)。\n *\n * 为什么有语句键还要 part 键:op 实现读的是「输入 part 的表」。按语句反查\n * (stmtOf(part))在重赋值下会指到**本语句**——register 先于 impl 执行,\n * `part0 = translate(part0)` 的 partOwner 已被 s2 覆盖,impl 读输入表时\n * 拿到的是自己的输出。part 键表只在 `recordOutput`(impl 内 fromBrep 时)\n * 才覆盖 ⇒ impl 读表时看到的仍是上一条语句记录的旧表——时序天然正确。\n */\n private readonly outputTablesByPart = new Map<PartName, ReadonlyMap<string, ReadonlyMap<string, readonly number[]>>>()\n\n /**\n * 登记一条语句(N1/N2/N3 全在这里校验)。\n *\n * @param draft - the statement's lineage facts (inputs still as Shape handles).\n * @param deps - the injected readers (`nameOf` / `currentStmt`).\n * @returns the stored node.\n * @throws LineageError on N1 (untracked input), N2 (anchor mismatch), or N3 (conflicting re-register).\n */\n register(draft: LineageDraft, deps: LineageDeps): LineageNode {\n const stmt = draft.stmt\n\n // N2:当前锚点必须是本条语句,否则说明\"我拿到的 stmt 不是正在跑的那条\"。\n const anchor = deps.currentStmt()\n if (!anchor) {\n throw new LineageError(\n 'E_TOPO_NO_ANCHOR',\n `${draft.op} 登记血缘时无当前语句锚点(getCurrentStmt() 为空)`,\n stmt,\n )\n }\n if (anchor.id !== stmt) {\n throw new LineageError(\n 'E_TOPO_NO_ANCHOR',\n `${draft.op} 声明的语句 ${stmt} 与当前锚点 ${anchor.id} 不符`,\n stmt,\n )\n }\n\n // N1:输入 Shape 必须都有 PartName——**不许默认成链根**。\n const inputs: PartName[] = []\n for (let i = 0; i < draft.inputs.length; i++) {\n const name = deps.nameOf(draft.inputs[i])\n if (name === undefined) {\n throw new LineageError(\n 'E_TOPO_UNTRACKED_INPUT',\n `${draft.op} 的第 ${i} 个输入 Shape 没有 PartName(op 内部临时造的件?)。` +\n `不允许默认成链根——那会产生\"能解析但解析错面\"的假身份。`,\n stmt,\n )\n }\n inputs.push(name)\n }\n\n const node: LineageNode = {\n stmt,\n op: draft.op,\n inputs,\n outputs: [...draft.outputs],\n provenance: draft.provenance,\n }\n\n // N3:同一语句重复登记,若**身份内容**不同即为冲突。\n // 注意比较范围刻意**不含 evolution**:它在执行期事后补(`attachEvolution`),\n // 若纳入比较,第二次登记会因\"上次还没补 evolution\"而误报冲突。\n const existing = this.nodes.get(stmt)\n if (existing && !sameIdentity(existing, node)) {\n throw new LineageError(\n 'E_TOPO_DUPLICATE_STMT',\n `${stmt} 被重复登记且内容不同:` +\n `已登记 ${existing.op}(${existing.inputs.join(',')} → ${existing.outputs.join(',')}, ${existing.provenance.kind}),` +\n `本次为 ${node.op}(${node.inputs.join(',')} → ${node.outputs.join(',')}, ${node.provenance.kind})`,\n stmt,\n )\n }\n\n // PartName → StmtId:反查索引(名字 → 语句)。**最后写者胜**。\n //\n // 重赋值(`part0 = cad.translate(part0, …)`)是 faijs 的合法惯用法:后一条语句\n // 重新绑定同名 PartName,旧绑定随之失效。身份载体是 `(StmtId, RoleName)`,\n // PartName 只是反查索引,故覆盖更新即可——不报错。\n //\n // ⚠️ 曾经这里有一条 `E_TOPO_PART_REDEFINED` 守卫(把\"两名同出\"一律判为\n // \"反查歧义\")。§1.4/1.5 接线后它当场误杀了重赋值(8 例回退,见\n // `api/dual-form-contract.test.ts`),已废除:线性程序里\"两名同出\"就是重赋值,\n // 是合法的;而当两条语句真的同时存活并引用时,\"当前绑定\"语义本就该取最新。\n\n // ⚠️ 幂等重登记必须**保留已补挂的 evolution**:既然 N3 刻意不比较它,\n // 那它就不是\"本次登记的输入\",重登记时用不带 evolution 的新对象覆盖\n // 等于把先前记录的 hash 演化**静默丢掉**——而丢掉的正是 kernel 类推进 role\n // 所需的全部信息(重新算一遍几何也补不回来,因为演化只在执行那一刻可得)。\n this.nodes.set(stmt, existing?.evolution ? { ...node, evolution: existing.evolution } : node)\n for (const out of node.outputs) this.partOwner.set(out, stmt)\n return this.nodes.get(stmt)!\n }\n\n /**\n * 事后补挂 hash 演化(`kind='kernel'` 用)。\n *\n * 与 `register` 分开是因为演化记录发生在几何算完之后,而登记发生在调用边界;\n * 合成一个操作会让 N3 的\"内容比较\"必须处理\"evolution 可能晚到\"的时序问题。\n *\n * @param stmt - the statement whose evolution to attach.\n * @param evolution - the hash evolution produced by this statement.\n * @throws LineageError when the statement was never registered.\n */\n attachEvolution(stmt: StmtId, evolution: EvolutionRecord): void {\n const node = this.nodes.get(stmt)\n if (!node) {\n throw new LineageError(\n 'E_TOPO_NO_ANCHOR',\n `为未登记的语句 ${stmt} 挂 hash 演化——必须先 register`,\n stmt,\n )\n }\n this.nodes.set(stmt, { ...node, evolution })\n }\n\n /**\n * 按语句 id 取节点。\n *\n * @param stmt - the statement id to look up.\n * @returns the statement's LineageNode, or undefined when not registered.\n */\n node(stmt: StmtId): LineageNode | undefined {\n return this.nodes.get(stmt)\n }\n\n /**\n * 按 part 名反查产出它的语句 id。\n *\n * @param part - the part name to look up.\n * @returns the producing statement id, or undefined when unowned.\n */\n stmtOf(part: PartName): StmtId | undefined {\n return this.partOwner.get(part)\n }\n\n /**\n * 按 part 名反查产出它的节点。\n *\n * @param part - the part name to look up.\n * @returns the producing node, or undefined when unowned.\n */\n nodeOfPart(part: PartName): LineageNode | undefined {\n const stmt = this.partOwner.get(part)\n return stmt === undefined ? undefined : this.nodes.get(stmt)\n }\n\n /**\n * 找把 `part` 作为输入的下游节点(回走推进用,1.10 前置②)。\n *\n * 链行走的方向是「origin → 消费者 → 消费者的消费者」:中间 part 的产出方\n * 是 origin 自己(`stmtOf` 指回原点),不能用产出方找下一步。\n *\n * @param part - the part name consumed by the wanted node.\n * @returns the first (registration-order) node whose inputs contain the part.\n */\n nodeConsuming(part: PartName): LineageNode | undefined {\n for (const node of this.nodes.values()) {\n if (node.inputs.includes(part)) return node\n }\n return undefined\n }\n\n /** 已登记的语句数。 */\n get size(): number {\n return this.nodes.size\n }\n\n /** 清空(每次执行开始时调用——一次执行内 `StmtId` 稳定)。 */\n clear(): void {\n this.nodes.clear()\n this.partOwner.clear()\n this.outputTables.clear()\n this.outputHandles.clear()\n this.outputTablesByPart.clear()\n }\n\n /**\n * 记录语句输出 part 的 roleTable 与句柄(1.10 前置③,执行期旁挂)。\n *\n * 调用点:`define-op.wrapped` 的 brep 分支——登记血缘时(或补挂演化时)\n * 顺手记录,读口是 `getSlot(outShape)`。表/句柄都可选(构造类 op 可能两者皆无)。\n *\n * @param stmt - the statement whose output is recorded.\n * @param roleTable - the output part's role table (origin→role→hash[]), if any.\n * @param solid - the output part's BREP handle, if any.\n * @param part - the output part name to also key the table under (part-key authority), if any.\n */\n recordOutput(stmt: StmtId, roleTable?: ReadonlyMap<string, ReadonlyMap<string, readonly number[]>>, solid?: unknown, part?: PartName): void {\n if (roleTable) this.outputTables.set(stmt, roleTable)\n if (solid !== undefined) this.outputHandles.set(stmt, solid)\n if (roleTable && part !== undefined) this.outputTablesByPart.set(part, roleTable)\n }\n\n /** 读语句输出 part 的 roleTable(回走锚定用)。\n *\n * @param stmt - the statement whose output table to read.\n * @returns the statement-keyed role table, or undefined when none was recorded.\n */\n outputTableOf(stmt: StmtId): ReadonlyMap<string, ReadonlyMap<string, readonly number[]>> | undefined {\n return this.outputTables.get(stmt)\n }\n\n /** 读语句输出 part 的 BREP 句柄(回走 ordinal↔hash 换算用)。\n *\n * @param stmt - the statement whose output handle to read.\n * @returns the statement-keyed BREP handle, or undefined when none was recorded.\n */\n outputHandleOf(stmt: StmtId): unknown | undefined {\n return this.outputHandles.get(stmt)\n }\n\n /**\n * 读 part 名键的 roleTable(op 实现读**输入**表用,1.10 前置③)。\n *\n * 语义 = 旧 `getSlot(input)?.roleTable`:impl 执行时刻,该 part 的表是\n * 上一条语句 `recordOutput` 记录的那份(本语句的覆盖发生在 impl 内\n * fromBrep 时,晚于任何输入读)。未记录(mesh 产物 / 未接血缘)→ undefined。\n *\n * @param part - the output part name whose role table to read.\n * @returns the part-keyed role table, or undefined when not recorded.\n */\n tableOfPart(part: PartName): ReadonlyMap<string, ReadonlyMap<string, readonly number[]>> | undefined {\n return this.outputTablesByPart.get(part)\n }\n}\n\n/**\n * 判断两节点是否\"身份内容\"相同(N3 用;刻意不含 `evolution`)。\n *\n * @param a - the stored node.\n * @param b - the incoming node.\n * @returns true when op / inputs / outputs / provenance all match.\n */\nfunction sameIdentity(a: LineageNode, b: LineageNode): boolean {\n return (\n a.op === b.op &&\n sameNames(a.inputs, b.inputs) &&\n sameNames(a.outputs, b.outputs) &&\n provenanceEquals(a.provenance, b.provenance)\n )\n}\n\n/**\n * 执行期共用的血缘图实例。\n *\n * 唯一性由约束 C1(禁止并发多 runtime)保证;测试请自建 `new LineageGraph()`。\n */\nexport const runtimeLineage = new LineageGraph()\n"]}
1
+ {"version":3,"file":"lineage.js","sourceRoot":"","sources":["../../../src/topology/naming/lineage.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * lineage.ts — 血缘图登记(计划 §4.3)。\n *\n * 每个 op 执行完登记一条 `LineageNode`:**谁(`StmtId`)用什么 op、吃了哪些\n * part、产出哪些 part、属哪个 provenance 类别**。两张表:\n *\n * | 表 | 键 → 值 | 用途 |\n * |---|---|---|\n * | `lineage` | `StmtId` → `LineageNode` | 从身份原点沿 DAG 前进 |\n * | `partToStmt` | `PartName` → `StmtId` | 从 part 名字反查是哪条语句造的 |\n *\n * ## 为什么这一层必须存在\n *\n * 现状把身份表达成 **hash**(`face-evolution.ts` 的内存指针哈希),于是每次查询都在\n * 付「对齐 hash」的利息:谁改了几何,谁的 hash 就变,身份就断。正确形态是\n * `(StmtId, RoleName)` 的**因果坐标**——`StmtId` 说「哪条语句产生」,`RoleName` 说\n * 「那条语句把它当作什么」。因果坐标不随几何变化,**也不需要知道中间过了几个 op**。\n *\n * ## 登记口只能有一个(但调用点有两个)\n *\n * 手写 op 走 `wrapBrepOne`(`define-op.ts`),生成投影走 `compatOp`\n * (`api/internal/compat-op.ts`)——**两条路径都必须登记**,否则 42 条投影永远无名。\n * 但两条路径共用一个 `register()`,规则才只有一处。\n *\n * ## 三条硬规则(这是「未来漏洞最少」的核心)\n *\n * | # | 规则 | 违反时 |\n * |---|---|---|\n * | **N1** | inputs 里任一 Shape 查不到 `PartName` → 报错 | `E_TOPO_UNTRACKED_INPUT` |\n * | **N2** | 当前语句锚点缺失,或与声明的 `stmt` 不符 → 报错 | `E_TOPO_NO_ANCHOR` |\n * | **N3** | 同一 `StmtId` 重复登记且**身份内容**不同 → 报错 | `E_TOPO_DUPLICATE_STMT` |\n *\n * **N1 为什么必须是错误而不是\"默认成链根\"**:op 内部常临时造 Shape(中间产物、\n * 工具件)。若给它们默认一个 origin,「看起来对但语义错」的身份就诞生了——\n * 引用能解析成功,但解析到**别的面**。这类错误不会在测试里暴露(测试用的参数恰好\n * 让两者重合),只会在用户改参数、改尺寸时暴露。**宁可在执行期就炸。**\n *\n * **N2 为什么现在才敢做**:它依赖 `getCurrentStmt()` 是\"当前语句的权威读法\"。\n * 这一点由约束 **C1(禁止并发多 runtime)** 保证(见 §4.7.1)——不是\"全局态凑合能用\"。\n *\n * ## 依赖注入,不读全局\n *\n * `register()` 收一个 `LineageDeps`(`nameOf` / `currentStmt`)而不是 import\n * `runtime-state`。理由有两条:其一,`topology/` 现有模块(如 `roles.ts`)都是\n * \"把依赖当参数\"的风格,读全局会破坏它;其二,N1/N2/N3 的测试不想去摆弄全局态。\n */\n\nimport type { PartName, StmtId } from '../../identity'\nimport type { HashEvolution } from '../../brep/face-evolution'\nimport { type RoleName } from './role-name'\n\n// ── provenance 类别(封闭,计划 §4.4)──\n\n/**\n * 新造面的获取方式(只有 `kernel` / `construct` 需要)。\n *\n * - `byAdjacency`:靠结果形状与输入的**邻接关系**推出哪个面是新造的\n * (布尔/倒角等:新面必然与已知面相邻,而幸存面有自己的坐标)\n * - `explicit`:op 直接给出词汇表(构造类:底面 = profile、侧面 i = 第 i 条边扫掠)\n *\n * ⚠️ **不能靠内核的 `generated` 桶**(Phase 0.4 实测):它与 `modified` 同构分段、\n * 键集相同,值是各输入面派生的**中间形**——`cut` 里 12 个 hash 结果里 0 存活,\n * `fillet`/`fuse` 里整桶为空。故 `byAdjacency` / `explicit` 是**必填**。\n */\nexport type NewFaceRule =\n | { readonly via: 'byAdjacency' }\n | { readonly via: 'explicit'; readonly vocab: readonly RoleName[] }\n\n/**\n * 六个 provenance 类别(计划 §4.4,封闭集)。\n *\n * **继承面的处置完全由类别决定,op 不写**;只有 `construct` 和 `kernel` 会造新面,\n * 才有词汇这一项 ⇒ `identity` / `subdivide` / `replicate(k)` **零声明**。\n *\n * 本表是**类别归属**,不是接线状态(例:`sweep` 属 `construct` 类但未接线,见 §1 D10)。\n */\nexport type Provenance =\n /** 内核给历史:boolean / fillet / chamfer / shell / offset / 刚体变换 */\n | { readonly kind: 'kernel'; readonly newFaces: NewFaceRule }\n /** 输出面 ↔ 输入的构造规则:extrude / revolve / sweep / loft / primitives / sketch / import_brep */\n | { readonly kind: 'construct'; readonly newFaces: Extract<NewFaceRule, { via: 'explicit' }> }\n /** 1:1,第 i 面 → 第 i 面:copy / place / clone / locate / applyMatrix */\n | { readonly kind: 'identity' }\n /** 每输入面 → 若干片:split / section */\n | { readonly kind: 'subdivide' }\n /** 第 k 份第 i 面 ← 第 i 面:linearPattern / circularPattern / gridPattern / rectangularPattern / mirrorJoin */\n | { readonly kind: 'replicate'; readonly k: number }\n /** 显式记账:算不出来。应趋近于 0;审计测试必须列出全部并给出理由 */\n | { readonly kind: 'unmodeled'; readonly reason: string }\n\n/** `Provenance` 的类别标签(封闭六值)。 */\nexport type ProvenanceKind = Provenance['kind']\n\n/** 六个类别标签,供审计测试枚举(新增类别必须同步此处)。 */\nexport const PROVENANCE_KINDS = [\n 'kernel',\n 'construct',\n 'identity',\n 'subdivide',\n 'replicate',\n 'unmodeled',\n] as const\n\n/**\n * 演化记录(`kind='kernel'` 时执行期补挂)。\n *\n * 两种形态并存(1.10 前置①实测):\n * - **序号键**(`slot.faceEvolution` 的实际存储形态,`Map<ordinal, ordinal[]>`):\n * boolean/fillet/chamfer 走 `decodeEvolution`(逐句柄 hashCode),copy/transform/place\n * 走 `identityEvolution`(恒等)。回走推进 identity 类与\"序号不变\"的 kernel 路径用它。\n * - **哈希键**(`HashEvolution`,`decodeHashEvolution` 的输出):只在 booleanWithRoleTable\n * 等组合函数内部瞬时存在,不落 slot。回走按哈希集合推进时用它。\n */\nexport type EvolutionRecord = Map<number, number[]> | HashEvolution\n\n/**\n * 判断演化记录是否为哈希键形态(`HashEvolution` 有 `modified`/`deleted` 字段)。\n *\n * @param e - the evolution record to test.\n * @returns true when the record is the hash-key form (`HashEvolution`).\n */\nexport function isHashEvolution(e: EvolutionRecord): e is HashEvolution {\n return 'modified' in e && 'deleted' in e\n}\n\n/**\n * 血缘图的一个节点 = 一条语句的登记记录。\n *\n * `inputs`/`outputs` 是 `PartName`(不是 Shape):Shape 是执行期的活对象,\n * 身份层必须只留**可序列化、可比较**的东西,否则节点会随 arena 释放而失去意义。\n */\nexport interface LineageNode {\n /** 该语句的 id(`ExecutionAnchor.id`),全局唯一。 */\n readonly stmt: StmtId\n /** op 名(如 `cad.fillet`)——用于报错信息与审计。 */\n readonly op: string\n /** 输入 part 名(`inputs.map(nameOf)` 的结果,已保证全部有名字)。 */\n readonly inputs: readonly PartName[]\n /** 产出 part 名(至少一个)。 */\n readonly outputs: readonly PartName[]\n /** provenance 类别 + 该类别的载荷。 */\n readonly provenance: Provenance\n /** `kind='kernel'` 时执行期记录的 hash 演化(`attachEvolution` 事后补上)。 */\n readonly evolution?: EvolutionRecord\n}\n\n/**\n * 登记入参(尚未解析成 `PartName` 的形态)。\n *\n * `inputs` 故意收 **Shape 句柄**而不是 `PartName`:N1 的判据就是\n * \"这个 Shape 有没有名字\",若调用方先自己 map 成名字,就正好把\n * \"查不到名字\"这一步跳过/默认了——那正是 N1 要防的。\n */\nexport interface LineageDraft {\n /** 声明本条语句的 id(N2 会与当前锚点核对)。 */\n readonly stmt: StmtId\n /** op 名。 */\n readonly op: string\n /** 输入 Shape 句柄(N1 在 register 内解析)。 */\n readonly inputs: readonly object[]\n /** 产出 part 名(非空;调用方从锚点/nameOf 拿到)。 */\n readonly outputs: readonly [PartName, ...PartName[]]\n /** provenance 类别 + 载荷。 */\n readonly provenance: Provenance\n}\n\n/** 登记所需的外部读口(由调用点注入,见文件头「依赖注入」)。 */\nexport interface LineageDeps {\n /** Shape → PartName(`runtime-state` 的 `nameOf`)。 */\n readonly nameOf: (shape: object) => PartName | undefined\n /** 当前执行语句锚点(`runtime-state` 的 `getCurrentStmt`)。 */\n readonly currentStmt: () => { readonly id: string } | undefined\n}\n\n// ── 错误 ──\n\n/** 血缘登记错误码(三条规则 N1/N2/N3)。 */\nexport type LineageErrorCode = 'E_TOPO_UNTRACKED_INPUT' | 'E_TOPO_NO_ANCHOR' | 'E_TOPO_DUPLICATE_STMT'\n\n/** 血缘登记失败。带稳定错误码,禁止静默兜底。 */\nexport class LineageError extends Error {\n /** 稳定错误码(宿主/args 校验按码识别)。 */\n readonly code: LineageErrorCode\n /** 出错的语句 id(若能确定)。 */\n readonly stmt?: string\n\n /**\n * @param code - the stable error code.\n * @param message - what went wrong, with the offending statement named.\n * @param stmt - the statement id, when known.\n */\n constructor(code: LineageErrorCode, message: string, stmt?: string) {\n super(message)\n this.name = 'LineageError'\n this.code = code\n this.stmt = stmt\n }\n}\n\n// ── 结构化比较(不引 node:util——topology/ 要能进浏览器构建)──\n\n/**\n * 两个 `RoleName` 是否相等(按值、递归)。\n *\n * 手写而不是 `JSON.stringify` 比较:键序会随写字面量的顺序变化\n * (`{index, op}` 与 `{op, index}` 是同一个值、不同的 JSON),\n * 而这两个函数是 N3「内容不同才报错」的判据——键序敏感会**误报冲突**。\n *\n * @param a - one role name.\n * @param b - the other role name.\n * @returns true when the two roles are structurally identical.\n */\nexport function roleNameEquals(a: RoleName, b: RoleName): boolean {\n switch (a.kind) {\n case 'semantic':\n return b.kind === 'semantic' && a.name === b.name\n case 'wall':\n return b.kind === 'wall' && a.index === b.index\n case 'imported':\n return b.kind === 'imported' && a.index === b.index\n case 'generated':\n return b.kind === 'generated' && a.op === b.op && a.index === b.index\n case 'hole':\n return b.kind === 'hole' && a.index === b.index && roleNameEquals(a.inner, b.inner)\n case 'replica':\n return b.kind === 'replica' && a.k === b.k && roleNameEquals(a.inner, b.inner)\n case 'splinter':\n return b.kind === 'splinter' && a.index === b.index && roleNameEquals(a.inner, b.inner)\n }\n}\n\n/**\n * 两条新造面规则是否相等(词汇表**逐项按序**比较——顺序是构造语义的一部分:\n * 侧面 i 对应第 i 条 profile 边,重排就是换了一个 role)。\n *\n * @param a - one rule.\n * @param b - the other rule.\n * @returns true when the two rules are structurally identical.\n */\nexport function newFaceRuleEquals(a: NewFaceRule, b: NewFaceRule): boolean {\n if (a.via === 'byAdjacency') return b.via === 'byAdjacency'\n if (b.via !== 'explicit') return false\n if (a.vocab.length !== b.vocab.length) return false\n for (let i = 0; i < a.vocab.length; i++) {\n if (!roleNameEquals(a.vocab[i], b.vocab[i])) return false\n }\n return true\n}\n\n/**\n * 两个 `Provenance` 是否相等(按值)。\n *\n * @param a - one provenance.\n * @param b - the other provenance.\n * @returns true when they are structurally identical.\n */\nexport function provenanceEquals(a: Provenance, b: Provenance): boolean {\n switch (a.kind) {\n case 'identity':\n return b.kind === 'identity'\n case 'subdivide':\n return b.kind === 'subdivide'\n case 'replicate':\n return b.kind === 'replicate' && a.k === b.k\n case 'unmodeled':\n return b.kind === 'unmodeled' && a.reason === b.reason\n case 'kernel':\n return b.kind === 'kernel' && newFaceRuleEquals(a.newFaces, b.newFaces)\n case 'construct':\n return b.kind === 'construct' && newFaceRuleEquals(a.newFaces, b.newFaces)\n }\n}\n\n/** 两个字符串数组是否逐项相等。 */\nfunction sameNames(a: readonly PartName[], b: readonly PartName[]): boolean {\n return a.length === b.length && a.every((x, i) => x === b[i])\n}\n\n// ── 血缘图 ──\n\n/**\n * 血缘图:两张表 + 一个登记函数。\n *\n * 实例化而非全局单例,是为了让 N1/N2/N3 的测试各用各的图、互不污染;\n * 执行期由 `runtime-state` 侧持有唯一实例(C1 保证单 runtime,不存在两图并存)。\n */\nexport class LineageGraph {\n private readonly nodes = new Map<StmtId, LineageNode>()\n private readonly partOwner = new Map<PartName, StmtId>()\n /**\n * 执行期旁挂:语句输出 part 的 roleTable(1.10 前置③)。\n *\n * 回走锚定需要 root 语句的「origin→role→hash[]」表;它本来只存在\n * `slot.roleTable`(解析缓存)里,删字段后唯一落点就是这里。\n * 不进 `LineageNode`(节点是身份数据,N3 比较不含它)。\n */\n private readonly outputTables = new Map<StmtId, ReadonlyMap<string, ReadonlyMap<string, readonly number[]>>>()\n /**\n * 执行期旁挂:语句输出 part 的 BREP 句柄(回走锚定/落地做 ordinal↔hash 换算用)。\n * 句柄是活对象不进节点;随 `clear()` 一起清(句柄生命周期由 solidCache 管)。\n */\n private readonly outputHandles = new Map<StmtId, unknown>()\n /**\n * 执行期旁挂:**part 名键**的 roleTable(1.10 前置③,op 读输入表用)。\n *\n * 为什么有语句键还要 part 键:op 实现读的是「输入 part 的表」。按语句反查\n * (stmtOf(part))在重赋值下会指到**本语句**——register 先于 impl 执行,\n * `part0 = translate(part0)` 的 partOwner 已被 s2 覆盖,impl 读输入表时\n * 拿到的是自己的输出。part 键表只在 `recordOutput`(impl 内 fromBrep 时)\n * 才覆盖 ⇒ impl 读表时看到的仍是上一条语句记录的旧表——时序天然正确。\n */\n private readonly outputTablesByPart = new Map<PartName, ReadonlyMap<string, ReadonlyMap<string, readonly number[]>>>()\n\n /**\n * 登记一条语句(N1/N2/N3 全在这里校验)。\n *\n * @param draft - the statement's lineage facts (inputs still as Shape handles).\n * @param deps - the injected readers (`nameOf` / `currentStmt`).\n * @returns the stored node.\n * @throws LineageError on N1 (untracked input), N2 (anchor mismatch), or N3 (conflicting re-register).\n */\n register(draft: LineageDraft, deps: LineageDeps): LineageNode {\n const stmt = draft.stmt\n\n // N2:当前锚点必须是本条语句,否则说明\"我拿到的 stmt 不是正在跑的那条\"。\n const anchor = deps.currentStmt()\n if (!anchor) {\n throw new LineageError(\n 'E_TOPO_NO_ANCHOR',\n `${draft.op} 登记血缘时无当前语句锚点(getCurrentStmt() 为空)`,\n stmt,\n )\n }\n if (anchor.id !== stmt) {\n throw new LineageError(\n 'E_TOPO_NO_ANCHOR',\n `${draft.op} 声明的语句 ${stmt} 与当前锚点 ${anchor.id} 不符`,\n stmt,\n )\n }\n\n // N1:输入 Shape 必须都有 PartName——**不许默认成链根**。\n const inputs: PartName[] = []\n for (let i = 0; i < draft.inputs.length; i++) {\n const name = deps.nameOf(draft.inputs[i])\n if (name === undefined) {\n throw new LineageError(\n 'E_TOPO_UNTRACKED_INPUT',\n `${draft.op} 的第 ${i} 个输入 Shape 没有 PartName(op 内部临时造的件?)。` +\n `不允许默认成链根——那会产生\"能解析但解析错面\"的假身份。`,\n stmt,\n )\n }\n inputs.push(name)\n }\n\n const node: LineageNode = {\n stmt,\n op: draft.op,\n inputs,\n outputs: [...draft.outputs],\n provenance: draft.provenance,\n }\n\n // N3:同一语句重复登记,若**身份内容**不同即为冲突。\n // 注意比较范围刻意**不含 evolution**:它在执行期事后补(`attachEvolution`),\n // 若纳入比较,第二次登记会因\"上次还没补 evolution\"而误报冲突。\n const existing = this.nodes.get(stmt)\n if (existing && !sameIdentity(existing, node)) {\n throw new LineageError(\n 'E_TOPO_DUPLICATE_STMT',\n `${stmt} 被重复登记且内容不同:` +\n `已登记 ${existing.op}(${existing.inputs.join(',')} → ${existing.outputs.join(',')}, ${existing.provenance.kind}),` +\n `本次为 ${node.op}(${node.inputs.join(',')} → ${node.outputs.join(',')}, ${node.provenance.kind})`,\n stmt,\n )\n }\n\n // PartName → StmtId:反查索引(名字 → 语句)。**最后写者胜**。\n //\n // 重赋值(`part0 = cad.translate(part0, …)`)是 faijs 的合法惯用法:后一条语句\n // 重新绑定同名 PartName,旧绑定随之失效。身份载体是 `(StmtId, RoleName)`,\n // PartName 只是反查索引,故覆盖更新即可——不报错。\n //\n // ⚠️ 曾经这里有一条 `E_TOPO_PART_REDEFINED` 守卫(把\"两名同出\"一律判为\n // \"反查歧义\")。§1.4/1.5 接线后它当场误杀了重赋值(8 例回退,见\n // `api/dual-form-contract.test.ts`),已废除:线性程序里\"两名同出\"就是重赋值,\n // 是合法的;而当两条语句真的同时存活并引用时,\"当前绑定\"语义本就该取最新。\n\n // ⚠️ 幂等重登记必须**保留已补挂的 evolution**:既然 N3 刻意不比较它,\n // 那它就不是\"本次登记的输入\",重登记时用不带 evolution 的新对象覆盖\n // 等于把先前记录的 hash 演化**静默丢掉**——而丢掉的正是 kernel 类推进 role\n // 所需的全部信息(重新算一遍几何也补不回来,因为演化只在执行那一刻可得)。\n this.nodes.set(stmt, existing?.evolution ? { ...node, evolution: existing.evolution } : node)\n for (const out of node.outputs) this.partOwner.set(out, stmt)\n return this.nodes.get(stmt)!\n }\n\n /**\n * 事后补挂 hash 演化(`kind='kernel'` 用)。\n *\n * 与 `register` 分开是因为演化记录发生在几何算完之后,而登记发生在调用边界;\n * 合成一个操作会让 N3 的\"内容比较\"必须处理\"evolution 可能晚到\"的时序问题。\n *\n * @param stmt - the statement whose evolution to attach.\n * @param evolution - the hash evolution produced by this statement.\n * @throws LineageError when the statement was never registered.\n */\n attachEvolution(stmt: StmtId, evolution: EvolutionRecord): void {\n const node = this.nodes.get(stmt)\n if (!node) {\n throw new LineageError(\n 'E_TOPO_NO_ANCHOR',\n `为未登记的语句 ${stmt} 挂 hash 演化——必须先 register`,\n stmt,\n )\n }\n this.nodes.set(stmt, { ...node, evolution })\n }\n\n /**\n * 按语句 id 取节点。\n *\n * @param stmt - the statement id to look up.\n * @returns the statement's LineageNode, or undefined when not registered.\n */\n node(stmt: StmtId): LineageNode | undefined {\n return this.nodes.get(stmt)\n }\n\n /**\n * 按 part 名反查产出它的语句 id。\n *\n * @param part - the part name to look up.\n * @returns the producing statement id, or undefined when unowned.\n */\n stmtOf(part: PartName): StmtId | undefined {\n return this.partOwner.get(part)\n }\n\n /**\n * 按 part 名反查产出它的节点。\n *\n * @param part - the part name to look up.\n * @returns the producing node, or undefined when unowned.\n */\n nodeOfPart(part: PartName): LineageNode | undefined {\n const stmt = this.partOwner.get(part)\n return stmt === undefined ? undefined : this.nodes.get(stmt)\n }\n\n /**\n * 找把 `part` 作为输入的下游节点(回走推进用,1.10 前置②)。\n *\n * 链行走的方向是「origin → 消费者 → 消费者的消费者」:中间 part 的产出方\n * 是 origin 自己(`stmtOf` 指回原点),不能用产出方找下一步。\n *\n * @param part - the part name consumed by the wanted node.\n * @returns the first (registration-order) node whose inputs contain the part.\n */\n nodeConsuming(part: PartName): LineageNode | undefined {\n for (const node of this.nodes.values()) {\n if (node.inputs.includes(part)) return node\n }\n return undefined\n }\n\n /** 已登记的语句数。 */\n get size(): number {\n return this.nodes.size\n }\n\n /**\n * 全部已登记语句 id(回走恢复需遍历候选 origin 时用)。\n *\n * @returns the registered statement ids.\n */\n stmtIds(): StmtId[] {\n return [...this.nodes.keys()]\n }\n\n /** 清空(每次执行开始时调用——一次执行内 `StmtId` 稳定)。 */\n clear(): void {\n this.nodes.clear()\n this.partOwner.clear()\n this.outputTables.clear()\n this.outputHandles.clear()\n this.outputTablesByPart.clear()\n }\n\n /**\n * 记录语句输出 part 的 roleTable 与句柄(1.10 前置③,执行期旁挂)。\n *\n * 调用点:`define-op.wrapped` 的 brep 分支——登记血缘时(或补挂演化时)\n * 顺手记录,读口是 `getSlot(outShape)`。表/句柄都可选(构造类 op 可能两者皆无)。\n *\n * @param stmt - the statement whose output is recorded.\n * @param roleTable - the output part's role table (origin→role→hash[]), if any.\n * @param solid - the output part's BREP handle, if any.\n * @param part - the output part name to also key the table under (part-key authority), if any.\n */\n recordOutput(stmt: StmtId, roleTable?: ReadonlyMap<string, ReadonlyMap<string, readonly number[]>>, solid?: unknown, part?: PartName): void {\n if (roleTable) this.outputTables.set(stmt, roleTable)\n if (solid !== undefined) this.outputHandles.set(stmt, solid)\n if (roleTable && part !== undefined) this.outputTablesByPart.set(part, roleTable)\n }\n\n /** 读语句输出 part 的 roleTable(回走锚定用)。\n *\n * @param stmt - the statement whose output table to read.\n * @returns the statement-keyed role table, or undefined when none was recorded.\n */\n outputTableOf(stmt: StmtId): ReadonlyMap<string, ReadonlyMap<string, readonly number[]>> | undefined {\n return this.outputTables.get(stmt)\n }\n\n /** 读语句输出 part 的 BREP 句柄(回走 ordinal↔hash 换算用)。\n *\n * @param stmt - the statement whose output handle to read.\n * @returns the statement-keyed BREP handle, or undefined when none was recorded.\n */\n outputHandleOf(stmt: StmtId): unknown | undefined {\n return this.outputHandles.get(stmt)\n }\n\n /**\n * 读 part 名键的 roleTable(op 实现读**输入**表用,1.10 前置③)。\n *\n * 语义 = 旧 `getSlot(input)?.roleTable`:impl 执行时刻,该 part 的表是\n * 上一条语句 `recordOutput` 记录的那份(本语句的覆盖发生在 impl 内\n * fromBrep 时,晚于任何输入读)。未记录(mesh 产物 / 未接血缘)→ undefined。\n *\n * @param part - the output part name whose role table to read.\n * @returns the part-keyed role table, or undefined when not recorded.\n */\n tableOfPart(part: PartName): ReadonlyMap<string, ReadonlyMap<string, readonly number[]>> | undefined {\n return this.outputTablesByPart.get(part)\n }\n}\n\n/**\n * 判断两节点是否\"身份内容\"相同(N3 用;刻意不含 `evolution`)。\n *\n * @param a - the stored node.\n * @param b - the incoming node.\n * @returns true when op / inputs / outputs / provenance all match.\n */\nfunction sameIdentity(a: LineageNode, b: LineageNode): boolean {\n return (\n a.op === b.op &&\n sameNames(a.inputs, b.inputs) &&\n sameNames(a.outputs, b.outputs) &&\n provenanceEquals(a.provenance, b.provenance)\n )\n}\n\n/**\n * 执行期共用的血缘图实例。\n *\n * 唯一性由约束 C1(禁止并发多 runtime)保证;测试请自建 `new LineageGraph()`。\n */\nexport const runtimeLineage = new LineageGraph()\n"]}
@@ -14,7 +14,7 @@
14
14
  */
15
15
  import type { BrepHandle } from '../../brep/engine/types.js';
16
16
  import type { EdgeTopoRef, RoleQualifier, TopoResolution } from './types.js';
17
- import { type FaceCandidateEntry, type ResolutionContext } from './resolve-face.js';
17
+ import { type EdgeCandidateEntry, type FaceCandidateEntry, type ResolutionContext } from './resolve-face.js';
18
18
  /**
19
19
  * 解析一个 RoleQualifier 到当前面候选(exact 优先,几何兜底)。
20
20
  *
@@ -23,6 +23,25 @@ import { type FaceCandidateEntry, type ResolutionContext } from './resolve-face.
23
23
  * @returns the face candidates for the role (possibly several after a split).
24
24
  */
25
25
  export declare function facesForQualifier(qualifier: RoleQualifier, ctx: ResolutionContext): FaceCandidateEntry[];
26
+ /**
27
+ * 在候选边集合里按**纯几何** hint(length / midpoint)取最优边。
28
+ *
29
+ * 这是「没有 role 层的边身份」的唯一裁决器,两个消费点共用同一份实现:
30
+ * - `resolveEdgeTopo` 的多公共边裁决与 mesh 降级路径;
31
+ * - 网格实体(近似拓扑)的边解析——那里 `EdgeTopoRef.faces` 只是占位限定符
32
+ * (网格零件没有 role,见 `mesh-primitive.test.ts` 的 Phase 1.8 契约)。
33
+ *
34
+ * 无法区分(最优点与次优点差值 < `HINT_MARGIN`)→ `undefined`,调用方按
35
+ * ambiguous / not-found 如实报错,**绝不**静默拿序号硬取。
36
+ *
37
+ * @param edges - the candidate edges (ordinal + optional handle/hint).
38
+ * @param hint - the edge hint carrying length / midpoint.
39
+ * @returns the best-matching candidate, or undefined when the hint cannot decide.
40
+ */
41
+ export declare function matchEdgeByHint(edges: readonly EdgeCandidateEntry[], hint: EdgeTopoRef['hint']): {
42
+ ordinal: number;
43
+ handle?: BrepHandle;
44
+ } | undefined;
26
45
  /**
27
46
  * 解析边 TopoRef 到当前快照的边序号。
28
47
  *
@@ -1 +1 @@
1
- {"version":3,"file":"resolve-edge.d.ts","sourceRoot":"","sources":["../../../src/topology/naming/resolve-edge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAA;AACzD,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AACzE,OAAO,EAAmB,KAAK,kBAAkB,EAAE,KAAK,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AAajG;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,aAAa,EACxB,GAAG,EAAE,iBAAiB,GACrB,kBAAkB,EAAE,CAgBtB;AAuBD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,WAAW,EAChB,GAAG,EAAE,iBAAiB,GACrB,cAAc,CAAC;IAAE,MAAM,CAAC,EAAE,UAAU,CAAA;CAAE,CAAC,CAwCzC"}
1
+ {"version":3,"file":"resolve-edge.d.ts","sourceRoot":"","sources":["../../../src/topology/naming/resolve-edge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAA;AACzD,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AACzE,OAAO,EAAmB,KAAK,kBAAkB,EAAE,KAAK,kBAAkB,EAAE,KAAK,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AAa1H;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,aAAa,EACxB,GAAG,EAAE,iBAAiB,GACrB,kBAAkB,EAAE,CAgBtB;AAuBD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,SAAS,kBAAkB,EAAE,EACpC,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC,GACxB;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,UAAU,CAAA;CAAE,GAAG,SAAS,CAiBtD;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,WAAW,EAChB,GAAG,EAAE,iBAAiB,GACrB,cAAc,CAAC;IAAE,MAAM,CAAC,EAAE,UAAU,CAAA;CAAE,CAAC,CAsDzC"}