@bldrs-ai/conway 1.389.1221 → 1.394.1504

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 (382) hide show
  1. package/README.md +36 -22
  2. package/compiled/Dist/ConwayGeomWasmNode.js +0 -0
  3. package/compiled/Dist/ConwayGeomWasmNodeMT.js +0 -0
  4. package/compiled/Dist/ConwayGeomWasmWeb.js +0 -0
  5. package/compiled/Dist/ConwayGeomWasmWebMT.js +1 -1
  6. package/compiled/Dist/ConwayGeomWasmWebMT.wasm +0 -0
  7. package/compiled/dependencies/conway-geom/Dist/ConwayGeomWasmNode.js +0 -0
  8. package/compiled/dependencies/conway-geom/Dist/ConwayGeomWasmNodeMT.js +0 -0
  9. package/compiled/dependencies/conway-geom/Dist/ConwayGeomWasmWeb.js +0 -0
  10. package/compiled/dependencies/conway-geom/Dist/ConwayGeomWasmWebMT.js +1 -1
  11. package/compiled/dependencies/conway-geom/Dist/ConwayGeomWasmWebMT.wasm +0 -0
  12. package/compiled/dependencies/conway-geom/interface/conway_geometry.d.ts +19 -0
  13. package/compiled/dependencies/conway-geom/interface/conway_geometry.d.ts.map +1 -1
  14. package/compiled/dependencies/conway-geom/interface/conway_geometry.js +17 -0
  15. package/compiled/dependencies/conway-geom/interface/parameters/surface_object.d.ts +6 -0
  16. package/compiled/dependencies/conway-geom/interface/parameters/surface_object.d.ts.map +1 -1
  17. package/compiled/examples/browser-bundled.cjs +1569 -51
  18. package/compiled/examples/cli-bundled.cjs +2790 -436
  19. package/compiled/examples/cli-step-bundled.cjs +1904 -229
  20. package/compiled/examples/validator-bundled.cjs +1569 -51
  21. package/compiled/src/AP214E3_2010/AP214E3_2010_gen/b_spline_curve.gen.d.ts +2 -2
  22. package/compiled/src/AP214E3_2010/AP214E3_2010_gen/b_spline_curve.gen.d.ts.map +1 -1
  23. package/compiled/src/AP214E3_2010/AP214E3_2010_gen/b_spline_curve.gen.js +2 -2
  24. package/compiled/src/AP214E3_2010/AP214E3_2010_gen/b_spline_surface.gen.d.ts +3 -3
  25. package/compiled/src/AP214E3_2010/AP214E3_2010_gen/b_spline_surface.gen.d.ts.map +1 -1
  26. package/compiled/src/AP214E3_2010/AP214E3_2010_gen/b_spline_surface.gen.js +3 -3
  27. package/compiled/src/AP214E3_2010/AP214E3_2010_gen/composite_curve.gen.d.ts +1 -1
  28. package/compiled/src/AP214E3_2010/AP214E3_2010_gen/composite_curve.gen.d.ts.map +1 -1
  29. package/compiled/src/AP214E3_2010/AP214E3_2010_gen/composite_curve.gen.js +1 -1
  30. package/compiled/src/AP214E3_2010/AP214E3_2010_gen/offset_curve_2d.gen.d.ts +1 -1
  31. package/compiled/src/AP214E3_2010/AP214E3_2010_gen/offset_curve_2d.gen.d.ts.map +1 -1
  32. package/compiled/src/AP214E3_2010/AP214E3_2010_gen/offset_curve_2d.gen.js +1 -1
  33. package/compiled/src/AP214E3_2010/AP214E3_2010_gen/offset_curve_3d.gen.d.ts +1 -1
  34. package/compiled/src/AP214E3_2010/AP214E3_2010_gen/offset_curve_3d.gen.d.ts.map +1 -1
  35. package/compiled/src/AP214E3_2010/AP214E3_2010_gen/offset_curve_3d.gen.js +1 -1
  36. package/compiled/src/AP214E3_2010/AP214E3_2010_gen/offset_surface.gen.d.ts +1 -1
  37. package/compiled/src/AP214E3_2010/AP214E3_2010_gen/offset_surface.gen.d.ts.map +1 -1
  38. package/compiled/src/AP214E3_2010/AP214E3_2010_gen/offset_surface.gen.js +1 -1
  39. package/compiled/src/AP214E3_2010/AP214E3_2010_gen/presentation_style_assignment.gen.d.ts.map +1 -1
  40. package/compiled/src/AP214E3_2010/AP214E3_2010_gen/presentation_style_assignment.gen.js +2 -2
  41. package/compiled/src/AP214E3_2010/AP214E3_2010_gen/schema_ap214.gen.js +11 -11
  42. package/compiled/src/AP214E3_2010/AP214E3_2010_gen/shape_aspect.gen.d.ts +1 -1
  43. package/compiled/src/AP214E3_2010/AP214E3_2010_gen/shape_aspect.gen.d.ts.map +1 -1
  44. package/compiled/src/AP214E3_2010/AP214E3_2010_gen/shape_aspect.gen.js +1 -1
  45. package/compiled/src/AP214E3_2010/ap214_command_line_main.js +7 -3
  46. package/compiled/src/AP214E3_2010/ap214_geometry_extraction.d.ts +181 -7
  47. package/compiled/src/AP214E3_2010/ap214_geometry_extraction.d.ts.map +1 -1
  48. package/compiled/src/AP214E3_2010/ap214_geometry_extraction.js +906 -137
  49. package/compiled/src/AP214E3_2010/ap214_geometry_extraction.test.js +10 -2
  50. package/compiled/src/AP214E3_2010/ap214_logical_attribute.test.d.ts +2 -0
  51. package/compiled/src/AP214E3_2010/ap214_logical_attribute.test.d.ts.map +1 -0
  52. package/compiled/src/AP214E3_2010/ap214_logical_attribute.test.js +114 -0
  53. package/compiled/src/AP214E3_2010/ap214_model_geometry.d.ts +6 -0
  54. package/compiled/src/AP214E3_2010/ap214_model_geometry.d.ts.map +1 -1
  55. package/compiled/src/AP214E3_2010/ap214_model_geometry.js +9 -0
  56. package/compiled/src/AP214E3_2010/ap214_pcurve_basis_surfaces.test.d.ts +2 -0
  57. package/compiled/src/AP214E3_2010/ap214_pcurve_basis_surfaces.test.d.ts.map +1 -0
  58. package/compiled/src/AP214E3_2010/ap214_pcurve_basis_surfaces.test.js +233 -0
  59. package/compiled/src/AP214E3_2010/ap214_sphere_vertex_loop.test.d.ts +2 -0
  60. package/compiled/src/AP214E3_2010/ap214_sphere_vertex_loop.test.d.ts.map +1 -0
  61. package/compiled/src/AP214E3_2010/ap214_sphere_vertex_loop.test.js +147 -0
  62. package/compiled/src/AP214E3_2010/ap214_step_model.d.ts +2 -1
  63. package/compiled/src/AP214E3_2010/ap214_step_model.d.ts.map +1 -1
  64. package/compiled/src/AP214E3_2010/ap214_step_model.js +1 -1
  65. package/compiled/src/AP214E3_2010/ap214_typed_select_enum.test.d.ts +2 -0
  66. package/compiled/src/AP214E3_2010/ap214_typed_select_enum.test.d.ts.map +1 -0
  67. package/compiled/src/AP214E3_2010/ap214_typed_select_enum.test.js +65 -0
  68. package/compiled/src/AP214E3_2010/ap214_unit_scale.test.d.ts +2 -0
  69. package/compiled/src/AP214E3_2010/ap214_unit_scale.test.d.ts.map +1 -0
  70. package/compiled/src/AP214E3_2010/ap214_unit_scale.test.js +111 -0
  71. package/compiled/src/compat/web-ifc/ap214_streamed_open.test.d.ts +2 -0
  72. package/compiled/src/compat/web-ifc/ap214_streamed_open.test.d.ts.map +1 -0
  73. package/compiled/src/compat/web-ifc/ap214_streamed_open.test.js +190 -0
  74. package/compiled/src/compat/web-ifc/coordination_export_order.test.d.ts +2 -0
  75. package/compiled/src/compat/web-ifc/coordination_export_order.test.d.ts.map +1 -0
  76. package/compiled/src/compat/web-ifc/coordination_export_order.test.js +110 -0
  77. package/compiled/src/compat/web-ifc/coordination_f64.d.ts +165 -0
  78. package/compiled/src/compat/web-ifc/coordination_f64.d.ts.map +1 -0
  79. package/compiled/src/compat/web-ifc/coordination_f64.js +286 -0
  80. package/compiled/src/compat/web-ifc/coordination_f64.test.d.ts +2 -0
  81. package/compiled/src/compat/web-ifc/coordination_f64.test.d.ts.map +1 -0
  82. package/compiled/src/compat/web-ifc/coordination_f64.test.js +225 -0
  83. package/compiled/src/compat/web-ifc/ifc_api.d.ts +154 -0
  84. package/compiled/src/compat/web-ifc/ifc_api.d.ts.map +1 -1
  85. package/compiled/src/compat/web-ifc/ifc_api.js +211 -3
  86. package/compiled/src/compat/web-ifc/ifc_api_deferred_open.test.d.ts +2 -0
  87. package/compiled/src/compat/web-ifc/ifc_api_deferred_open.test.d.ts.map +1 -0
  88. package/compiled/src/compat/web-ifc/ifc_api_deferred_open.test.js +288 -0
  89. package/compiled/src/compat/web-ifc/ifc_api_model_passthrough.d.ts +39 -0
  90. package/compiled/src/compat/web-ifc/ifc_api_model_passthrough.d.ts.map +1 -1
  91. package/compiled/src/compat/web-ifc/ifc_api_model_passthrough_factory.d.ts +30 -0
  92. package/compiled/src/compat/web-ifc/ifc_api_model_passthrough_factory.d.ts.map +1 -1
  93. package/compiled/src/compat/web-ifc/ifc_api_model_passthrough_factory.js +83 -0
  94. package/compiled/src/compat/web-ifc/ifc_api_preview_channel.test.d.ts +2 -0
  95. package/compiled/src/compat/web-ifc/ifc_api_preview_channel.test.d.ts.map +1 -0
  96. package/compiled/src/compat/web-ifc/ifc_api_preview_channel.test.js +383 -0
  97. package/compiled/src/compat/web-ifc/ifc_api_preview_coordination.test.d.ts +2 -0
  98. package/compiled/src/compat/web-ifc/ifc_api_preview_coordination.test.d.ts.map +1 -0
  99. package/compiled/src/compat/web-ifc/ifc_api_preview_coordination.test.js +124 -0
  100. package/compiled/src/compat/web-ifc/ifc_api_proxy_ap214.d.ts +132 -0
  101. package/compiled/src/compat/web-ifc/ifc_api_proxy_ap214.d.ts.map +1 -1
  102. package/compiled/src/compat/web-ifc/ifc_api_proxy_ap214.js +488 -92
  103. package/compiled/src/compat/web-ifc/ifc_api_proxy_ifc.d.ts +268 -0
  104. package/compiled/src/compat/web-ifc/ifc_api_proxy_ifc.d.ts.map +1 -1
  105. package/compiled/src/compat/web-ifc/ifc_api_proxy_ifc.js +996 -149
  106. package/compiled/src/compat/web-ifc/ifc_api_streamed_open.test.d.ts +2 -0
  107. package/compiled/src/compat/web-ifc/ifc_api_streamed_open.test.d.ts.map +1 -0
  108. package/compiled/src/compat/web-ifc/ifc_api_streamed_open.test.js +129 -0
  109. package/compiled/src/compat/web-ifc/spatial_imposter.d.ts +134 -0
  110. package/compiled/src/compat/web-ifc/spatial_imposter.d.ts.map +1 -0
  111. package/compiled/src/compat/web-ifc/spatial_imposter.js +933 -0
  112. package/compiled/src/compat/web-ifc/spatial_imposter.test.d.ts +2 -0
  113. package/compiled/src/compat/web-ifc/spatial_imposter.test.d.ts.map +1 -0
  114. package/compiled/src/compat/web-ifc/spatial_imposter.test.js +467 -0
  115. package/compiled/src/compat/web-ifc/store_preview_channel.d.ts +187 -0
  116. package/compiled/src/compat/web-ifc/store_preview_channel.d.ts.map +1 -0
  117. package/compiled/src/compat/web-ifc/store_preview_channel.js +524 -0
  118. package/compiled/src/compat/web-ifc/store_preview_channel.test.d.ts +2 -0
  119. package/compiled/src/compat/web-ifc/store_preview_channel.test.d.ts.map +1 -0
  120. package/compiled/src/compat/web-ifc/store_preview_channel.test.js +234 -0
  121. package/compiled/src/compat/web-ifc/streamed_preview_channel.d.ts +306 -0
  122. package/compiled/src/compat/web-ifc/streamed_preview_channel.d.ts.map +1 -0
  123. package/compiled/src/compat/web-ifc/streamed_preview_channel.js +580 -0
  124. package/compiled/src/compat/web-ifc/web_wasm_directory.test.d.ts +2 -0
  125. package/compiled/src/compat/web-ifc/web_wasm_directory.test.d.ts.map +1 -0
  126. package/compiled/src/compat/web-ifc/web_wasm_directory.test.js +22 -0
  127. package/compiled/src/core/composed_model_skeleton.d.ts +63 -0
  128. package/compiled/src/core/composed_model_skeleton.d.ts.map +1 -0
  129. package/compiled/src/core/composed_model_skeleton.js +66 -0
  130. package/compiled/src/core/composed_model_skeleton.test.d.ts +2 -0
  131. package/compiled/src/core/composed_model_skeleton.test.d.ts.map +1 -0
  132. package/compiled/src/core/composed_model_skeleton.test.js +69 -0
  133. package/compiled/src/core/demand_geometry_queue.d.ts +147 -0
  134. package/compiled/src/core/demand_geometry_queue.d.ts.map +1 -0
  135. package/compiled/src/core/demand_geometry_queue.js +223 -0
  136. package/compiled/src/core/demand_geometry_queue.test.d.ts +2 -0
  137. package/compiled/src/core/demand_geometry_queue.test.d.ts.map +1 -0
  138. package/compiled/src/core/demand_geometry_queue.test.js +133 -0
  139. package/compiled/src/core/demand_residency_pump.d.ts +93 -0
  140. package/compiled/src/core/demand_residency_pump.d.ts.map +1 -0
  141. package/compiled/src/core/demand_residency_pump.js +120 -0
  142. package/compiled/src/core/demand_residency_pump.test.d.ts +2 -0
  143. package/compiled/src/core/demand_residency_pump.test.d.ts.map +1 -0
  144. package/compiled/src/core/demand_residency_pump.test.js +148 -0
  145. package/compiled/src/core/geometry_tile_bindings.d.ts +110 -0
  146. package/compiled/src/core/geometry_tile_bindings.d.ts.map +1 -0
  147. package/compiled/src/core/geometry_tile_bindings.js +76 -0
  148. package/compiled/src/core/geometry_tile_bindings.test.d.ts +2 -0
  149. package/compiled/src/core/geometry_tile_bindings.test.d.ts.map +1 -0
  150. package/compiled/src/core/geometry_tile_bindings.test.js +211 -0
  151. package/compiled/src/core/geometry_tile_pool.d.ts +99 -0
  152. package/compiled/src/core/geometry_tile_pool.d.ts.map +1 -0
  153. package/compiled/src/core/geometry_tile_pool.js +104 -0
  154. package/compiled/src/core/geometry_tile_pool.test.d.ts +2 -0
  155. package/compiled/src/core/geometry_tile_pool.test.d.ts.map +1 -0
  156. package/compiled/src/core/geometry_tile_pool.test.js +180 -0
  157. package/compiled/src/core/mem/chunked_pool.d.ts +116 -0
  158. package/compiled/src/core/mem/chunked_pool.d.ts.map +1 -0
  159. package/compiled/src/core/mem/chunked_pool.js +149 -0
  160. package/compiled/src/core/mem/chunked_pool.test.d.ts +2 -0
  161. package/compiled/src/core/mem/chunked_pool.test.d.ts.map +1 -0
  162. package/compiled/src/core/mem/chunked_pool.test.js +63 -0
  163. package/compiled/src/core/mem/shared_asset_pool.d.ts +82 -0
  164. package/compiled/src/core/mem/shared_asset_pool.d.ts.map +1 -0
  165. package/compiled/src/core/mem/shared_asset_pool.js +113 -0
  166. package/compiled/src/core/mem/shared_asset_pool.test.d.ts +2 -0
  167. package/compiled/src/core/mem/shared_asset_pool.test.d.ts.map +1 -0
  168. package/compiled/src/core/mem/shared_asset_pool.test.js +49 -0
  169. package/compiled/src/core/model_registry.d.ts +87 -0
  170. package/compiled/src/core/model_registry.d.ts.map +1 -0
  171. package/compiled/src/core/model_registry.js +101 -0
  172. package/compiled/src/core/model_registry.test.d.ts +2 -0
  173. package/compiled/src/core/model_registry.test.d.ts.map +1 -0
  174. package/compiled/src/core/model_registry.test.js +60 -0
  175. package/compiled/src/core/model_uri.d.ts +57 -0
  176. package/compiled/src/core/model_uri.d.ts.map +1 -0
  177. package/compiled/src/core/model_uri.js +101 -0
  178. package/compiled/src/core/model_uri.test.d.ts +2 -0
  179. package/compiled/src/core/model_uri.test.d.ts.map +1 -0
  180. package/compiled/src/core/model_uri.test.js +49 -0
  181. package/compiled/src/core/progress.d.ts +16 -2
  182. package/compiled/src/core/progress.d.ts.map +1 -1
  183. package/compiled/src/core/progress.js +31 -5
  184. package/compiled/src/core/progress.test.js +11 -2
  185. package/compiled/src/core/progress_log.d.ts +1 -0
  186. package/compiled/src/core/progress_log.d.ts.map +1 -1
  187. package/compiled/src/core/progress_log.js +7 -2
  188. package/compiled/src/core/progress_log.test.js +21 -0
  189. package/compiled/src/core/shared_byte_budget.d.ts +60 -0
  190. package/compiled/src/core/shared_byte_budget.d.ts.map +1 -0
  191. package/compiled/src/core/shared_byte_budget.js +85 -0
  192. package/compiled/src/core/shared_byte_budget.test.d.ts +2 -0
  193. package/compiled/src/core/shared_byte_budget.test.d.ts.map +1 -0
  194. package/compiled/src/core/shared_byte_budget.test.js +55 -0
  195. package/compiled/src/core/wasm_heap.d.ts +208 -0
  196. package/compiled/src/core/wasm_heap.d.ts.map +1 -0
  197. package/compiled/src/core/wasm_heap.js +417 -0
  198. package/compiled/src/core/wasm_heap.test.d.ts +2 -0
  199. package/compiled/src/core/wasm_heap.test.d.ts.map +1 -0
  200. package/compiled/src/core/wasm_heap.test.js +546 -0
  201. package/compiled/src/demand/index.d.ts +23 -0
  202. package/compiled/src/demand/index.d.ts.map +1 -0
  203. package/compiled/src/demand/index.js +22 -0
  204. package/compiled/src/ifc/ifc4_gen/IfcLogical.gen.d.ts +1 -1
  205. package/compiled/src/ifc/ifc4_gen/IfcLogical.gen.d.ts.map +1 -1
  206. package/compiled/src/ifc/ifc4_gen/IfcLogical.gen.js +1 -1
  207. package/compiled/src/ifc/ifc4_gen/IfcPresentationStyleAssignment.gen.d.ts.map +1 -1
  208. package/compiled/src/ifc/ifc4_gen/IfcPresentationStyleAssignment.gen.js +2 -2
  209. package/compiled/src/ifc/ifc4_gen/IfcRelInterferesElements.gen.d.ts +1 -1
  210. package/compiled/src/ifc/ifc4_gen/IfcRelInterferesElements.gen.d.ts.map +1 -1
  211. package/compiled/src/ifc/ifc4_gen/IfcRelInterferesElements.gen.js +1 -1
  212. package/compiled/src/ifc/ifc4_gen/schema_ifc.gen.js +2 -2
  213. package/compiled/src/ifc/ifc_demand_extraction.test.d.ts +2 -0
  214. package/compiled/src/ifc/ifc_demand_extraction.test.d.ts.map +1 -0
  215. package/compiled/src/ifc/ifc_demand_extraction.test.js +251 -0
  216. package/compiled/src/ifc/ifc_geometry_extraction.d.ts +367 -6
  217. package/compiled/src/ifc/ifc_geometry_extraction.d.ts.map +1 -1
  218. package/compiled/src/ifc/ifc_geometry_extraction.js +1322 -389
  219. package/compiled/src/ifc/ifc_grid_placement.test.d.ts +2 -0
  220. package/compiled/src/ifc/ifc_grid_placement.test.d.ts.map +1 -0
  221. package/compiled/src/ifc/ifc_grid_placement.test.js +261 -0
  222. package/compiled/src/ifc/ifc_model_geometry.d.ts +12 -0
  223. package/compiled/src/ifc/ifc_model_geometry.d.ts.map +1 -1
  224. package/compiled/src/ifc/ifc_model_geometry.js +15 -0
  225. package/compiled/src/ifc/ifc_regression_batch_main.js +210 -12
  226. package/compiled/src/ifc/ifc_spatial_skeleton.d.ts +145 -0
  227. package/compiled/src/ifc/ifc_spatial_skeleton.d.ts.map +1 -0
  228. package/compiled/src/ifc/ifc_spatial_skeleton.js +266 -0
  229. package/compiled/src/ifc/ifc_spatial_skeleton.test.d.ts +2 -0
  230. package/compiled/src/ifc/ifc_spatial_skeleton.test.d.ts.map +1 -0
  231. package/compiled/src/ifc/ifc_spatial_skeleton.test.js +199 -0
  232. package/compiled/src/ifc/ifc_step_model.d.ts +6 -2
  233. package/compiled/src/ifc/ifc_step_model.d.ts.map +1 -1
  234. package/compiled/src/ifc/ifc_step_model.js +6 -4
  235. package/compiled/src/ifc/ifc_step_parser.d.ts +58 -0
  236. package/compiled/src/ifc/ifc_step_parser.d.ts.map +1 -1
  237. package/compiled/src/ifc/ifc_step_parser.js +64 -0
  238. package/compiled/src/ifc/ifc_stream_model.test.d.ts +2 -0
  239. package/compiled/src/ifc/ifc_stream_model.test.d.ts.map +1 -0
  240. package/compiled/src/ifc/ifc_stream_model.test.js +70 -0
  241. package/compiled/src/ifc/ifc_stream_open.d.ts +131 -0
  242. package/compiled/src/ifc/ifc_stream_open.d.ts.map +1 -0
  243. package/compiled/src/ifc/ifc_stream_open.js +116 -0
  244. package/compiled/src/ifc/ifc_stream_open.test.d.ts +2 -0
  245. package/compiled/src/ifc/ifc_stream_open.test.d.ts.map +1 -0
  246. package/compiled/src/ifc/ifc_stream_open.test.js +230 -0
  247. package/compiled/src/ifc/ifc_tile_extractor.d.ts +84 -0
  248. package/compiled/src/ifc/ifc_tile_extractor.d.ts.map +1 -0
  249. package/compiled/src/ifc/ifc_tile_extractor.js +134 -0
  250. package/compiled/src/ifc/ifc_tile_extractor.test.d.ts +2 -0
  251. package/compiled/src/ifc/ifc_tile_extractor.test.d.ts.map +1 -0
  252. package/compiled/src/ifc/ifc_tile_extractor.test.js +118 -0
  253. package/compiled/src/ifc/ifc_typed_select_enum.test.d.ts +2 -0
  254. package/compiled/src/ifc/ifc_typed_select_enum.test.d.ts.map +1 -0
  255. package/compiled/src/ifc/ifc_typed_select_enum.test.js +60 -0
  256. package/compiled/src/index.d.ts +21 -1
  257. package/compiled/src/index.d.ts.map +1 -1
  258. package/compiled/src/index.js +28 -1
  259. package/compiled/src/logging/logger.d.ts +16 -2
  260. package/compiled/src/logging/logger.d.ts.map +1 -1
  261. package/compiled/src/logging/logger.js +34 -7
  262. package/compiled/src/logging/logger.test.js +30 -0
  263. package/compiled/src/mem/index.d.ts +17 -0
  264. package/compiled/src/mem/index.d.ts.map +1 -0
  265. package/compiled/src/mem/index.js +16 -0
  266. package/compiled/src/namespace_surface.test.d.ts +2 -0
  267. package/compiled/src/namespace_surface.test.d.ts.map +1 -0
  268. package/compiled/src/namespace_surface.test.js +43 -0
  269. package/compiled/src/parsing/parsing_buffer.d.ts +23 -0
  270. package/compiled/src/parsing/parsing_buffer.d.ts.map +1 -1
  271. package/compiled/src/parsing/parsing_buffer.js +31 -0
  272. package/compiled/src/scripts/model_report_displacement.test.d.ts +2 -0
  273. package/compiled/src/scripts/model_report_displacement.test.d.ts.map +1 -0
  274. package/compiled/src/scripts/model_report_displacement.test.js +104 -0
  275. package/compiled/src/scripts/render_glb_paths.test.d.ts +2 -0
  276. package/compiled/src/scripts/render_glb_paths.test.d.ts.map +1 -0
  277. package/compiled/src/scripts/render_glb_paths.test.js +115 -0
  278. package/compiled/src/step/indexing/step_type_indexer.d.ts +20 -0
  279. package/compiled/src/step/indexing/step_type_indexer.d.ts.map +1 -1
  280. package/compiled/src/step/indexing/step_type_indexer.js +67 -0
  281. package/compiled/src/step/parsing/byte_source.d.ts +153 -0
  282. package/compiled/src/step/parsing/byte_source.d.ts.map +1 -0
  283. package/compiled/src/step/parsing/byte_source.js +106 -0
  284. package/compiled/src/step/parsing/byte_source.test.d.ts +2 -0
  285. package/compiled/src/step/parsing/byte_source.test.d.ts.map +1 -0
  286. package/compiled/src/step/parsing/byte_source.test.js +47 -0
  287. package/compiled/src/step/parsing/byte_source_node.d.ts +41 -0
  288. package/compiled/src/step/parsing/byte_source_node.d.ts.map +1 -0
  289. package/compiled/src/step/parsing/byte_source_node.js +54 -0
  290. package/compiled/src/step/parsing/columnar_index.d.ts +103 -0
  291. package/compiled/src/step/parsing/columnar_index.d.ts.map +1 -0
  292. package/compiled/src/step/parsing/columnar_index.js +224 -0
  293. package/compiled/src/step/parsing/columnar_index.test.d.ts +2 -0
  294. package/compiled/src/step/parsing/columnar_index.test.d.ts.map +1 -0
  295. package/compiled/src/step/parsing/columnar_index.test.js +155 -0
  296. package/compiled/src/step/parsing/cross_reference_registry.d.ts +95 -0
  297. package/compiled/src/step/parsing/cross_reference_registry.d.ts.map +1 -0
  298. package/compiled/src/step/parsing/cross_reference_registry.js +91 -0
  299. package/compiled/src/step/parsing/cross_reference_registry.test.d.ts +2 -0
  300. package/compiled/src/step/parsing/cross_reference_registry.test.d.ts.map +1 -0
  301. package/compiled/src/step/parsing/cross_reference_registry.test.js +66 -0
  302. package/compiled/src/step/parsing/decode_utf8.d.ts +15 -0
  303. package/compiled/src/step/parsing/decode_utf8.d.ts.map +1 -1
  304. package/compiled/src/step/parsing/decode_utf8.js +28 -0
  305. package/compiled/src/step/parsing/express_ref_scan.d.ts +20 -0
  306. package/compiled/src/step/parsing/express_ref_scan.d.ts.map +1 -0
  307. package/compiled/src/step/parsing/express_ref_scan.js +91 -0
  308. package/compiled/src/step/parsing/express_ref_scan.test.d.ts +2 -0
  309. package/compiled/src/step/parsing/express_ref_scan.test.d.ts.map +1 -0
  310. package/compiled/src/step/parsing/express_ref_scan.test.js +28 -0
  311. package/compiled/src/step/parsing/index_sidecar.d.ts +81 -0
  312. package/compiled/src/step/parsing/index_sidecar.d.ts.map +1 -0
  313. package/compiled/src/step/parsing/index_sidecar.js +283 -0
  314. package/compiled/src/step/parsing/index_sidecar.test.d.ts +2 -0
  315. package/compiled/src/step/parsing/index_sidecar.test.d.ts.map +1 -0
  316. package/compiled/src/step/parsing/index_sidecar.test.js +122 -0
  317. package/compiled/src/step/parsing/inf_recovery_index.test.d.ts +2 -0
  318. package/compiled/src/step/parsing/inf_recovery_index.test.d.ts.map +1 -0
  319. package/compiled/src/step/parsing/inf_recovery_index.test.js +108 -0
  320. package/compiled/src/step/parsing/prefix_type_index.d.ts +124 -0
  321. package/compiled/src/step/parsing/prefix_type_index.d.ts.map +1 -0
  322. package/compiled/src/step/parsing/prefix_type_index.js +207 -0
  323. package/compiled/src/step/parsing/prefix_type_index.test.d.ts +2 -0
  324. package/compiled/src/step/parsing/prefix_type_index.test.d.ts.map +1 -0
  325. package/compiled/src/step/parsing/prefix_type_index.test.js +298 -0
  326. package/compiled/src/step/parsing/range_byte_source.d.ts +69 -0
  327. package/compiled/src/step/parsing/range_byte_source.d.ts.map +1 -0
  328. package/compiled/src/step/parsing/range_byte_source.js +78 -0
  329. package/compiled/src/step/parsing/range_byte_source.test.d.ts +2 -0
  330. package/compiled/src/step/parsing/range_byte_source.test.d.ts.map +1 -0
  331. package/compiled/src/step/parsing/range_byte_source.test.js +70 -0
  332. package/compiled/src/step/parsing/record_event.d.ts +23 -0
  333. package/compiled/src/step/parsing/record_event.d.ts.map +1 -0
  334. package/compiled/src/step/parsing/record_event.js +1 -0
  335. package/compiled/src/step/parsing/record_field_cursor.d.ts +94 -0
  336. package/compiled/src/step/parsing/record_field_cursor.d.ts.map +1 -0
  337. package/compiled/src/step/parsing/record_field_cursor.js +189 -0
  338. package/compiled/src/step/parsing/step_deserialization_functions.d.ts +29 -0
  339. package/compiled/src/step/parsing/step_deserialization_functions.d.ts.map +1 -1
  340. package/compiled/src/step/parsing/step_deserialization_functions.js +45 -0
  341. package/compiled/src/step/parsing/step_deserialization_functions.test.js +59 -1
  342. package/compiled/src/step/parsing/step_parser.d.ts +66 -1
  343. package/compiled/src/step/parsing/step_parser.d.ts.map +1 -1
  344. package/compiled/src/step/parsing/step_parser.js +164 -10
  345. package/compiled/src/step/parsing/step_string_parser.js +8 -8
  346. package/compiled/src/step/parsing/streaming_index_builder.d.ts +141 -0
  347. package/compiled/src/step/parsing/streaming_index_builder.d.ts.map +1 -0
  348. package/compiled/src/step/parsing/streaming_index_builder.js +280 -0
  349. package/compiled/src/step/parsing/streaming_index_builder.test.d.ts +2 -0
  350. package/compiled/src/step/parsing/streaming_index_builder.test.d.ts.map +1 -0
  351. package/compiled/src/step/parsing/streaming_index_builder.test.js +107 -0
  352. package/compiled/src/step/parsing/streaming_index_builder_async.test.d.ts +2 -0
  353. package/compiled/src/step/parsing/streaming_index_builder_async.test.d.ts.map +1 -0
  354. package/compiled/src/step/parsing/streaming_index_builder_async.test.js +109 -0
  355. package/compiled/src/step/parsing/streaming_record_dispatcher.d.ts +71 -0
  356. package/compiled/src/step/parsing/streaming_record_dispatcher.d.ts.map +1 -0
  357. package/compiled/src/step/parsing/streaming_record_dispatcher.js +88 -0
  358. package/compiled/src/step/parsing/streaming_record_dispatcher.test.d.ts +2 -0
  359. package/compiled/src/step/parsing/streaming_record_dispatcher.test.d.ts.map +1 -0
  360. package/compiled/src/step/parsing/streaming_record_dispatcher.test.js +66 -0
  361. package/compiled/src/step/parsing/uint32_sink.d.ts +72 -0
  362. package/compiled/src/step/parsing/uint32_sink.d.ts.map +1 -0
  363. package/compiled/src/step/parsing/uint32_sink.js +180 -0
  364. package/compiled/src/step/parsing/uint32_sink.test.d.ts +2 -0
  365. package/compiled/src/step/parsing/uint32_sink.test.d.ts.map +1 -0
  366. package/compiled/src/step/parsing/uint32_sink.test.js +199 -0
  367. package/compiled/src/step/step_buffer_provider.d.ts +48 -3
  368. package/compiled/src/step/step_buffer_provider.d.ts.map +1 -1
  369. package/compiled/src/step/step_buffer_provider.js +60 -11
  370. package/compiled/src/step/step_buffer_provider.test.js +14 -0
  371. package/compiled/src/step/step_entity_base.d.ts +65 -3
  372. package/compiled/src/step/step_entity_base.d.ts.map +1 -1
  373. package/compiled/src/step/step_entity_base.js +135 -3
  374. package/compiled/src/step/step_model_base.d.ts +221 -8
  375. package/compiled/src/step/step_model_base.d.ts.map +1 -1
  376. package/compiled/src/step/step_model_base.js +542 -7
  377. package/compiled/src/stream/index.d.ts +34 -0
  378. package/compiled/src/stream/index.d.ts.map +1 -0
  379. package/compiled/src/stream/index.js +32 -0
  380. package/compiled/src/version/version.js +1 -1
  381. package/compiled/tsconfig.tsbuildinfo +1 -1
  382. package/package.json +16 -1
