Skip to content

fix(geometry): material-layer walls emit a watertight skin, not a doubled "ghost face"#1311

Merged
louistrue merged 5 commits into
mainfrom
fix/layer-wall-watertight-section
Jun 23, 2026
Merged

fix(geometry): material-layer walls emit a watertight skin, not a doubled "ghost face"#1311
louistrue merged 5 commits into
mainfrom
fix/layer-wall-watertight-section

Conversation

@louistrue

@louistrue louistrue commented Jun 22, 2026

Copy link
Copy Markdown
Collaborator

Summary

Material-layer walls (IfcMaterialLayerSetUsage) rendered correctly but the emitted mesh carried a spurious, full-cross-section "ghost face" offset by a layer thickness: it was non-watertight and ~3× the triangles of the correct solid. Reported on opening-cut layered walls (e.g. AC-20-Smiley-West-10-Bldg.ifc #37781).

This is finding #1 from the geometry audit. (Finding #2 — "opening not subtracted on clipped hosts" — turned out to be the #1297 local-frame bug, already fixed by #1310; findings #3/#4 are lower-priority and tracked separately.)

Root cause

The slicer (rust/geometry/src/router/layers.rs) cut a layered wall into per-layer slabs and capped each slab at its interface planes so every slab was an independently closed solid. Every shared interface was therefore capped twice — two coincident, oppositely-wound, full-cross-section sheets. The wall still rendered solid (the interior caps are GEOM_CLASS_LAYER_SLICE backface-culled), but the mesh had degree-4 interface edges (non-manifold) and triple the triangles.

AC-20 #37781 sub-meshes tris degree-4 edges open edges
before 2 272 73 (ghost sheet) 0
after 2 160 0 0 (watertight union)

Fix

Rust slicer: slice without capping, carving each band off a running remainder so both sides of every interface come from the same clip of the same mesh. The cut tessellations then match exactly, so the open bands weld edge-for-edge (no T-junctions) — the union of the bands is precisely the wall's watertight outer skin, partitioned per material. (A first cut that capped each interface once still left T-junctions where a twice-clipped middle band diverged from its neighbour; the progressive carve eliminates them — verified: synthetic 3-layer wall and real AC-20 #37781 both report open=0, degree-4=0.)

2D section (@ifc-lite/drawing-2d): the section reconstructs per-layer fills from these slab meshes (useDrawingGeneration feeds geometryResult.meshes straight into the cutter), and a forward-only loop builder strands an open band's segments → no fill. The PolygonBuilder loop builder is now bidirectional: each open band assembles into a ring whose implicit head→tail chord re-creates the interface line the cap used to draw, so per-layer section fills are unchanged.

Tests

  • material_layers_local_frame_test.rs updated: the slab union must be watertight (no open edges) and carry no doubled interface sheet (no degree-4 edges).
  • polygon-builder.test.ts: new open-band reconstruction test — two cap-free U-bands sharing an interface still yield one filled polygon per layer.
  • Full geometry layer/wall/void suites green (material_layers 6/6, merge_layers 2/2, wall_opening_cut_regression 7/7, lib 389/0); drawing-2d 45/45.

🤖 Generated with Claude Code


Follow-up folded in: solid layer look in 3D section view

The watertight (cap-free) bands made layered walls read hollow when cut in the 3D section view, not just at minor gaps. Two commits fix that while keeping the watertight geometry from this PR (no Rust change):

fix(drawing-2d): solid per-layer section cap on opening-cut walls. The 3D section clip and the cap are both gated on the section tool, so the cap is always generated when you cut. Its per-layer reconstruction from open bands broke on any 3+ layer wall with an opening: an interior layer (no broad face) sections into 4+ disconnected strips, and the greedy nearest-endpoint stitch joined a strip to the one ACROSS the opening, emitting one self-overlapping polygon that bridged the void and failed to triangulate. That layer is the bulk of the wall thickness, so the cut read hollow. Closure now runs along the interface lines (paired consecutively, scanline-style, on the band's principal/length axis, so it is robust to rotated walls), which fills each solid chunk and leaves the opening empty.

feat(drawing-2d): opaque base-cap backstop so section cuts never read hollow. For each multi-material entity the builder also emits its full closed cross-section (the watertight union always closes, so no interface stitching is needed), carried in a new Drawing2D.layerBaseCutPolygons that ONLY the 3D section overlay consumes. The overlay draws this opaque base behind the per-layer colours, so colours show where they reconstruct and solid cut material shows everywhere else. The flat 2D drawing, SVG export, and measure/snap paths read cutPolygons and are untouched.

fix(renderer): draw material-layer slices double-sided so walls aren't hollow. The deeper cause of "hollow" was in NORMAL (uncut) 3D, not just section. The renderer backface-culled the slices, assuming reliable outward winding. That held for the OLD closed slabs (the cull hid their coincident interface caps). The slabs are now open bands whose union is the wall's watertight outer skin (no caps), and IFC winding is not reliably outward, so culling dropped inward-wound faces and punched holes, making the wall look like a thin see-through shell. The slices now render double-sided like all other IFC geometry, so every face of the watertight skin draws and the wall reads solid; with no coincident caps left there is nothing to z-fight, so the dedicated culled pipeline and the isLayer batch flag are removed (GEOM_CLASS_LAYER_SLICE stays as the per-layer-fill marker only).

Tests: new polygon-builder-opening.test.ts (2-layer + opening, 3-layer interior core + opening, rotated wall, base-cap cases); full drawing-2d now 51/51; drawing-2d, renderer, and the changed viewer files typecheck clean.

Summary by CodeRabbit

  • Bug Fixes
    • Fixed layer section rendering showing coincident “ghost face” artifacts and reduced related triangle duplication.
    • Improved 2D/3D section overlay robustness with opaque base cross-sections to prevent hollow/see-through caps when layer reconstruction can’t fully resolve.
    • Corrected multilayer wall appearance (including double-sided layer rendering) and ensured openings in multilayer walls are not filled/bridged.
  • Tests
    • Added new coverage for cap-free layer reconstruction and opening-cut multilayer behavior.

…bled "ghost face"

A material-layer wall was sliced into per-layer slabs, each CAPPED at its
interface planes to be an independently closed solid. Every SHARED interface was
therefore capped twice — a coincident, oppositely-wound, full-cross-section
sheet. The wall still rendered solid (the interior caps are backface-culled) but
the emitted mesh was non-watertight (degree-4 interface edges) and ~3x the
triangles: the "ghost face" reported on opening-cut layered walls.
AC-20 #37781: 272 tris / 73 degree-4 edges -> 160 tris / 0 degree-4, watertight.

Slice without capping, carving each band off a running REMAINDER so both sides
of every interface come from the same clip of the same mesh (matching
tessellation, so the bands weld with no T-junctions). The union of the open
bands is exactly the wall's watertight outer skin, partitioned per material.

The 2D section consumed the capped slabs to reconstruct per-layer fills, so the
@ifc-lite/drawing-2d PolygonBuilder loop builder is now bidirectional: each open
band assembles into a ring whose implicit head->tail chord re-creates the
interface line the cap used to draw. Per-layer section fills are unchanged
(verified by an open-band reconstruction test).
@vercel

vercel Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
ifc-lite Ready Ready Preview, Comment Jun 23, 2026 10:53am
2 Skipped Deployments
Project Deployment Actions Updated (UTC)
ifc-lite-dev Ignored Ignored Preview Jun 23, 2026 10:53am
ifc-lite-viewer-embed Ignored Ignored Jun 23, 2026 10:53am

@coderabbitai

coderabbitai Bot commented Jun 22, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e88c9d86-6527-4333-a85c-73e3d3dbe63d

📥 Commits

Reviewing files that changed from the base of the PR and between ac3ceeb and ffe5ac5.

📒 Files selected for processing (13)
  • .changeset/layer-wall-watertight-section.md
  • apps/viewer/src/components/viewer/useRenderUpdates.ts
  • apps/viewer/src/hooks/useDrawingGeneration.ts
  • packages/drawing-2d/src/drawing-generator.ts
  • packages/drawing-2d/src/polygon-builder-opening.test.ts
  • packages/drawing-2d/src/polygon-builder.test.ts
  • packages/drawing-2d/src/polygon-builder.ts
  • packages/drawing-2d/src/types.ts
  • packages/renderer/src/index.ts
  • packages/renderer/src/pipeline.ts
  • packages/renderer/src/scene.ts
  • packages/renderer/src/types.ts
  • rust/processing/src/element.rs

📝 Walkthrough

Walkthrough

The Rust geometry slicer is rewritten to progressively carve uncapped layer bands from a running remainder mesh, eliminating coincident ghost faces and triangle duplication. To handle the resulting open bands, the TypeScript polygon builder adds bidirectional head/tail loop construction with interface-aware closure, principal-axis estimation, and endpoint-pair stitching to reconstruct multi-layer walls. The renderer removes its culled pipeline and renders all layer slices double-sided. The viewer integrates opaque base cross-sections (held separately in layerBaseCutPolygons) as an overlay backstop to prevent see-through caps, while flat 2D/SVG/measurement paths remain unchanged.

Changes

Cap-free layer slicing and multi-layer wall reconstruction

Layer / File(s) Summary
Rust geometry: cap-free layer carving
rust/geometry/src/router/layers.rs, rust/geometry/tests/material_layers_local_frame_test.rs
Removes cap_half_space_clip import and rewrites slice_mesh_into_layers to clip a running remainder against successive interface planes without capping, producing uncapped layer bands. Test validation switches from per-layer closed-solid assertions to union-level union_edge_stats checking that combined sub-meshes are watertight (open == 0) and free of doubled ghost sheets (doubled == 0).
TypeScript: polygon types for base layer reconstruction
packages/drawing-2d/src/types.ts
DrawingPolygon adds optional isLayerBase flag (marks opaque base cross-sections); Drawing2D adds optional layerBaseCutPolygons field (holds base polygons separate from colorized cutPolygons, consumed only by 3D overlay).
TypeScript: bidirectional polygon loop builder
packages/drawing-2d/src/polygon-builder.ts
Rewrites buildSingleLoop from single-ended forward chaining to bidirectional head/tail extension: maintains both ends, prefers tail extension, falls back to head, closes when tail meets head, and returns an open contour when neither end can extend. Updated buildLoops accepts stitchOpen flag and classifies chains as standalone vs. fragment, collecting fragments only when stitching is enabled.
TypeScript: interface-aware closure and principal-axis analysis
packages/drawing-2d/src/polygon-builder.ts
Implements closeAlongInterfaces to close open-band fragments by estimating a principal axis for the endpoint cloud, clustering endpoints into interface-line groups, pairing endpoints consecutively along each line, and walking polylines while hopping between paired endpoints. Implements principalAxis via covariance eigenvector logic. Extends stitchOpenChains to merge fragments iteratively by nearest neighbor, optionally reversing, emitting loops only when signed area is non-degenerate.
TypeScript: opaque base polygon generation
packages/drawing-2d/src/polygon-builder.ts
Adds buildBasePolygons public method that groups segments by entity, filters to multi-material entities, builds closed loop polygons for the combined solid section, stamps isLayerBase: true, and returns flattened result.
TypeScript: drawing generator produces base polygons
packages/drawing-2d/src/drawing-generator.ts
Drawing2DGenerator.generate() now builds an additional layerBaseCutPolygons set via polygonBuilder.buildBasePolygons(cutSegments) separate from colorized cutPolygons, and includes it in the returned Drawing2D object.
TypeScript: polygon reconstruction test coverage
packages/drawing-2d/src/polygon-builder.test.ts, packages/drawing-2d/src/polygon-builder-opening.test.ts
Adds comprehensive tests for open-band reconstruction verifying that buildPolygons closes each cap-free layer band at interface chord with correct colors and unit-area outer contours (validated via polygonSignedArea), and correctly stitches disconnected interior-core bands in 3+ layer walls. Opening-cut tests verify buildPolygons reconstructs per-layer chunks without bridging across openings, and buildBasePolygons emits opaque base cross-sections per solid chunk for multi-material entities while omitting bases for single-material walls.
Renderer: remove culled pipeline, render layer slices double-sided
packages/renderer/src/index.ts, packages/renderer/src/pipeline.ts, packages/renderer/src/types.ts
Removes culledPipeline field and getCulledPipeline() method from RenderPipeline. In Renderer.render(), all opaque batches (including layer slices) now route through standard getPipeline() double-sided pipeline; removes special-case batch.isLayer and subBatch.isLayer branches. BatchedMesh interface removes isLayer flag and adds origin vector for local-frame vertex position translation.
TypeScript: scene/types cleanup and processing docs
packages/renderer/src/scene.ts, rust/processing/src/element.rs
Scene.createBatchedMesh() no longer computes isLayer flag. Processing comment for GEOM_CLASS_LAYER_SLICE updated to reflect that slices are now open bands drawn double-sided, and the tag is purely a per-layer-fill marker (no longer used for culling).
TypeScript: viewer integration of base polygons
apps/viewer/src/components/viewer/useRenderUpdates.ts, apps/viewer/src/hooks/useDrawingGeneration.ts
In useRenderUpdates 2D section overlay, constructs both opaque "base" polygon set from drawing2D.layerBaseCutPolygons and colorized "layer" set from drawing2D.cutPolygons, rendering base first to prevent see-through caps. In useDrawingGeneration hybrid drawing construction, filters result.layerBaseCutPolygons to remove base polygons for entities replaced by symbolic representations.
Release notes
.changeset/layer-wall-watertight-section.md
Changeset adds patch bumps for @ifc-lite/drawing-2d and @ifc-lite/renderer. Documents per-layer fill reconstruction from open (cap-free) bands, bidirectional loop building with interface-chord closure, interior-strip stitching for multi-layer walls, opening-cut hardening via endpoint pairing, opaque base-cap backstop in layerBaseCutPolygons (3D overlay only), and double-sided rendering for normal 3D multilayer walls.

Sequence Diagram(s)

sequenceDiagram
  participant Geometry as Geometry Slicer
  participant PolygonBuilder as Polygon Builder
  participant Renderer as Renderer
  participant Viewer as 2D Overlay

  Geometry->>Geometry: Carve cap-free bands from remainder
  Geometry->>PolygonBuilder: Uncapped layer band segments
  PolygonBuilder->>PolygonBuilder: Bidirectional head/tail loop closure
  PolygonBuilder->>PolygonBuilder: Interface-aware fragment stitching
  PolygonBuilder->>Renderer: Per-layer colorized polygons
  PolygonBuilder->>Viewer: Opaque layerBaseCutPolygons
  Renderer->>Renderer: Render layer slices double-sided (no cull)
  Viewer->>Viewer: Render base first, then per-layer colors
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

  • LTplus-AG/ifc-lite#1176: Both PRs modify the material-layer slicing/rendering pipeline—this PR removes interface capping and changes layer-slice rendering to double-sided, while the retrieved PR covers related per-layer slicing and backface-culling changes—so they overlap on how "layer slices" are constructed and rendered.

Suggested labels

geometry, rust

Poem

🐇 No more ghost faces haunting the walls,
Each layer now carved with no caps at all!
The loop walks both ways—head, tail, and chord—
Open bands close tight, by the interface moored.
Base polygons backstop the 3D overlay,
Double-sided slices render the day! 🏗️

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: fixing material-layer walls to emit watertight geometry without spurious doubled ghost faces, which is the primary objective across all modified files.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/layer-wall-watertight-section

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ac3ceeb32c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread rust/geometry/src/router/layers.rs
…eview)

Codex review: the watertight-bands change dropped the section fill of an INTERIOR
layer of a 3+ layer wall. Such a band has no wall face — its plan section is two
disconnected end strips that no single chain can close — so the bidirectional
loop builder, which closes a 2-layer U-band fine, emitted nothing for the core.

The PolygonBuilder now collects band fragments that are too short to close on
their own and stitches them end-to-end at the interface chords, only closing a
chain on itself once no other fragment remains (merging across-first matters: an
interior band is thin, so its interface chord is longer than the band thickness,
and a naive nearest-endpoint close would collapse the band). Fragments that
already close into a non-degenerate loop on their own (a 2-layer U-band, the
finish-on-both-faces case) stay separate, so existing per-loop behaviour is
unchanged. Scoped to multi-material (per-layer) groups only.

Adds a 3-layer regression test (the core layer fills with the correct area); all
46 drawing-2d tests pass.
@louistrue

Copy link
Copy Markdown
Collaborator Author

viewer now messes up multilayer display...

@louistrue louistrue marked this pull request as draft June 22, 2026 14:22
@louistrue louistrue added the bug Something isn't working label Jun 22, 2026
Since #1311 each material layer is emitted as an OPEN band (watertight
union, no doubled interface sheet), so the 3D section cap re-closes each
band at its interface chords. On a wall with a door/window opening, an
interior layer (no broad face) sections into 4+ disconnected vertical
strips, and the greedy nearest-endpoint stitch hopped one strip to the
strip ACROSS the opening — one self-overlapping polygon that bridged the
void and failed to triangulate. The cut then read HOLLOW, which is what
"the whole wall looks hollow in 3D section view" was.

