The Rust purity state is the whole source B-rep, gap caches included, but
the native snapshot never observed the vertex-use and edge-use gap caches.
On the Fillet box_diff_cyl / cyl_on_box_w_fillet sources both kernels reset
the same 8 vertex/face gap caches on the source (CalcVertexFaceGap resets
every same-face use before caching its own), so the C++ side reported pure
and the Rust side impure.
The shim now emits per vertex use the vertex/edge and vertex/face gap init
flags with their edge t / face UV, and per edgeuse the max edge/face gap
init flag, read only through already-initialised caches. input.pure
compares them before/after. Adds the 66 Fillet DoSolidOffset cases
(fillet_files.json) and a unit test that a reset cache alone breaks purity.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MNXLXj2sJf943y2dDF36Vy
ShellBrep's sheet branch builds each side wall as the ruled surface between
a lamina edge and its offset. A flat wall never becomes a plane, so a
thickened cylinder sheet's end rings come back as SmSurfOfRevolution.
This ports the fork's tangency-labs/smlib#62 (d384e86) behind a new opt-in,
UpstreamFixes::thicken_planar_side_walls. With it, every planar wall goes
onto an exact plane (sm_PutPlanarFaceOnItsPlane), and the seam the old
surface leaves as a slit is then deleted, which splits the ring into its two
circles. The #978 merge stays behind ShellOptions::merge_sheet_side_walls.
Adds a difftest cylinder-sheet fixture (shim kind 8): C++ gives the same
non-planar rings as the Rust default.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MNXLXj2sJf943y2dDF36Vy
offset_brep, OffsetExecutive::shell_brep and api_shell_brep_full copy the source's
own attributes into the caller's stores under original_key_of and hand the lists of
the returned B-rep's live objects back to it (the result arena under result_key_of,
an inset shell's original arena under original_key_of). A merging PiecewiseMerge's
B-rep takes the result identities, so its lists move there; a merge's surface map
is not a topology attribute and is dropped. New offset_brep_simple and
shell_brep_simple build the notification identities themselves.
Regression test tests/issue_1462_offset_attributes.rs; the offset p2 runner gains
an attributed mode (fixtures/offset.offset_executive_p2/attributed.json, 48 cases).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MNXLXj2sJf943y2dDF36Vy
The p2 runner gets a `file` source fixture: an ASCII .smb read by
SmBrep::ReadFromFile in the shim (kind 7, path bytes in the f64 protocol)
and imported through the topology.brep_p1 export on the Rust side, keeping
the file's tolerance as smOffsetTest.cpp's ShellBrep does. Selections now
index the native GetFaces list (face_list), which a file import's arena
order need not follow.
34 cases (shell_files.json) from TestFiles/pt_TestFiles/Shell: the
smOffsetTest.cpp ShellBrep set (extend corners and rounded), MateEdges with
two intersection curves (problemShell15 faces 8 and 9), and the two
divergences below. All agree with C++.
Fixes:
- sweep store register_empty_ssi: a PiecewiseMerge skip pair naming a
surface whose face no longer exists in any body returned "not a surface
owner"; upstream registers the pointer, which never matches, so the pair
is skipped (13+ rounded-offset cases errored in Rust, C++ succeeded).
- BuildOffsetOfFaceuse's 2D domain Boolean ran inside the kernel-context
lend and failed with "nested edit"; Context::with_lease_returned gives
the callbacks back to the kernel context for the temporary B-reps and
the Boolean (upstream has one context).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SdcgEtgaA54W2nr8dK1EYp
Adds SmApiCreateCylinder and SmApiCreateSphere fixtures (and their ports)
to the p2 runner, and 36 cases offsetting them (rounded, extend-corner and
direct extended offsets, API offset/shell, insets past the radius, tiny
and huge scales, shell faces). The cylinder seam and the sphere's closed
face are tangent sectors, so the extend-corner pass of DoExtendedOffset
now runs against C++. The input projection classifies face and edge kinds
with the shim's IsKindOf classes on both sides (a cone or sphere is an
SmBSplineSurface).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SdcgEtgaA54W2nr8dK1EYp
offset_executive_p2: tiny/far-translated boxes build as an empty B-rep and
merged/dropped-face sheets as a degenerate face; both are defined native
results (no crash, hang or UB) and are now built and compared on both sides.
Only a selection of the nonexistent face 0 stays rejected (nothing to run).
trans_sweep_geometry: a curve constructor failure status is compared with
Rust's instead of rejected; null curves are never passed to
CreateWireEdgeFromCurve.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011gJAwcLRBPQXYLmvXd3pWf
Preserve caller notification identities and records through the production Boolean adapter, including record restoration on unwind. Respect signed operand order and actual retained ownership on deferred exits. Keep automatic constructor tolerances with their owning unit, add native sheet/wire topology guards and regression fixtures, and preserve notification-aware p7 calls after merging main.
Co-Authored-By: GPT-6.1-Sol <noreply@openai.com>
Wire real region and face-construction APIs, share edge preparation and gap handling with part 1, reject incomplete native box construction, and add regression coverage with fresh differential evidence.
Co-Authored-By: GPT-6-Astra <noreply@openai.com>