# Primitives and Projection Checkpoint ## Latest Continuation: 2026-09-17 17:57 UTC Batch `4aa3ea5e85f9c4b3e4412ba2`; both selected commands remain incomplete. This continuation completes primitive subelement vertex snapping. Earlier requirements and deferred cases below remain in force except where explicitly superseded by the verified behavior here. - `DocumentProbe.cpp` now serializes unique OCCT vertices from the existing transformed display shape when builder geometry is requested. Vertices retain native precision and world placement. The document facade validates finite triples and agreement with the native topology count. - The mounted primitive task passes these coordinates into the existing Three.js view. Its optional vertex picker uses a 10 CSS pixel radius and mesh occlusion checks, returns the exact native point, and consumes misses without changing the draft primitive or its name. Surface picking remains independently usable. Callback refs avoid rebuilding the scene when arming/disarming a pick. - Extended `tools/part-circle-vertex-picking-business-cases.mjs`: a plane rotated 90 degrees and translated 4 mm exposes four expected world vertices; desktop and mobile clicks offset by 3 pixels snap to the exact vertices. Face-interior clicks keep the gate armed and fields unchanged. Creating the arc asserts radius sqrt(200), a 180-degree interval, native endpoints, valid topology, no pre-create document/history changes, and atomic undo/redo. - Existing standalone vertex, surface pick, cancel, OPFS/FCStd, desktop/mobile canvas pixel and layout assertions remain executable and completed. Validation: - `web/node_modules/.bin/tsc --noEmit -p web/tsconfig.json` passed. - Focused `FreeCADWebDocumentProbe` build passed using `python3 tools/build_web_module_artifacts.py --target FreeCADWebDocumentProbe --jobs 8 --timeout 240`. - `node web/tools/sync-assets.mjs` copied three files, skipped 101, and updated the manifest in 3.549 s. Existing server at `http://127.0.0.1:5180` was reused. - Combined unchanged runner invocation for both selected IDs produced `business-evidence/32e5a354bbd763bd5df41ad4-20260917T175628274821.json` in 21.338 s. Projection completed five assertions, including native linked geometry/recompute/FCStd and mounted desktop/mobile cases, with no case error. Primitive failed only in the new test's comparison of create versus read response metadata (`createdObject` versus `attachmentEditing`). Fixed the new fixture to capture its baseline with a read; no old assertion was relaxed. - Isolated runner invocation `python3 tools/run_business_acceptance.py --module Part --ids Part:desktop:Part_Primitives --reuse` produced `business-evidence/13fb362e5bcf598a7f1f90a6-20260917T175702364139.json` in 15.127 s. All four recorded scenario groups passed, browser and cleanup completed. Native browser load took 2.391 s; the new subelement stage took 2.487 s. The runner correctly returns `acceptance_incomplete`, exit 1, zero completed commands, because the remaining requirements are explicit. - Screenshots and detailed results: `part-circle-vertex-picking-business/2026-09-17T17-56-47-560Z/`. `subelement-vertices.png` and `mobile-canvas.png` were visually inspected and show the native arc/plane and vertex geometry. No blank viewport was observed. Next work: 1. Primitives: desktop location picking, expression binding and task lifecycle. Reuse completed three-point circle, vertex/surface picking, all sixteen primitive types, placement/container and cylinder skew implementations. 2. Projection: task activation/live preview transaction, commit on accept, rollback on reject, and viewport face/edge/wire selection gates. Its existing linked-object workflow completed again after this native snapshot change. 3. Preserve all deferred legacy scenario lists. This focused turn did not rerun every primitive type or every projection mode. Mesh occlusion is implemented for snapping; a dedicated overlapping-solids occlusion fixture remains useful. Arbitrary nested/scaled-link vertex snapping was not separately exercised. No acceptance machinery, contract, verifier, proof requirements, passing status or coverage tag was edited. `docs/business-acceptance/Part.json` still matches the supplied packet hash `86146084d148d0fa402a8af92d00f5cc5fff0fed08985a649c17567d75faf084`. No IFC implementation or claim was made; the IFC semantic export contract stays in force. No full-parity/API gate, deployment, push or external message occurred. Current implementation hashes: | File | SHA-256 | | --- | --- | | DocumentProbe.cpp | d09993d329e8c2683ba6a58ae1fde7af3999229d8c511280f780c7ba23842d1d | | part-document-facade.ts | 7ee5d7193f3d698b392acb0b27bf7565c0b63f476ac1fc9972b23c9b3a01289d | | openscad-desktop-view.tsx | f0fe640b02c9d7a2caa5002876205960b090e18657354cd1ddece451977a8126 | | part-primitives-task.tsx | 160d64713b89ba4ea75a6e965267c3d64b09a6914f83cbb8eae242c42aa33d5f | | part-circle-vertex-picking-business-cases.mjs | dcbddef086cc311f3c176ebb071fb60a369cf30fdecf03ce1bf8f3050ed68bff | | FreeCADWebDocumentProbe.wasm | e5721f7be1c7146b76711148150887c1ec58974fc5b28b33f370f9edbe31d6c0 | ## Earlier Checkpoints Primitive continuation at 11:07 UTC: [Cylinder skew](PART_CYLINDER_SKEW_PROGRESS.md) is now implemented with nine completed new scenario groups. Keep the container/link work below; next primitive gaps are three-point circle picking, location/expression UI and live task lifecycle. Full command acceptance remains incomplete. ## Latest Continuation: 2026-09-17 10:51 UTC Batch `4aa3ea5e85f9c4b3e4412ba2` remains incomplete for both selected IDs. This update supersedes the historical placement/container and linked-object gaps below only to the extent of the concrete checks described here. All other original and supplemental requirements remain in force. ### Implemented and Reused - Reused the mounted primitive/projection tasks, Part adapter, document facade, existing OCCT geometry and `FreeCADWebDocumentProbe` owner. No dispatcher or frontend application changes were needed. - Fixed `DocumentProbe.cpp` snapshot serialization: linked objects now resolve through `Part::Feature::getTopoShape(ResolveLink | Transform)` and expose native topology, edge samples and face meshes while retaining App::Link identity. This fixes the actual browser SupportLink selector timeout. - Feature display shapes apply the official `GeoFeature::getGlobalPlacement` parent transform, removing the already-applied local placement before composition. Mesh positions/normals/bounds, edge samples and vertex markers now share world placement. Editable feature placement stays local. - Extended `tools/part-primitive-container-business-cases.mjs` with translated and rotated nested Parts, root-object invariance, local rotation/translation, analytic mesh/edge/point coordinates, FCStd reopen, browser OPFS/history, desktop/mobile canvas pixels and orbit movement. - Extended `tools/part-linked-projection-business-cases.mjs` with link snapshot topology/mesh assertions, actual mounted support/source selection and native projection, plus desktop/mobile render and selector bounds checks. Existing link recompute, invalid-subelement rollback and FCStd assertions remain. ### Build and Attributable Evidence - Focused build succeeded: `python3 tools/build_web_module_artifacts.py --target FreeCADWebDocumentProbe --jobs 8 --timeout 240` (one target passed). - `node web/tools/sync-assets.mjs` completed in 3.481 seconds: three files copied, 101 skipped; JS/WASM/worker artifacts and manifest synchronized. - Ran `python3 tools/run_business_acceptance.py --module Part --ids Part:desktop:Part_Primitives Part:desktop:Part_ProjectionOnSurface --reuse`. Current report: `business-evidence/32e5a354bbd763bd5df41ad4-20260917T105057732115.json`. Runtime 30.248 seconds; all eight recorded case assertions passed, both browser stages completed, no case errors. Both case statuses deliberately remain `not_implemented`; runner reports `acceptance_incomplete`, zero passed commands, exit 1. Do not convert assertion success into command completion. - Current primitive detail and screenshots: `part-primitive-container-business/2026-09-17T10-50-27-795Z/`. Native load 0.409 s; native cases through cleanup 11.543 s; browser stage 7.497 s. Native cleanup completed before browser startup. - Current projection detail and screenshots: `part-linked-projection-business/2026-09-17T10-50-50-843Z/`. Native load 0.384 s; linked create through native cleanup 0.575 s; browser stage 3.197 s. Desktop/mobile screenshots for both workflows were inspected. - Baseline failure retained in `business-evidence/32e5a354bbd763bd5df41ad4-20260917T104612942596.json`: projection could not select SupportLink because snapshots lacked topology. Do not replay this unchanged baseline. - Scoped `git diff --check` passed. Acceptance contract, verifier, runner, proof requirements, coverage tags and passing statuses were not edited. `docs/business-acceptance/Part.json` still hashes to `f0fd2e6fd7e90f2f4c8cbb72b0f4cb1496e6cea76db149e3777707782816ac04`. Current fingerprints (full input/artifact hashes also retained in case reports): | File | SHA-256 | | --- | --- | | DocumentProbe.cpp | 968b3acd508837e35cf59421c5ae3cd37fbfb3df665580be2aa240d621470e9b | | part-primitive-container-business-cases.mjs | 9bea0d5695703ae9a0622aedc4cb9ad4de8c87128e8cc91f7c13b23fc1e3d453 | | part-linked-projection-business-cases.mjs | b772bfb1bd02a1472ccb3922e69edf0e631d07fb5bdaf2a793c543e9b2d2fd0f | | FreeCADWebDocumentProbe.wasm | b54714854c49f805eeee4b788c5b7921a0c53788a1a4918ac2c3295c8ee4439f | ### Next Work 1. Projection still needs a desktop preview transaction spanning task activation, live updates, accept/commit and reject/rollback, plus viewport subelement selection gates. Start at `PartProjectionDocument.h`, the native document transaction lifecycle, `executePartProjectionDesktop` and the mounted task. The linked-object selector failure is fixed; do not implement it again. 2. Primitives still need cylinder skew, circle from three points, desktop expression binding and live task-lifecycle behavior. Sixteen primitive types, placement and active-container membership/display already have implementations and executable cases; reuse them. 3. Current focused cases preserve their explicit deferred legacy case lists. This run did not rerun every primitive type, every projection mode or arbitrary nested/scaled links. Retain all prior cases and original requirements when completing the commands; no full-parity/API gate is authorized. 4. The packet's preflight still lists these commands as missing coverage. Do not edit the contract or add coverage labels to bypass the remaining behavior. Implement the next missing behavior, then invoke the unchanged acceptance runner for attributable evidence against stable files. Reuse the running local server at `http://127.0.0.1:5180`; no new server was started. No IFC behavior, contract or verifier was changed, and no IFC semantic claim is made. No deployment, push or external message occurred. ## Earlier Checkpoint (Retained) Primitive status is superseded by [Helix and Spiral progress](PART_HELIX_SPIRAL_PROGRESS.md): all sixteen types are exposed; continue with placement/container and remaining task interactions, not the historical missing-type list below. Preserve the earlier evidence without replaying its completed cases. Batch `4aa3ea5e85f9c4b3e4412ba2`, 2026-09-17. Selected: `Part:desktop:Part_Primitives` and `Part:desktop:Part_ProjectionOnSurface`. Both remain incomplete. ## Delivered This Turn - Added the mounted Projection task's Use camera direction button. It reads the current viewport camera direction, including after orbit interaction, into the existing direction fields. Apply continues through the existing Part adapter, document facade, Worker and native Part::ProjectOnSurface geometry route. - Added an optional direction callback to `web/src/openscad-desktop-view.tsx`, using a ref so observing camera movement does not rebuild the scene. The task consumes it in `web/src/part-projection-task.tsx`. - Desktop source semantics: `DlgProjectionOnSurface.cpp`, `DlgProjectOnSurface::onGetCurrentCamDirClicked` around line 1406 transforms camera-local (0,0,-1) and sets Direction. Existing axis buttons remain intact. - Extended `tools/part-projection-business-cases.mjs` with actual camera orbit interaction, analytic cylindrical-support edge projection, radius-driven recomputation, FCStd reopen and subsequent radius edit, and indirect source and support cycle rejection through two dependent compounds. - Curved fixture checks one valid edge, length 3, y=3, z endpoints 2 and 5, x=sqrt(radius^2-9) for radii 5, 6 and 7, and exact native projection links. Cycle cases require an explicit cycle error and unchanged document snapshots, geometry, links, undo history and second document. - Existing DocumentProbe WASM was reused. No native build or artifact sync was necessary. No acceptance contract, runner, verifier, proof requirements or passing status was modified; no coverage tags were added. ## Attributable Execution Both isolated commands used `python3 tools/run_business_acceptance.py --module Part --ids --reuse`. Each returned `acceptance_incomplete`, exit 1, with the case result `not_implemented` because the explicit remaining requirements below are still open. Neither command is counted as passed. | Command | Assertions | Seconds | Evidence in docs/current/business-evidence | | --- | --- | --- | --- | | Part_ProjectionOnSurface | 34 passed, 0 failed | 21.576 | 7eb5ff3f52f792bd7cf89e8e-20260917T070842519089.json | | Part_Primitives | 31 passed, 0 failed | 78.753 | 13fb362e5bcf598a7f1f90a6-20260917T071048395612.json | Both reached browser-complete and cleanup-complete. Projection native load took about 0.404 s, native projection through curved/persistence checks about 8.532 s, and browser work about 9.029 s. Primitive native load took about 0.409 s, native fixture/history/persistence work about 31.476 s, and browser work about 45 s. Projection screenshots at widths 1440 and 390 were generated with canvas-pixel and overflow assertions and visually inspected. They are under `docs/current/part-projection-business/2026-09-17T07-08-21-248Z/`. They show the native support, source and extruded projection without overlap. TypeScript passed with `web/node_modules/.bin/tsc --noEmit -p web/tsconfig.json`. Scoped `git diff --check` passed. The first combined baseline run was invalidated by source edits made while it was running; do not use it as current evidence. The first isolated Projection run failed at the existing exact FCStd object comparison after the newly added curved fixture caused normal remeshing roundoff/reordering. That failure remains in `7eb5ff3f52f792bd7cf89e8e-20260917T070716119724.json`. The new curved fixture was moved after the unchanged original persistence assertions and given its own analytic persistence and dependency assertions. Existing assertions were not relaxed or removed. The subsequent stable run above completed all assertions. ## Remaining Work and Next Anchors Projection: - Desktop preview transaction: create on task activation, recompute live edits, commit on accept, and abort all task edits on reject. Current Apply commits separate edits; Close does not implement desktop preview rollback. - Viewport subelement selection gates. Current controls select named topology; viewport picking selects objects only. - Linked-object projection behavior and executable cases. Current native `PartProjectionDocument.h` resolver requires Part::Feature even though shape extraction uses ResolveLink. Desktop `FeatureProjectOnSurface.cpp` getSupportFace also requests Part::Feature; examine actual link semantics before changing either owner. No link support was claimed this turn. Primitives: - Prism, Wedge, Helix, Spiral, Circle, Ellipse, Polygon, Line and Vertex. - Placement/orientation and active-container semantics. - Existing Plane, Box, Cylinder, Cone, Sphere, Torus and Ellipsoid workflows passed their current cases; do not rebuild or recreate these implementations. - Relevant anchors: `DocumentProbe.cpp` primitiveProperties around line 170, setPrimitive validation/property assignment around line 1328; `part-document-facade.ts` PART_PRIMITIVE_FIELDS and validation around line 363; `part-primitives-task.tsx` defaults/type picker; adapter executePartPrimitivesDesktop around line 739; runPrimitiveTaskCases in `tools/part-primitive-business-cases.mjs` around line 26. Continue by implementing a missing behavior above, then run only the affected isolated acceptance case against stable files. Do not replay unchanged cases to refresh timestamps. Preserve all original and supplemental requirements, including `docs/current/IFC_SEMANTIC_EXPORT_CONTRACT.md`; no IFC work or semantic completion was claimed here. No full-parity/API gate, deployment, push or message to others was performed. Existing local server reused: `http://127.0.0.1:5180`. Projection task: `/workbench.html?module=Part&command=Part_ProjectionOnSurface`.