Close open bands along the interface LINES instead: detect the band's
principal (length) axis via the endpoint covariance (robust to rotated
walls), cluster endpoints onto the <=2 parallel interface lines, and pair
them CONSECUTIVELY along each line (a scanline rule). That closes every
solid chunk and leaves the opening between chunks empty. Ambiguous,
near-square endpoint clouds fall back to the previous stitch, so no case
regresses.

Tests: new polygon-builder-opening suite (2-layer + opening, 3-layer
interior core + opening, rotated wall); full drawing-2d 49/49 green.
… hollow

The per-layer cap is reconstructed from open (cap-free) layer bands, so an
exotic wall the reconstruction cannot disambiguate can still leave a gap and
the 3D section cut reads see-through. Add a backstop that guarantees a solid
cut regardless.

For every MULTI-material entity, also build its full closed cross-section
(buildBasePolygons): combining all of an entity's cut segments drops the open
interfaces and leaves the watertight outer skin, which closes into the solid
chunks with no interface stitching needed. This base is carried in a NEW
Drawing2D.layerBaseCutPolygons that ONLY the 3D section overlay reads, so the
flat 2D drawing, SVG export, and measure/snap paths are untouched.

The overlay triangulates polygons in array order into one draw, so the viewer
prepends the (colourless => opaque uniform cap fill) base polygons before the
per-layer colours: the colours show where they reconstruct, and solid cut
material shows everywhere else. Net effect: per-layer colour where possible,
never a hollow-looking cut.