@@ -44,8 +44,18 @@ async function safeExecWithCancellation(command, timeoutMs) {
44
44
  });
45
45
  // Set up the timeout promise.
46
46
  const timeoutHandle = setTimeout(() => {
47
- // Timeout occurred: kill the child process.
48
- child.kill();
47
+ // Timeout occurred: SIGKILL (not the default SIGTERM) so a child stuck
48
+ // in a wasm compute loop is force-killed. A model exceeding the timeout
49
+ // is not expected once batch concurrency is bounded — this is a safety
50
+ // net. The explicit process.exit at the end of the run guarantees the
51
+ // batch still terminates promptly even if a killed child leaves a
52
+ // grandchild behind holding an open pipe.
53
+ try {
54
+ child.kill('SIGKILL');
55
+ }
56
+ catch {
57
+ // Already gone.
58
+ }
49
59
  resolve({
50
60
  type: 'Failed',
51
61
  name: 'TimeoutError',
@@ -78,6 +88,39 @@ function csvSafeString(from) {
78
88
  }
79
89
  return from;
80
90
  }
91
+ /**
92
+ * Read back the first field of a line written with csvSafeString.
93
+ *
94
+ * Naive `line.split(',')[0]` is wrong for exactly the inputs csvSafeString
95
+ * exists for: a model filename containing a comma comes back quoted, and
96
+ * splitting on ',' truncates it mid-name. The zero-geometry collision check
97
+ * keys on this field, so a truncated name silently changes which stems it
98
+ * thinks collide.
99
+ *
100
+ * @param line A CSV line whose first field was written by csvSafeString.
101
+ * @return {string} The unescaped first field.
102
+ */
103
+ function csvFirstField(line) {
104
+ const trimmed = line.replace(/[\r\n]+$/, '');
105
+ if (!trimmed.startsWith('"')) {
106
+ return trimmed.split(',')[0];
107
+ }
108
+ let result = '';
109
+ for (let cursor = 1; cursor < trimmed.length; ++cursor) {
110
+ if (trimmed[cursor] !== '"') {
111
+ result += trimmed[cursor];
112
+ continue;
113
+ }
114
+ // A doubled quote is a literal one; a lone quote closes the field.
115
+ if (trimmed[cursor + 1] === '"') {
116
+ result += '"';
117
+ ++cursor;
118
+ continue;
119
+ }
120
+ break;
121
+ }
122
+ return result;
123
+ }
81
124
  /**
82
125
  * Encapsulates a string in a CSV safe way, taking
83
126
  * file paths (assumed by directory characters / and \,
@@ -196,6 +239,36 @@ async function runForFile(filePath, outputPath, maxTimeout, perfPath) {
196
239
  './compiled/src/ifc/ifc_regression_main.js';
197
240
  const safeExecCommand = `node --experimental-specifier-resolution=node ${childScript} -d${perfFlag} "${filePath}" "${outputPath}"`;
198
241
  console.log(`Current File: ${filePath}`);
242
+ // A model file that is still an unsmudged Git LFS pointer is NOT a model,
243
+ // and must not reach a child. Both engines parse the 132-byte placeholder
244
+ // as an empty document and exit 0, so without this it reads as a
245
+ // successful load of a model with no geometry - and a blessing run commits
246
+ // that to the baseline, where it stays. It already happened: NEMA 23 and
247
+ // ISSUE_098 were blessed at zero rows and filed as engine bugs (#477)
248
+ // before anyone noticed the run had never read them. See #486.
249
+ //
250
+ // Checked before the stale-digest removal below, deliberately: a local
251
+ // checkout that failed to smudge should not also destroy the good
252
+ // committed digest for that model.
253
+ if (await isGitLfsPointer(filePath)) {
254
+ console.error(`::error::"${path.basename(filePath)}" is an unsmudged Git LFS pointer, not a model. ` +
255
+ `Run \`git lfs pull\` in the models checkout.`);
256
+ return {
257
+ type: 'Failed',
258
+ message: 'Git LFS pointer stub, not a model file',
259
+ failureReason: 'lfs-pointer-stub',
260
+ name: 'Error',
261
+ };
262
+ }
263
+ // Remove any stale digest before the child runs. Without this, a child that
264
+ // dies without writing one leaves the committed baseline CSV in place, the
265
+ // batch hashes THAT, and the model reports an unchanged hash with no failure
266
+ // and no zero-geometry row - green, while extraction is completely broken.
267
+ // That is precisely the case this gate exists to catch.
268
+ const staleDigest = `${outputPath}.csv`;
269
+ if (fs.existsSync(staleDigest)) {
270
+ await fsPromises.rm(staleDigest, { force: true });
271
+ }
199
272
  // Use safeExecWithCancellation, will kill the process if it takes longer than MAX_TIMEOUT_MS.
200
273
  const process = await safeExecWithCancellation(safeExecCommand, MAX_TIMEOUT_MS);
201
274
  totalTime += Date.now() - startTime;
@@ -218,22 +291,78 @@ async function runForFile(filePath, outputPath, maxTimeout, perfPath) {
218
291
  }
219
292
  const outputFile = path.basename(outputPath);
220
293
  let fileHash;
294
+ // Absent digest counts as zero geometry: the stale file was removed before
295
+ // the child ran, so nothing here can be left over from the committed
296
+ // baseline. A child that dies without writing one is exactly the case this
297
+ // gate exists to catch, and hashing the old file would report it as green.
298
+ let producedNoGeometry = true;
221
299
  const outputCSV = `${outputPath}.csv`;
222
300
  if (fs.existsSync(outputCSV)) {
301
+ const digest = await fsPromises.readFile(outputCSV);
223
302
  fileHash = crypto
224
303
  .createHash('sha1')
225
- .update(await fsPromises.readFile(outputCSV))
304
+ .update(digest)
226
305
  .digest('hex');
306
+ // A digest with nothing after its header means the model loaded and
307
+ // produced no geometry at all. The child still exits 0, so this is
308
+ // invisible to every other signal the harness has — see #477 / #478.
309
+ //
310
+ // Known limitation: a digest row is any hashed entity, and that includes
311
+ // non-renderable ones (IFCSURFACESTYLE, IFCPOLYLINE, IFCCENTERLINEPROFILEDEF
312
+ // …), so "has rows" is weaker than "has renderable geometry". A model that
313
+ // emits only styles and profiles reads as fine here. That is a deliberate
314
+ // floor, not an oversight: this catches the total-blank case with zero
315
+ // false positives, which is what an unconditional CI gate needs. Tightening
316
+ // it to a mesh/vertex count means teaching the digest which types are
317
+ // renderable and re-blessing every baseline; tracked on #478.
318
+ producedNoGeometry =
319
+ digest.toString('utf8').split('\n').filter((line) => line.trim().length > 0).length <= 1;
227
320
  }
228
321
  return {
229
322
  type: 'Run',
230
323
  errorLines: errorLines.length > 0 ? errorLines : undefined,
231
324
  outputFile,
232
325
  hash: fileHash,
326
+ producedNoGeometry,
233
327
  };
234
328
  }
235
329
  // Model files the regression harness understands: IFC plus STEP AP214.
236
330
  const SUPPORTED_MODEL_EXTENSIONS = ['.ifc', '.stp', '.step'];
331
+ /**
332
+ * First bytes of a Git LFS pointer file, per the v1 pointer spec. The spec
333
+ * fixes this as the first line of every pointer, so a prefix match is exact
334
+ * rather than a heuristic - and no STEP or IFC file can begin this way, both
335
+ * being required to start with `ISO-10303-21;`.
336
+ */
337
+ const GIT_LFS_POINTER_PREFIX = 'version https://git-lfs.github.com/spec/v1';
338
+ /**
339
+ * Whether this file is an unsmudged Git LFS pointer rather than the model it
340
+ * stands for.
341
+ *
342
+ * Reads only the prefix: pointers are ~132 bytes, and a real model may be
343
+ * hundreds of megabytes.
344
+ *
345
+ * @param filePath Model file to inspect.
346
+ * @return {Promise<boolean>} True if the file is an LFS pointer stub.
347
+ */
348
+ async function isGitLfsPointer(filePath) {
349
+ let handle;
350
+ try {
351
+ handle = await fsPromises.open(filePath, 'r');
352
+ const buffer = Buffer.alloc(GIT_LFS_POINTER_PREFIX.length);
353
+ const { bytesRead } = await handle.read(buffer, 0, buffer.length, 0);
354
+ return bytesRead === buffer.length &&
355
+ buffer.toString('utf8') === GIT_LFS_POINTER_PREFIX;
356
+ }
357
+ catch {
358
+ // Unreadable is not this function's business to report - let the child
359
+ // run and fail with whatever the real problem is.
360
+ return false;
361
+ }
362
+ finally {
363
+ await handle?.close();
364
+ }
365
+ }
237
366
  /**
238
367
  * Whether this is a STEP (AP214) model file by extension.
239
368
  *
@@ -311,13 +440,15 @@ function getSystemMemoryUsagePercent() {
311
440
  * @param errorLines
312
441
  * @param fileLines
313
442
  * @param failedLines
443
+ * @param zeroGeometryLines
314
444
  * @param memUtilization
315
445
  * @param maxTimeout
446
+ * @param concurrency Max children processed at once (>= 1).
316
447
  * @param perfDir If set, the child writes its perf CSV here as <basename>.perf.csv.
317
448
  */
318
- async function processIFCFilesInParallel(ifcFiles, outputPath, errorLines, fileLines, failedLines, memUtilization, maxTimeout, perfDir) {
319
- const concurrencyLimit = os.cpus().length;
320
- console.log(`Concurrency: ${concurrencyLimit} threads - Max Timeout: ${maxTimeout} ms`);
449
+ async function processIFCFilesInParallel(ifcFiles, outputPath, errorLines, fileLines, failedLines, zeroGeometryLines, memUtilization, maxTimeout, concurrency, perfDir) {
450
+ const concurrencyLimit = Math.max(1, concurrency);
451
+ console.log(`Concurrency: ${concurrencyLimit} children - Max Timeout: ${maxTimeout} ms`);
321
452
  const limit = pLimit(concurrencyLimit);
322
453
  const taskTimeout = 2000;
323
454
  let activeTasks = 0;
@@ -349,12 +480,18 @@ async function processIFCFilesInParallel(ifcFiles, outputPath, errorLines, fileL
349
480
  fileLines.push(`${csvSafeString(path.basename(ifcPath))},` +
350
481
  `${csvSafeString(fileResults.hash ?? '')},` +
351
482
  `${fileResults.errorLines?.length ?? 0}\n`);
483
+ if (fileResults.producedNoGeometry) {
484
+ zeroGeometryLines.push(`${csvSafeString(path.basename(ifcPath))}\n`);
485
+ }
352
486
  }
353
487
  else {
354
488
  // it's 'Failed'
489
+ // failureReason takes the signal column when the harness diagnosed the
490
+ // failure itself, so the row says what happened instead of leaving a
491
+ // reader to infer it from two empty fields. See RunErrorResults.
355
492
  failedLines.push(`${csvSafeString(path.basename(ifcPath))},` +
356
493
  `${csvSafeString(fileResults.code?.toString() ?? '')},` +
357
- `${csvSafeString(fileResults.signal ?? '')}\n`);
494
+ `${csvSafeString(fileResults.failureReason ?? fileResults.signal ?? '')}\n`);
358
495
  }
359
496
  }
360
497
  }
@@ -367,10 +504,11 @@ async function processIFCFilesInParallel(ifcFiles, outputPath, errorLines, fileL
367
504
  * @param errorLines
368
505
  * @param fileLines
369
506
  * @param failedLines
507
+ * @param zeroGeometryLines
370
508
  * @param maxTimeout
371
509
  * @param perfDir If set, the child writes its perf CSV here as <basename>.perf.csv.
372
510
  */
373
- async function recursiveWalk(parentPath, excludeRegex, outputPath, errorLines, fileLines, failedLines, maxTimeout, perfDir) {
511
+ async function recursiveWalk(parentPath, excludeRegex, outputPath, errorLines, fileLines, failedLines, zeroGeometryLines, maxTimeout, perfDir) {
374
512
  const items = await fsPromises.readdir(parentPath, { withFileTypes: true });
375
513
  items.sort((a, b) => (a.name > b.name ? 1 : -1));
376
514
  for (const item of items) {
@@ -379,7 +517,7 @@ async function recursiveWalk(parentPath, excludeRegex, outputPath, errorLines, f
379
517
  continue;
380
518
  }
381
519
  if (item.isDirectory()) {
382
- await recursiveWalk(resolved, excludeRegex, outputPath, errorLines, fileLines, failedLines, maxTimeout, perfDir);
520
+ await recursiveWalk(resolved, excludeRegex, outputPath, errorLines, fileLines, failedLines, zeroGeometryLines, maxTimeout, perfDir);
383
521
  }
384
522
  else if (isSupportedModelFile(resolved)) {
385
523
  const perfChildPath = perfDir ?
@@ -391,9 +529,13 @@ async function recursiveWalk(parentPath, excludeRegex, outputPath, errorLines, f
391
529
  errorLines.push(...fileResults.errorLines);
392
530
  }
393
531
  fileLines.push(`${csvSafeString(path.basename(resolved))},${csvSafeString(fileResults.hash ?? '')},${fileResults.errorLines?.length ?? 0}\n`);
532
+ if (fileResults.producedNoGeometry) {
533
+ zeroGeometryLines.push(`${csvSafeString(path.basename(resolved))}\n`);
534
+ }
394
535
  }
395
536
  else {
396
- failedLines.push(`${csvSafeString(path.basename(resolved))},${csvSafeString(fileResults.code?.toString() ?? '')},${csvSafeString(fileResults.signal ?? '')}\n`);
537
+ // See the parallel path's copy for why failureReason wins here.
538
+ failedLines.push(`${csvSafeString(path.basename(resolved))},${csvSafeString(fileResults.code?.toString() ?? '')},${csvSafeString(fileResults.failureReason ?? fileResults.signal ?? '')}\n`);
397
539
  }
398
540
  }
399
541
  }
@@ -437,6 +579,17 @@ const args = yargs(process.argv.slice(SKIP_PARAMS))
437
579
  alias: 'm',
438
580
  default: 95,
439
581
  });
582
+ // only relevant if parallel is enabled
583
+ yargs2.option('concurrency', {
584
+ describe: 'Max IFC files processed at once in parallel mode. Each child ' +
585
+ 'is itself multi-threaded, so os.cpus() children heavily ' +
586
+ 'oversubscribe the cores: the largest models\' wall-clock then ' +
587
+ 'balloons (spurious timeouts) and per-model perf numbers become ' +
588
+ 'noise. Lower this for steady timings. Default: CPU core count.',
589
+ type: 'number',
590
+ alias: 'j',
591
+ default: 0,
592
+ });
440
593
  // Validate mem-utilization only if parallel mode is active
441
594
  yargs2.check((argv) => {
442
595
  if (argv.parallel) {
@@ -481,6 +634,9 @@ const args = yargs(process.argv.slice(SKIP_PARAMS))
481
634
  const doParallel = argv['parallel'] ?? false; // <--- read the parallel flag
482
635
  const memUtilization = argv['mem-utilization'];
483
636
  const maxTimeout = argv['timeout'];
637
+ // 0 (the default) means "auto": one child per core.
638
+ const concurrencyArg = argv['concurrency'];
639
+ const concurrency = concurrencyArg && concurrencyArg > 0 ? Math.floor(concurrencyArg) : os.cpus().length;
484
640
  const perfOutputPath = (argv['perf'] ?? '').trim();
485
641
  if (changes.length === 0) {
486
642
  changes = path.join(outputPath, 'changes');
@@ -498,25 +654,60 @@ const args = yargs(process.argv.slice(SKIP_PARAMS))
498
654
  const mainPath = path.join(outputPath, 'main.csv');
499
655
  const errorPath = path.join(outputPath, 'errors.csv');
500
656
  const failedPath = path.join(outputPath, 'failed.csv');
657
+ const zeroGeometryPath = path.join(outputPath, 'zero_geometry.csv');
501
658
  const errorLines = [];
502
659
  const fileLines = [];
503
660
  const failedLines = [];
661
+ const zeroGeometryLines = [];
504
662
  const excludeRegex = excludeFilter.length > 0 ? new RegExp(excludeFilter) : undefined;
505
663
  if (doParallel) {
506
664
  console.log('Processing in parallel mode...');
507
665
  // 1) Collect all IFC files first
508
666
  const allIFCFiles = await collectIFCFiles(ifcFolder, excludeRegex);
509
667
  // 2) Process them in parallel
510
- await processIFCFilesInParallel(allIFCFiles, outputPath, errorLines, fileLines, failedLines, memUtilization, maxTimeout, perfTmpDir);
668
+ await processIFCFilesInParallel(allIFCFiles, outputPath, errorLines, fileLines, failedLines, zeroGeometryLines, memUtilization, maxTimeout, concurrency, perfTmpDir);
511
669
  }
512
670
  else {
513
671
  console.log('Processing in serial mode...');
514
- await recursiveWalk(ifcFolder, excludeRegex, outputPath, errorLines, fileLines, failedLines, maxTimeout, perfTmpDir);
672
+ await recursiveWalk(ifcFolder, excludeRegex, outputPath, errorLines, fileLines, failedLines, zeroGeometryLines, maxTimeout, perfTmpDir);
515
673
  }
516
674
  // Write out results
517
675
  await fsPromises.writeFile(mainPath, `file,hash,errors\n${fileLines.join('')}`);
518
676
  await fsPromises.writeFile(errorPath, `${errorCSVHeader}\n${errorLines.join('')}`);
519
677
  await fsPromises.writeFile(failedPath, `file,code,signal\n${failedLines.join('')}`);
678
+ // Models that loaded and produced no geometry. Written as its own
679
+ // artifact rather than folded into failed.csv, because the two need
680
+ // different gates: failed.csv is empty and stays empty, while a
681
+ // handful of zero-geometry models are known and tracked (#477), so
682
+ // CI compares this against an explicit allowlist instead.
683
+ // Models whose digest stem collides cannot be judged: two models
684
+ // sharing a basename write the SAME digest file, so in --parallel one
685
+ // can be read between another's truncate and its first row. That
686
+ // collision is a pre-existing harness bug (it also means the blessed
687
+ // digest is whichever model ran last) - `ifc/index.ifc` and
688
+ // `ifc/bldrs/index.ifc` are a live example, both in the smoke subset.
689
+ // Suppress rather than guess, so it cannot red an unrelated PR, and
690
+ // say so loudly.
691
+ const stemCounts = new Map();
692
+ for (const line of fileLines) {
693
+ const stem = path.parse(csvFirstField(line)).name;
694
+ stemCounts.set(stem, (stemCounts.get(stem) ?? 0) + 1);
695
+ }
696
+ const collidingStems = new Set([...stemCounts].filter(([, count]) => count > 1).map(([stem]) => stem));
697
+ if (collidingStems.size > 0) {
698
+ console.warn(`WARNING: ${collidingStems.size} digest stem(s) are written by more ` +
699
+ `than one model, so their digests overwrite each other and their ` +
700
+ `zero-geometry status cannot be determined: ${[...collidingStems].join(', ')}`);
701
+ }
702
+ const reportableZeroGeometry = zeroGeometryLines.filter((line) => !collidingStems.has(path.parse(csvFirstField(line)).name));
703
+ await fsPromises.writeFile(zeroGeometryPath, `file\n${reportableZeroGeometry.join('')}`);
704
+ if (reportableZeroGeometry.length > 0) {
705
+ console.log(`\n${reportableZeroGeometry.length} model(s) loaded but produced NO geometry:`);
706
+ for (const line of reportableZeroGeometry) {
707
+ console.log(` ${line.trim()}`);
708
+ }
709
+ console.log('');
710
+ }
520
711
  // Aggregate per-child perf rows (if requested) before runDiff so the
521
712
  // run completes deterministically even when the git diff step is
522
713
  // skipped or fails.
@@ -539,5 +730,12 @@ const args = yargs(process.argv.slice(SKIP_PARAMS))
539
730
  const overallEnd = Date.now();
540
731
  const totalSec = ((overallEnd - overallStart) / divisor).toFixed(fixedPoint);
541
732
  console.log(`\nAll tasks completed. Total runtime: ${totalSec} seconds.`);
733
+ // All work is done and every CSV is written. Exit explicitly rather
734
+ // than waiting for the event loop to drain: a child that had to be
735
+ // force-killed (or any lingering wasm worker handle) can otherwise
736
+ // keep this process alive long after the run, hanging the CI step
737
+ // for the rest of the job timeout. console.log to a pipe is
738
+ // synchronous on Linux, so the line above is already flushed.
739
+ process.exit(0);
542
740
  })
543
741
  .help().argv;
@@ -0,0 +1,145 @@
1
+ import EntityTypesIfc from "./ifc4_gen/entity_types_ifc.gen.js";
2
+ import IfcStepParser from "./ifc_step_parser.js";
3
+ import { StreamingRecordDispatcher } from "../step/parsing/streaming_record_dispatcher.js";
4
+ /** One node of the skeleton: what a tree row needs, and nothing else. */
5
+ export interface SkeletonNode {
6
+ /** The record's express ID. */
7
+ expressID: number;
8
+ /** The record's concrete type. */
9
+ type: EntityTypesIfc;
10
+ /** `Name`, when the record carried one. */
11
+ name?: string;
12
+ /** `LongName`, for spatial elements that carried one. */
13
+ longName?: string;
14
+ /** `GlobalId`, when the record carried one. */
15
+ globalId?: string;
16
+ /** Children, in the order their relationships were parsed. */
17
+ children: SkeletonNode[];
18
+ }
19
+ /**
20
+ * The spatial **names skeleton** (M2, issue #393): project → site → building →
21
+ * storey → product, with names, built from the streaming parse's record events
22
+ * so the tree can be shown while the model is still loading.
23
+ *
24
+ * This is the one standard consumer that genuinely belongs on the event path,
25
+ * and the reason is the record's *bytes*. Everything else M2 wanted —
26
+ * membership, counts, ids — is in the columnar index and is cheaper (and, for
27
+ * complex records, only correct) when derived from a prefix snapshot; see
28
+ * {@link import('../step/parsing/prefix_type_index').PrefixTypeIndex}. Names
29
+ * and relationship edges are not in the columns, and after the parse they cost
30
+ * a second pass that pages every relationship and every named record back in
31
+ * through the windowed provider — which is exactly what Share's post-parse
32
+ * `'names'` sweep does today.
33
+ *
34
+ * What runs per record is deliberately small: tokenize the record's attribute
35
+ * list, copy out at most three short strings, and append two integers per
36
+ * edge. Nothing is resolved and no tree is built until {@link tree} is called —
37
+ * "resolvable" therefore means "present when you asked", and a file that
38
+ * forward-references its way through the spatial hierarchy simply resolves at
39
+ * end of stream, with no pending-reference table to maintain.
40
+ *
41
+ * Idempotence: the streaming builder's grow-and-restart re-fires records from
42
+ * localID 0. A non-ascending localID is taken as that restart and clears both
43
+ * the nodes and the edge columns, so a restarted parse rebuilds rather than
44
+ * doubling its edges.
45
+ */
46
+ export declare class IfcSpatialSkeleton {
47
+ private readonly nodes_;
48
+ private edgeParents_;
49
+ private edgeChildren_;
50
+ private edgeCount_;
51
+ private readonly cursor_;
52
+ private lastLocalID_;
53
+ /**
54
+ * @param parser The IFC parser whose tokenizer reads the record bytes.
55
+ * Defaults to the singleton the streaming open uses.
56
+ */
57
+ constructor(parser?: IfcStepParser);
58
+ /**
59
+ * Subscribe this skeleton to a dispatcher — the object definitions it names
60
+ * and the two relationship types it draws edges from.
61
+ *
62
+ * @param dispatcher The dispatcher fed by the streaming parse.
63
+ */
64
+ subscribe(dispatcher: StreamingRecordDispatcher<EntityTypesIfc>): void;
65
+ /**
66
+ * @return {number} Nodes seen so far (children not yet linked).
67
+ */
68
+ get nodeCount(): number;
69
+ /**
70
+ * @return {number} Containment edges captured so far.
71
+ */
72
+ get edgeCount(): number;
73
+ /**
74
+ * Record a named object definition. Bound for direct use as a subscription.
75
+ *
76
+ * @param localID The record's dense local ID.
77
+ * @param expressID The record's express ID.
78
+ * @param typeID The record's concrete type.
79
+ * @param buffer The live parse window holding the record.
80
+ * @param byteOffset Offset of the record's attribute list in `buffer`.
81
+ * @param byteLength Length of the attribute list.
82
+ */
83
+ private readonly handleObject;
84
+ /**
85
+ * Where this type keeps `LongName`, if it has one.
86
+ *
87
+ * @param typeID The record's concrete type.
88
+ * @return {number | undefined} The attribute index, or undefined for types
89
+ * that carry no `LongName` at all.
90
+ */
91
+ private longNameAttribute;
92
+ /**
93
+ * Record the containment edges of one relationship. Bound for direct use as
94
+ * a subscription.
95
+ *
96
+ * @param localID The record's dense local ID.
97
+ * @param expressID The record's express ID.
98
+ * @param typeID The record's concrete type.
99
+ * @param buffer The live parse window holding the record.
100
+ * @param byteOffset Offset of the record's attribute list in `buffer`.
101
+ * @param byteLength Length of the attribute list.
102
+ */
103
+ private readonly handleRelationship;
104
+ /**
105
+ * Reset if the parse restarted. localIDs ascend strictly within a run, so a
106
+ * localID that does not exceed the last one seen means the streaming
107
+ * builder hit its grow-and-restart valve and is re-firing from 0. Testing
108
+ * for `localID === 0` would not do: this consumer only sees its subscribed
109
+ * types, and record 0 is rarely one of them.
110
+ *
111
+ * @param localID The record's dense local ID.
112
+ */
113
+ private noteRestart;
114
+ /**
115
+ * Append one containment edge, growing the columns as needed.
116
+ *
117
+ * @param parent Express ID of the containing entity.
118
+ * @param child Express ID of the contained entity.
119
+ */
120
+ private pushEdge;
121
+ /**
122
+ * Look one node up without building the tree.
123
+ *
124
+ * @param expressID The express ID.
125
+ * @return {SkeletonNode | undefined} The node, if it has been parsed.
126
+ */
127
+ node(expressID: number): SkeletonNode | undefined;
128
+ /**
129
+ * Build the tree over everything parsed so far and return its roots — nodes
130
+ * that are nobody's child. That is the project once it has been seen, plus
131
+ * whatever a prefix has not reached the parent of yet, plus the object
132
+ * definitions that genuinely hang outside the spatial hierarchy (type
133
+ * objects, ungrouped actors); a caller that wants strictly the spatial tree
134
+ * should walk down from the project's express ID rather than treat every
135
+ * root as spatial.
136
+ *
137
+ * Each call relinks children from the edge columns, so a caller may call it
138
+ * repeatedly as the parse advances; the returned nodes are the live ones, so
139
+ * a previously returned tree is not a snapshot.
140
+ *
141
+ * @return {SkeletonNode[]} The roots, in parse order.
142
+ */
143
+ tree(): SkeletonNode[];
144
+ }
145
+ //# sourceMappingURL=ifc_spatial_skeleton.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ifc_spatial_skeleton.d.ts","sourceRoot":"","sources":["../../../src/ifc/ifc_spatial_skeleton.ts"],"names":[],"mappings":"AAEA,OAAO,cAAc,MAAM,iCAAiC,CAAA;AAQ5D,OAAO,aAAa,MAAM,mBAAmB,CAAA;AAC7C,OAAO,EAAE,yBAAyB,EAAE,MAAM,6CAA6C,CAAA;AAwCvF,yEAAyE;AACzE,MAAM,WAAW,YAAY;IAE3B,+BAA+B;IAC/B,SAAS,EAAE,MAAM,CAAA;IAEjB,kCAAkC;IAClC,IAAI,EAAE,cAAc,CAAA;IAEpB,2CAA2C;IAC3C,IAAI,CAAC,EAAE,MAAM,CAAA;IAEb,yDAAyD;IACzD,QAAQ,CAAC,EAAE,MAAM,CAAA;IAEjB,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,MAAM,CAAA;IAEjB,8DAA8D;IAC9D,QAAQ,EAAE,YAAY,EAAE,CAAA;CACzB;AAGD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,qBAAa,kBAAkB;IAE7B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkC;IAEzD,OAAO,CAAC,YAAY,CAAmC;IAEvD,OAAO,CAAC,aAAa,CAAmC;IAExD,OAAO,CAAC,UAAU,CAAI;IAEtB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAmC;IAE3D,OAAO,CAAC,YAAY,CAAK;IAEzB;;;OAGG;gBACU,MAAM,GAAE,aAAsC;IAI3D;;;;;OAKG;IACI,SAAS,CAAE,UAAU,EAAE,yBAAyB,CAAC,cAAc,CAAC,GAAI,IAAI;IAM/E;;OAEG;IACH,IAAW,SAAS,IAAI,MAAM,CAE7B;IAED;;OAEG;IACH,IAAW,SAAS,IAAI,MAAM,CAE7B;IAED;;;;;;;;;OASG;IACH,OAAO,CAAC,QAAQ,CAAC,YAAY,CA6C5B;IAED;;;;;;OAMG;IACH,OAAO,CAAC,iBAAiB;IAQzB;;;;;;;;;;OAUG;IACH,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAoClC;IAED;;;;;;;;OAQG;IACH,OAAO,CAAC,WAAW;IASnB;;;;;OAKG;IACH,OAAO,CAAC,QAAQ;IAiBhB;;;;;OAKG;IACI,IAAI,CAAE,SAAS,EAAE,MAAM,GAAI,YAAY,GAAG,SAAS;IAI1D;;;;;;;;;;;;;;OAcG;IACI,IAAI,IAAI,YAAY,EAAE;CAgC9B"}