diff --git a/CLAUDE.md b/CLAUDE.md index b14432e..5671187 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -135,8 +135,7 @@ follow-up PR by regenerating `Package.resolved` from an isolated, sibling-free c [full decision entry](okf/decisions/occtswift-3.0.0-floor-bump-blocked-on-cohort-releases.md) for the timeline. Previously **floored at v2.0.0** (OCCTSwiftScripts#111): a correctness major (17 breaking changes to the public Swift API; see `docs/SEMVER.md#v200` in the OCCTSwift repo). Two fixes landed in this repo alongside that bump: (1) `ShapeAnalysisResult.selfIntersectionCount` was removed (#763; always `0`, never computed), so `Heal.swift`/`GraphValidate.swift` now report `hasSelfIntersection`/`selfIntersecting` as `Bool?` via the real, opt-in `Shape.analyze(selfIntersectionTimeout:)` check (`nil` = "not checked" by default, since the check is ~3000x an ordinary scan on pathological input and both verbs would run it twice), rather than the fabricated always-`0`/always-`false` the removed field silently produced. (2) AAG builds nodes from face **occurrences** (#642): `AAGNode.faceIndex` / `PocketFeature.floorFaceIndex`/`wallFaceIndices` / `detectHoles()`'s `faceIndex` / `AAGEdge.face1Index`/`face2Index` now index `Shape.orientedFaces()`, not the `Shape.faces()` `face[N]` scheme `query-topology` emits (the two agreed automatically pre-2.0.0, since `faces()` was itself occurrence-based then). `FeatureRecognize.swift` (both the `occtkit` command and the legacy standalone target), `GraphSelect.swift`, and `GraphML.swift` all cross-reference AAG output against that `face[N]` scheme and now resolve through the new `AAGNode.distinctFaceIndex` bridge; a no-op on any shape that shares no face (every single-solid part, the only kind this repo's pre-#111 tests exercised), so it only bites a multi-solid compound with a shared face, exactly the shape a caller runs `feature-recognize`/`graph-select`/`graph-ml` against to look for cross-solid structure. `Tests/OcctkitCommandTests/AAGFaceIndexTests.swift` regression-tests the fix directly against `graph-select`/`graph-ml`'s JSON output on a split-box-compound fixture. Before that, **floored at v1.17.0** (raised in d5d31e8 for the OCCTSwift#377/#380 Pass 1a duplication and bug-fix audit; also carries the `Shape.drilled` direction fix, OCCTSwift#272, which lands between 1.12.0 and 1.12.9 and corrected recipe 01's through-holes). Before that, **floored at v1.15.0**: v1.15.0 renamed the Swift wrapper class `TopologyGraph` → `BRepGraph` (OCCTSwift#335) to match the C++ package it wraps; this repo has migrated off the deprecated `TopologyGraph` typealias onto `BRepGraph` directly (OCCTSwiftScripts#78), so the floor must guarantee the `BRepGraph` symbol exists. Earlier, v1.7.0 realigned the BRepGraph wrapper to OCCT's redesigned graph model (definitions vs references/usages, persistent UIDs, controlled layers) and v1.7.1 made the derived graph reads real again: `adjacentFaces`/`faces(of:)`/`edges(of:)`/`sharedEdges`, `faceSameDomain`, `faceIsNaturalRestriction`, plus durable `UID`/`RefUID`/`ItemUID` identity. Our graph verbs (graph-validate/compact/dedup/ml, query-topology) build and run **unchanged** against it. Behaviour changes are **confined to the BRepGraph domain**: `edgeMaxContinuity`/`setEdgeRegularity` are now no-ops (use `Shape.maxContinuity` for continuity); `degenerated`/`closed`/`sameParameter`/`sameRange` setters no-op while their getters return the live derived value. The cookbook ergonomics relied on since v1.3.1, namely `Shape.circularPatternCut` (#169), orientation-normalised `Shape.sweep` + `orientedForward`/`signedVolume` (#170), `concaveEdges`/`convexEdges`/`edges(where:)` selectors (#171), are unchanged. The 2.0.0-bump-era cohort gap (OCCTSwiftIO/Tools/AIS/Mesh all still on their "repin to 1.17.0" floors, blocking remote resolution) resolved by 2026-08-10, when OCCTSwiftIO v1.7.7, OCCTSwiftTools v1.6.3, and OCCTSwiftMesh v1.7.3 each shipped their own "repin OCCTSwift to 2.0.0" release; see the v3.0.0 cohort-gap note above this paragraph for the current (unresolved as of this writing) equivalent. - **OCCTSwiftViewport**: `https://github.com/gsdali/OCCTSwiftViewport.git` (>= 1.0.0). Provides `OffscreenRenderer`, `CameraState`, `DisplayMode`, `ViewportBody` for `render-preview`. Graduated to v1.0.0 on 2026-05-08, one day after the rest of the cohort; floor unblocked by Tools v1.0.2 (closes #45). -- **OCCTSwiftTools**: `https://github.com/gsdali/OCCTSwiftTools.git` (>= 1.0.0; resolves to v1.0.2+ for the widened Viewport constraint). Bridge layer between the B-Rep kernel and the Metal viewport. We use `CADFileLoader.shapeToBodyAndMetadata` in `render-preview` for Shape → `ViewportBody` conversion (both input bodies and highlight sub-shapes). Lives in its own repo since Viewport v0.55.0 split. -- **OCCTSwiftAIS**: `https://github.com/gsdali/OCCTSwiftAIS.git` (>= 1.0.0). Headless-friendly subset only: `Trihedron` / `WorkPlane` / `Axis` / `PointCloud` scene objects (each emits `[ViewportBody]` via `makeBodies()`) for `render-preview`'s `--show-axes` / `--show-workplane` overlays, plus the SubShape selection vocabulary for `--highlight face[N]/edge[M]/vertex[K]`. Selection / Manipulator / SwiftUI surfaces aren't relevant to a CLI. `Dimension` overlays render via a SwiftUI Canvas inside `MetalViewportView` and so can't reach `OffscreenRenderer`, so `--annotate-dimensions` is deferred (filed as OCCTSwiftViewport#26). Note: `OCCTSwiftAIS` re-exports a `DisplayMode` enum (3 cases) that collides with `OCCTSwiftViewport.DisplayMode` (6 cases); fully-qualify in `RenderPreview.swift` as `OCCTSwiftViewport.DisplayMode`. +- **OCCTSwiftInteraction**: `https://github.com/SecondMouseAU/OCCTSwiftInteraction.git` (>= 0.1.0). Vends `OCCTSwiftTools` and `OCCTSwiftAIS` as two of its three SwiftPM targets/library products (the third, `OCCTSwiftCADKit`, the assembled SwiftUI viewport service, is not named by anything here and so never enters this build). **Migrated from the standalone `OCCTSwiftTools`/`OCCTSwiftAIS` repos** (OCCTSwiftScripts#122) after those two and `OCCTSwiftCADKit` merged into this one package (SecondMouseAU/ecosystem#42, #43): the three old repos are archived, not deleted, and their tags still resolve, but SwiftPM enforces target-name uniqueness across the whole transitive package graph before any per-consumer product pruning, so a graph containing both this repo and anything depending on `OCCTSwiftInteraction` directly (OCCTMCP, blocked on this for OCCTMCP#182) hit a hard resolution error, not a version-range conflict, until this repo's `occtDep` entries and `package:` labels moved off the old names. Per `OCCTSwiftInteraction`'s `docs/MIGRATION.md`, module names are unchanged: `import OCCTSwiftTools` / `import OCCTSwiftAIS` still work, since each target's identity was preserved across the merge. `OCCTSwiftTools` is the bridge layer between the B-Rep kernel and the Metal viewport: we use `CADFileLoader.shapeToBodyAndMetadata` in `render-preview` for Shape → `ViewportBody` conversion (both input bodies and highlight sub-shapes). `OCCTSwiftAIS` is used for the headless-friendly subset only: `Trihedron` / `WorkPlane` / `Axis` / `PointCloud` scene objects (each emits `[ViewportBody]` via `makeBodies()`) for `render-preview`'s `--show-axes` / `--show-workplane` overlays, plus the SubShape selection vocabulary for `--highlight face[N]/edge[M]/vertex[K]`. Selection / Manipulator / SwiftUI surfaces aren't relevant to a CLI. `Dimension` overlays render via a SwiftUI Canvas inside `MetalViewportView` and so can't reach `OffscreenRenderer`, so `--annotate-dimensions` is deferred (filed as OCCTSwiftViewport#26). Note: `OCCTSwiftAIS` re-exports a `DisplayMode` enum (3 cases) that collides with `OCCTSwiftViewport.DisplayMode` (6 cases); fully-qualify in `RenderPreview.swift` as `OCCTSwiftViewport.DisplayMode`. - **OCCTSwiftMesh**: `https://github.com/gsdali/OCCTSwiftMesh.git` (>= 1.0.0). LGPL-2.1 wrapper that vendors `meshoptimizer` (BSD-2-Clause / MIT-equivalent) inside `OCCTMeshOptimizer` for QEM decimation. Powers `simplify-mesh` via `Mesh.simplified(_:)`. Smoothing / repair / remeshing are future work. - **OCCTSwiftIO**: `https://github.com/gsdali/OCCTSwiftIO.git` (>= 1.7.5). Provides `BRepGraph.exportForML` / `exportJSON` via extension after OCCTSwift v0.171.0 hoisted them out of the kernel. **Pulled into the `GraphML` standalone target and the `graph-ml` verb only**; the rest of the package keeps its existing `ScriptManifest` type from `Sources/ScriptHarness/Manifest.swift` (which carries a `graphs` field that OCCTSwiftIO's `ScriptManifest` is missing). If a future verb wants progress-aware STEP loading via `ShapeLoader.load(from:format:progress:)`, broaden the dep then. **Floor raised from `>= 1.0.0, < 1.1.0` to `>= 1.7.5`** (OCCTSwiftScripts#80): the old cap (from #69, guarding against OCCTSwiftIO 1.1.0+'s heavy mesh-IO stack: SwiftPMX/SwiftX/ThreeMF/SwiftGLTF via a `MeshIO` target, plus SwiftJWW/SwiftDXF) became unsatisfiable once OCCTSwiftTools >=1.6.1 started requiring OCCTSwiftIO >=1.7.0 directly; any consumer depending on both packages at once (e.g. OCCTMCP) hit an unresolvable graph. Checked OCCTSwiftIO 1.7.5's manifest for a narrower product to preserve the cap's intent: it ships `OCCTSwiftIO` and `MeshIO` as separate library products, but the `OCCTSwiftIO` target has an unconditional target dependency on `MeshIO`, so the heavy stack is unavoidable via either product, and there's no BREP/STEP-only surface to depend on instead. Floored at 1.7.5 rather than the bare 1.7.0 Tools needs because 1.7.5 is OCCTSwiftIO's own `TopologyGraph` -> `BRepGraph` rename (mirroring OCCTSwift 1.15.0's rename above), and 1.7.1-1.7.4 are pure OCCTSwift-floor repins for crash/hang fixes already required transitively via our own OCCTSwift >=1.15.0 floor. - **macOS 15+**, **Swift 6.0+**. diff --git a/Package.resolved b/Package.resolved index fb35626..66dbd7f 100644 --- a/Package.resolved +++ b/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "2d59b7c43804ef574a87a6790e9049c573d1cceb4530b9f40490a209289fddb8", + "originHash" : "d5cea687ade4dca5bb9bc19c22be3e56cd896b4c910e451879d6f730900269c5", "pins" : [ { "identity" : "nodal", @@ -20,12 +20,12 @@ } }, { - "identity" : "occtswiftais", + "identity" : "occtswiftinteraction", "kind" : "remoteSourceControl", - "location" : "https://github.com/SecondMouseAU/OCCTSwiftAIS.git", + "location" : "https://github.com/SecondMouseAU/OCCTSwiftInteraction.git", "state" : { - "revision" : "c6fbe2b3ee9044b391e85e91df3ffee42a254b57", - "version" : "1.3.2" + "revision" : "bbeadbeae1e23a5f52f94d1d89ea3c169563c847", + "version" : "0.1.0" } }, { @@ -46,15 +46,6 @@ "version" : "1.7.5" } }, - { - "identity" : "occtswifttools", - "kind" : "remoteSourceControl", - "location" : "https://github.com/SecondMouseAU/OCCTSwiftTools.git", - "state" : { - "revision" : "d48a7c297eb6dcc0255da48a814698a292b47384", - "version" : "1.6.4" - } - }, { "identity" : "occtswiftviewport", "kind" : "remoteSourceControl", diff --git a/Package.swift b/Package.swift index a3cc9f0..37a6f64 100644 --- a/Package.swift +++ b/Package.swift @@ -131,27 +131,31 @@ let package = Package( // body load (Viewport #30) and v1.0.4 makes the published Viewport // package dependency-free (broke the Viewport↔Tools cycle). occtDep("OCCTSwiftViewport", from: "1.0.4"), - // OCCTSwiftTools v1.0.0 graduated alongside OCCTSwift v1.0.0. We use - // Tools for the bridge-layer CADFileLoader.shapeToBodyAndMetadata in - // RenderPreview, which legitimately needs Viewport, so the Tools dep - // stays. We don't separately depend on OCCTSwiftIO because - // OCCTSwiftIO's ScriptManifest is missing the `graphs` field our - // local Sources/ScriptHarness/Manifest.swift carries, the - // topology-graph descriptors that ScriptContext.addGraph() and - // addGraphsForAllShapes() emit. Swapping would silently lose that - // metadata for downstream OCCTSwiftViewport ScriptWatcher consumers. - // If a future verb wants progress-aware STEP loading via - // OCCTSwiftIO's ShapeLoader.load(from:format:progress:), add the dep - // then. - occtDep("OCCTSwiftTools", from: "1.1.1"), - // OCCTSwiftAIS v1.0.0 graduated alongside OCCTSwift v1.0.0. Used - // here for the headless-friendly subset only, Trihedron / WorkPlane - // / Axis / PointCloud scene objects (each emits ViewportBody arrays - // via makeBodies()) and the SubShape ↔ ViewportBody plumbing for - // highlight overlays. Selection / Manipulator / SwiftUI surfaces - // aren't relevant to a CLI; Dimension overlays render via a SwiftUI + // OCCTSwiftTools and OCCTSwiftAIS merged into one package, OCCTSwiftInteraction, alongside + // OCCTSwiftCADKit (SecondMouseAU/ecosystem#42, ecosystem#43). The three old repos are + // archived, not deleted (their tags still resolve), but every consumer is asked to repin + // per OCCTSwiftInteraction's docs/MIGRATION.md (OCCTSwiftScripts#122). Module names are + // unchanged: `import OCCTSwiftTools` / `import OCCTSwiftAIS` still work, since each stays + // its own SwiftPM target inside the merged package, so only the `package:` label on each + // product below changes, not the dependency names in code or this repo's `import` lines. + // We don't use OCCTSwiftCADKit (the SwiftUI-assembled viewport service) or name its + // product, so its target never enters this build. + // + // OCCTSwiftTools is the kernel-to-renderer bridge: CADFileLoader.shapeToBodyAndMetadata in + // RenderPreview, which legitimately needs Viewport, so the dep stays. We don't separately + // depend on OCCTSwiftIO's own product because OCCTSwiftIO's ScriptManifest is missing the + // `graphs` field our local Sources/ScriptHarness/Manifest.swift carries, the + // topology-graph descriptors that ScriptContext.addGraph() and addGraphsForAllShapes() + // emit. Swapping would silently lose that metadata for downstream OCCTSwiftViewport + // ScriptWatcher consumers. If a future verb wants progress-aware STEP loading via + // OCCTSwiftIO's ShapeLoader.load(from:format:progress:), add the dep then. + // + // OCCTSwiftAIS is used here for the headless-friendly subset only, Trihedron / WorkPlane + // / Axis / PointCloud scene objects (each emits ViewportBody arrays via makeBodies()) and + // the SubShape <-> ViewportBody plumbing for highlight overlays. Selection / Manipulator / + // SwiftUI surfaces aren't relevant to a CLI; Dimension overlays render via a SwiftUI // Canvas inside MetalViewportView and so don't reach OffscreenRenderer. - occtDep("OCCTSwiftAIS", from: "1.0.2"), + occtDep("OCCTSwiftInteraction", from: "0.1.0"), // OCCTSwiftMesh v1.0.0 graduated alongside OCCTSwift v1.0.0. Powers // the `simplify-mesh` verb. occtDep("OCCTSwiftMesh", from: "1.0.0"), @@ -285,8 +289,8 @@ let package = Package( "DrawingComposer", .product(name: "OCCTSwift", package: "OCCTSwift"), .product(name: "OCCTSwiftViewport", package: "OCCTSwiftViewport"), - .product(name: "OCCTSwiftTools", package: "OCCTSwiftTools"), - .product(name: "OCCTSwiftAIS", package: "OCCTSwiftAIS"), + .product(name: "OCCTSwiftTools", package: "OCCTSwiftInteraction"), + .product(name: "OCCTSwiftAIS", package: "OCCTSwiftInteraction"), .product(name: "OCCTSwiftMesh", package: "OCCTSwiftMesh"), .product(name: "OCCTSwiftIO", package: "OCCTSwiftIO"), ], diff --git a/README.md b/README.md index ef1262f..2a38531 100644 --- a/README.md +++ b/README.md @@ -267,7 +267,6 @@ The `occtkit` executable is a separate target; install via the `Makefile` above - Swift 6.0+ - [OCCTSwift](https://github.com/SecondMouseAU/OCCTSwift) `>= 2.0.0` (xcframework built against OCCT 8.0.1; a correctness major, 17 breaking changes, see OCCTSwiftScripts#111 and OCCTSwift's `docs/SEMVER.md#v200`. **Not yet resolvable from a fresh clone**: the rest of the cohort below hasn't released a version compatible with OCCTSwift 2.0.0 yet) - [OCCTSwiftViewport](https://github.com/SecondMouseAU/OCCTSwiftViewport) `>= 1.0.0` (powers `render-preview`) -- [OCCTSwiftTools](https://github.com/SecondMouseAU/OCCTSwiftTools) `>= 1.0.0` (bridge layer used by `render-preview` for Shape→ViewportBody conversion) -- [OCCTSwiftAIS](https://github.com/SecondMouseAU/OCCTSwiftAIS) `>= 1.0.0` (headless overlays for `render-preview`'s `--show-axes` / `--show-workplane` / `--highlight`) +- [OCCTSwiftInteraction](https://github.com/SecondMouseAU/OCCTSwiftInteraction) `>= 0.1.0` (vends `OCCTSwiftTools`, the bridge layer used by `render-preview` for Shape→ViewportBody conversion, and `OCCTSwiftAIS`, headless overlays for `render-preview`'s `--show-axes` / `--show-workplane` / `--highlight`; migrated from the standalone `OCCTSwiftTools`/`OCCTSwiftAIS` repos in OCCTSwiftScripts#122, `import` lines unchanged) - [OCCTSwiftMesh](https://github.com/SecondMouseAU/OCCTSwiftMesh) `>= 1.0.0` (powers `simplify-mesh`) - [OCCTSwiftIO](https://github.com/SecondMouseAU/OCCTSwiftIO) `>= 1.7.5` (powers `graph-ml`'s ML feature export; floor raised from `>= 1.0.0, < 1.1.0` to stay compatible with OCCTSwiftTools' own `>= 1.7.0` requirement, see OCCTSwiftScripts#80; no narrower product avoids OCCTSwiftIO's mesh-IO stack, see `Package.swift`) diff --git a/docs/guides/architecture.md b/docs/guides/architecture.md index 4609e5e..b24ebdb 100644 --- a/docs/guides/architecture.md +++ b/docs/guides/architecture.md @@ -84,8 +84,9 @@ OCCTSwiftScripts depends on the OCCTSwift cohort and is depended on by OCCTMCP: ``` OCCTSwift B-Rep kernel (~400+ methods), ISO drawings, FeatureReconstructor, SheetMetal, XCAF ├─ OCCTSwiftViewport OffscreenRenderer / CameraState / DisplayMode → render-preview - ├─ OCCTSwiftTools CADFileLoader (Shape → ViewportBody) → render-preview - ├─ OCCTSwiftAIS Trihedron / WorkPlane / SubShape selection → render-preview overlays + ├─ OCCTSwiftInteraction + │ ├─ OCCTSwiftTools CADFileLoader (Shape → ViewportBody) → render-preview + │ └─ OCCTSwiftAIS Trihedron / WorkPlane / SubShape selection → render-preview overlays ├─ OCCTSwiftMesh meshoptimizer QEM decimation → simplify-mesh └─ OCCTSwiftIO BRepGraph.exportForML → graph-ml │ diff --git a/okf/index.md b/okf/index.md index 37545bf..d607934 100644 --- a/okf/index.md +++ b/okf/index.md @@ -17,7 +17,7 @@ timestamp: 2026-06-22 ## Role in the ecosystem - **Cluster:** kernel -- **Depends on:** [OCCTSwift](https://github.com/SecondMouseAU/OCCTSwift) (B-Rep kernel), [OCCTSwiftViewport](https://github.com/SecondMouseAU/OCCTSwiftViewport) (offscreen render for `render-preview`), [OCCTSwiftTools](https://github.com/SecondMouseAU/OCCTSwiftTools) (Shape ↔ ViewportBody bridge), [OCCTSwiftAIS](https://github.com/SecondMouseAU/OCCTSwiftAIS) (headless scene-object overlays), [OCCTSwiftMesh](https://github.com/SecondMouseAU/OCCTSwiftMesh) (`simplify-mesh`), and [OCCTSwiftIO](https://github.com/SecondMouseAU/OCCTSwiftIO) (`graph-ml` feature export). +- **Depends on:** [OCCTSwift](https://github.com/SecondMouseAU/OCCTSwift) (B-Rep kernel), [OCCTSwiftViewport](https://github.com/SecondMouseAU/OCCTSwiftViewport) (offscreen render for `render-preview`), [OCCTSwiftInteraction](https://github.com/SecondMouseAU/OCCTSwiftInteraction) (vends `OCCTSwiftTools`, the Shape ↔ ViewportBody bridge, and `OCCTSwiftAIS`, headless scene-object overlays; migrated from those two standalone repos in OCCTSwiftScripts#122), [OCCTSwiftMesh](https://github.com/SecondMouseAU/OCCTSwiftMesh) (`simplify-mesh`), and [OCCTSwiftIO](https://github.com/SecondMouseAU/OCCTSwiftIO) (`graph-ml` feature export). - **Feeds:** headless / agent consumers. OCCTMCP and any JSON-driven tooling drive its verbs via `--serve`; the `ScriptHarness` and `DrawingComposer` library products link into downstream apps (e.g. the viewport ScriptWatcher and OCCTSwiftPartsAgent). This is the **single knowledge store** for this repo. `CLAUDE.md` at the repo root stays the diff --git a/okf/log.md b/okf/log.md index 6de3d09..7194215 100644 --- a/okf/log.md +++ b/okf/log.md @@ -1,5 +1,22 @@ # Knowledge Log +## 2026-08-20 (fix/122-occtswiftinteraction-migration) + +* **Update**: Migrated `occtkit`'s `OCCTSwiftTools` and `OCCTSwiftAIS` dependencies onto + `OCCTSwiftInteraction` (#122), the package the two merged into alongside `OCCTSwiftCADKit` + (SecondMouseAU/ecosystem#42/#43). SwiftPM enforces target-name uniqueness across the whole + transitive graph before per-consumer product pruning, so any consumer needing both this repo + and `OCCTSwiftInteraction` directly (OCCTMCP, for OCCTMCP#182) hit a hard resolution error, not + a version conflict, until this repo repinned. Per `OCCTSwiftInteraction`'s `docs/MIGRATION.md`, + this is a manifest-only change: replaced the two `occtDep` entries with one + `occtDep("OCCTSwiftInteraction", from: "0.1.0")` and repointed both products' `package:` label; + `import OCCTSwiftTools` / `import OCCTSwiftAIS` lines are unchanged since each stayed its own + target inside the merged package. Regenerated `Package.resolved` from an isolated, sibling-free + clone (per the lesson below), confirmed both a local sibling build and the sibling-free remote + build compile, and confirmed `swift test` (12/12) and `Scripts/recipe-check.sh` (7/7) pass. + Updated `CLAUDE.md`, `README.md`, `docs/guides/architecture.md`, and `okf/index.md` to describe + the new package. + ## 2026-08-19 (fix/stale-package-resolved-post-3.0.0) * **Update**: Released OCCTSwiftScripts v1.6.2 (#118/#119) once the cohort (`OCCTSwiftTools`