Tests: buildBasePolygons suite (full section per layered entity, opening stays
empty, none for single-material); full drawing-2d 51/51 green; drawing-2d +
changed viewer files typecheck clean.
…t hollow

Multilayer walls read HOLLOW in normal (uncut) 3D, not only in section. Root
cause: the renderer backface-culled material-layer slices (the culledPipeline,
cullMode 'back'), assuming their winding was reliably outward. That held for the
OLD closed per-layer slabs, where the cull hid the coincident interface caps
that would otherwise z-fight. Since #1311 the slabs are OPEN bands whose union
is the wall's watertight outer skin (no caps), and IFC winding is not reliably
outward, so culling dropped every inward-wound face and punched holes into the
skin — the wall looked like a thin see-through shell.

Render layer slices DOUBLE-SIDED like all other IFC geometry: every face of the
watertight skin draws, so the wall reads solid. With no coincident caps left
there is nothing to z-fight, so the dedicated culled pipeline and the isLayer
batch flag that selected it are removed. GEOM_CLASS_LAYER_SLICE stays — it now
only marks per-layer section fills, not culling.

renderer + spatial typecheck clean; drawing-2d 51/51. element.rs change is the
stale-comment update only (no code change).
@louistrue louistrue marked this pull request as ready for review June 23, 2026 13:21
@louistrue louistrue merged commit 207a4fb into main Jun 23, 2026
23 of 24 checks passed

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ffe5ac50dc

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +2 to +3
"@ifc-lite/drawing-2d": patch
"@ifc-lite/renderer": patch

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Bump the wasm package for the slicer change

