Opening-classifier outcome counts.
Failure counts by stable reason label, sorted desc by count.
Hosts that had openings processed (batch-summed upper bound).
OptionaloversizedContent-hash references the geometry pass refused because they exceeded
u32::MAX (#3421 / #3752). Nonzero means some instancing was skipped, not
that geometry is wrong. Optional: absent on payloads from producers
predating the counter.
Distinct products with at least one failure (batch-summed upper bound).
rect_fast fast-path engagement (perf observability).
OptionaldeferTooManyOpenings?: numberOptional: absent on payloads produced before this counter existed (#1649).
Contract version handshake (mirrors Rust
GEOMETRY_DIAGNOSTICS_SCHEMA_VERSION, currently 3 — that constant carries
the per-version changelog and is the single source of truth). Bumped on
field renames, field removals, and count-semantics changes; also on an
additive field whose absence a consumer must tell apart from a real zero,
which is why 2 (removed guardSaved) and 3 (added
totalUnsupportedItems) both bumped. A purely additive optional field
that no consumer gates on does not bump.
REQUIRED, not optional: the Rust field is a plain u32 serialized
unconditionally, so every producer since #1514 writes the key. A value of
0 is what Rust's #[serde(default)] yields when it READS a payload
written before #1514, and is the only "pre-versioned producer" signal a
consumer sees.
Hosts where rectangular cutters ran, the triangle count was unchanged, and NO failure was recorded (cut attempted, geometry not modified) - the highest- signal "looks wrong but did not error" indicator. Hosts that failed are excluded (they are loud failures counted in totalCsgFailures, not silent). Batch-summed upper bound.
Total CSG boolean failures (un-cut openings, emptied hosts, kernel fallbacks).
OptionaltotalRepresentation items dropped from the output: no processor is registered for the IFC type, or the registered processor errored (degenerate/failed geometry). Excludes elements with no Body representation at all — those are correctly absent from the 3D view and never counted here. Absent on a payload produced before this counter existed (schemaVersion < 3).
A lower bound on instances: a drop inside a RepresentationMap source is
counted once per walking router, not once per IfcMappedItem occurrence
that reuses the cached source. That is once model-wide on the wasm batch
path, which uses one router; the native pool builds a router per element,
and a source whose items ALL drop is never published to the shared cache
(it meshes to nothing), so there it contributes once per owning element.
Read it as "these types were dropped", never as a count of affected
elements or of distinct sources.
OptionalunsupportedtotalUnsupportedItems broken down by IFC type, sorted desc by count.
Bounded top-N worst-failing hosts (opt-in per-product detail).
Optionalbbox?: { max: [number, number, number]; min: [number, number, number] }World-space AABB of the host mesh, when a void cut captured it.
Mirrors the {min, max} shape used by MeshData.localBounds.
OptionalfirstFailureLabel?: stringOptionaltriangleCount?: numberFinal triangle count of the host's mesh (post-cut when a void subtraction ran, otherwise the pre-cut count).
Public CSG / opening diagnostics contract for @ifc-lite/geometry. The shape mirrors the Rust
GeometryDiagnostics(rust/geometry router::diagnostics), which is built once per geometry batch and serialized to a JS object. The geometry worker merges per-batch values across batches and the parallel loader merges across workers, surfacing onediagnosticsobject on the streamingcompleteevent. The nativeProcessingStatspath reuses the same aggregator (wired:rust/processingpopulatesgeometry_diagnostics).Counts are best-effort observability:
totalCsgFailuresand the classification counts are exact, whileproductsWithFailures/hostsWithOpenings/silentNoOpsare summed per batch and are therefore upper bounds (a product whose geometry spans batches may be counted more than once).