Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -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+**.
19 changes: 5 additions & 14 deletions Package.resolved

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

48 changes: 26 additions & 22 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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"),
Expand Down Expand Up @@ -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"),
],
Expand Down
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`)
5 changes: 3 additions & 2 deletions docs/guides/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion okf/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading
Loading