When this changeset is published, only @ifc-lite/drawing-2d and @ifc-lite/renderer receive new versions, but the mesh-slicing fix lives in rust/geometry/src/router/layers.rs and is shipped to npm through @ifc-lite/wasm. Consumers can therefore get the new renderer that deliberately stops culling layer slices while still resolving the old wasm runtime that emits capped, coincident layer slabs, reintroducing the z-fighting/hollow wall case this PR fixes. Add a patch bump for @ifc-lite/wasm (and the dependent geometry package if releases rely on it) so the renderer and wasm geometry stay in lockstep.

Useful? React with 👍 / 👎.

Comment on lines +105 to +108
const colors = new Set(entitySegments.map((s) => colorKey(s.color)));
if (colors.size < 2) continue;
// Colourless build ⇒ closed-loop path (the combined section is closed).
const base = this.buildColorGroupPolygons(entitySegments, undefined)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Gate base caps to true layer bands

This treats every multi-colour cut as a material-layer wall, but DrawingPolygon.color is also used for non-layer splits such as a frame+glass window. In that case buildBasePolygons() emits a colourless base polygon behind the transparent glass/frame parts; useRenderUpdates uploads that base without a material colour, so the shader fills it with the opaque cap style before blending the glass polygon, making transparent window cuts read as opaque solid material. Restrict the base backstop to actual layer-slice entities instead of colors.size > 1 alone.

Useful? React with 👍 / 👎.

louistrue added a commit that referenced this pull request Jun 23, 2026
#1311 changed rust/geometry + rust/processing (compiled into @ifc-lite/wasm)
but the changeset only listed @ifc-lite/drawing-2d and @ifc-lite/renderer.
`changeset publish` only publishes packages whose local version is not already
on npm, so the new wasm mesh generation would never reach npm consumers and the
hollow-wall fix in the release notes would not actually ship. Add @ifc-lite/wasm
to the changeset. @ifc-lite/geometry needs no bump: it builds with tsc and
imports @ifc-lite/wasm as an external runtime dependency (workspace:^), so
consumers pick up the republished wasm transitively at install time.

Mark @ifc-lite/viewer private. apps/viewer is a Vite app deployed via Vercel,
not a library: it has no main/module/exports/bin entry point, so the published
package is unusable as a dependency. It was never marked private (unlike its
sibling app @ifc-lite/viewer-embed), so every release dumps a ~29MB / 1100-file
tarball of the whole app tree (full src/, built dist/ incl. the Cesium asset
bundle, configs, a stray .turbo build log) to npm with zero consumers. The real
consumable viewer library is @ifc-lite/viewer-core. The #1311 overlay change in
apps/viewer ships via Vercel deployment from main, not via npm, so the viewer
does not belong in the changeset. Existing npm 1.x versions are left in place.

Verified with `changeset version`: bumps wasm 2.13.0->2.13.1,
drawing-2d 1.18.3->1.18.4, renderer 1.29.1->1.29.2; viewer is not versioned or
published (private + absent from the changeset).
louistrue added a commit that referenced this pull request Jun 23, 2026
#1328)

#1311 changed rust/geometry + rust/processing (compiled into @ifc-lite/wasm)
but the changeset only listed @ifc-lite/drawing-2d and @ifc-lite/renderer.
`changeset publish` only publishes packages whose local version is not already
on npm, so the new wasm mesh generation would never reach npm consumers and the
hollow-wall fix in the release notes would not actually ship. Add @ifc-lite/wasm
to the changeset. @ifc-lite/geometry needs no bump: it builds with tsc and
imports @ifc-lite/wasm as an external runtime dependency (workspace:^), so
consumers pick up the republished wasm transitively at install time.

Mark @ifc-lite/viewer private. apps/viewer is a Vite app deployed via Vercel,
not a library: it has no main/module/exports/bin entry point, so the published
package is unusable as a dependency. It was never marked private (unlike its
sibling app @ifc-lite/viewer-embed), so every release dumps a ~29MB / 1100-file
tarball of the whole app tree (full src/, built dist/ incl. the Cesium asset
bundle, configs, a stray .turbo build log) to npm with zero consumers. The real
consumable viewer library is @ifc-lite/viewer-core. The #1311 overlay change in
apps/viewer ships via Vercel deployment from main, not via npm, so the viewer
does not belong in the changeset. Existing npm 1.x versions are left in place.

Verified with `changeset version`: bumps wasm 2.13.0->2.13.1,
drawing-2d 1.18.3->1.18.4, renderer 1.29.1->1.29.2; viewer is not versioned or
published (private + absent from the changeset).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant