diff --git a/CLAUDE.md b/CLAUDE.md index e2ceed7..6780a3d 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -82,10 +82,10 @@ No tests exist. No linter is configured. The full cohort graduated to v1.0 on 2026-05-07 alongside OCCT 8.0.0 GA. SemVer-stable from these floors — only bump on documented breaking changes. Pre-1.0 dep history (which API landed in which 0.x tag) lives in git log; consult it when you actually need to support an older floor, otherwise treat the v1.0 surface as the contract. -- **OCCTSwift** — `https://github.com/gsdali/OCCTSwift.git` (>= 1.15.0; xcframework built against **OCCT 8.0.0p1**). The B-Rep kernel: ~400+ methods for parametric CAD, the full ISO drawings stack (Sheet/TitleBlock/ProjectionSymbol/Section2D/Hatch/AutoCentermarks/CuttingPlaneLine/CosmeticThread/SurfaceFinish/GDT/DetailView/DrawingScale), `FeatureReconstructor` for `reconstruct`, the `SheetMetal` namespace for `compose-sheet-metal`, and the XCAF surfaces (`AssemblyNode.labelId`, `Document.node(at:)`) for `inspect-assembly` / `set-metadata`. **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 — `Shape.circularPatternCut` (#169), orientation-normalised `Shape.sweep` + `orientedForward`/`signedVolume` (#170), `concaveEdges`/`convexEdges`/`edges(where:)` selectors (#171) — are unchanged. The rest of the cohort still resolves at its existing floors (Viewport 1.0.4 / Tools 1.1.1 / AIS 1.0.2 / Mesh 1.0.0 / IO 1.0.0), all of which compile against 1.15.0. +- **OCCTSwift** — `https://github.com/gsdali/OCCTSwift.git` (>= 1.15.0; xcframework built against **OCCT 8.0.0p1**). The B-Rep kernel: ~400+ methods for parametric CAD, the full ISO drawings stack (Sheet/TitleBlock/ProjectionSymbol/Section2D/Hatch/AutoCentermarks/CuttingPlaneLine/CosmeticThread/SurfaceFinish/GDT/DetailView/DrawingScale), `FeatureReconstructor` for `reconstruct`, the `SheetMetal` namespace for `compose-sheet-metal`, and the XCAF surfaces (`AssemblyNode.labelId`, `Document.node(at:)`) for `inspect-assembly` / `set-metadata`. **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 — `Shape.circularPatternCut` (#169), orientation-normalised `Shape.sweep` + `orientedForward`/`signedVolume` (#170), `concaveEdges`/`convexEdges`/`edges(where:)` selectors (#171) — are unchanged. The rest of the cohort still resolves at its existing floors (Viewport 1.0.4 / Tools 1.1.1 / AIS 1.0.2 / Mesh 1.0.0 / IO 1.7.5), all of which compile against 1.15.0. - **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` — `--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.0.0). 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. +- **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 — 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 521c9cf..c66b474 100644 --- a/Package.resolved +++ b/Package.resolved @@ -1,6 +1,15 @@ { - "originHash" : "902fcc11c2f4dd087ed5a213efa27f51334af57a8ae2692d8718df8dd65529b8", + "originHash" : "fb5d03c0c4ec0e5129f75f7146d63d21f81c2fc74b3c1a5953847e18f4fe31a7", "pins" : [ + { + "identity" : "nodal", + "kind" : "remoteSourceControl", + "location" : "https://github.com/tomasf/Nodal.git", + "state" : { + "revision" : "a4dbde9c2d0b70e10e834bd62c46b9d78a67e5f0", + "version" : "1.0.1" + } + }, { "identity" : "occtswift", "kind" : "remoteSourceControl", @@ -15,8 +24,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/SecondMouseAU/OCCTSwiftAIS.git", "state" : { - "revision" : "b70a22e29b6f1dd64dcdd9ad773f3adb9fdef5a7", - "version" : "1.0.5" + "revision" : "af1de6d47430f45681c1a419a1cf7a07a73a6e81", + "version" : "1.3.1" } }, { @@ -24,8 +33,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/SecondMouseAU/OCCTSwiftIO.git", "state" : { - "revision" : "566d870ed8551df548c3e847a8be55e0f6a6ddf1", - "version" : "1.0.2" + "revision" : "f7babdf70704ed7a20e9b41831a54b811b9ff387", + "version" : "1.7.5" } }, { @@ -42,8 +51,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/SecondMouseAU/OCCTSwiftTools.git", "state" : { - "revision" : "632e1cd96560c4909e7ad949b540e208cd6b24bf", - "version" : "1.3.1" + "revision" : "1c85263dc7067a9fd8f3c6411ed504ef271d5667", + "version" : "1.6.1" } }, { @@ -51,8 +60,71 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/SecondMouseAU/OCCTSwiftViewport.git", "state" : { - "revision" : "66bee2038ba4b835d35f650b865241203f40c613", - "version" : "1.1.24" + "revision" : "61be7a48c68ed6d2efdc495f9250fb199c96e8df", + "version" : "1.1.26" + } + }, + { + "identity" : "swiftdxf", + "kind" : "remoteSourceControl", + "location" : "https://github.com/SecondMouseAU/SwiftDXF.git", + "state" : { + "revision" : "8419e9aade961cc973bd642e0312e5cd173a87ae", + "version" : "0.2.1" + } + }, + { + "identity" : "swiftgltf", + "kind" : "remoteSourceControl", + "location" : "https://github.com/schwa/SwiftGLTF.git", + "state" : { + "revision" : "e17b478ca157733543a7cf9da370d34dbabc9236", + "version" : "1.0.2" + } + }, + { + "identity" : "swiftjww", + "kind" : "remoteSourceControl", + "location" : "https://github.com/SecondMouseAU/SwiftJWW.git", + "state" : { + "revision" : "f41e6be050545f43184a6708b03cb1e9e7be9e63", + "version" : "1.2.2" + } + }, + { + "identity" : "swiftpmx", + "kind" : "remoteSourceControl", + "location" : "https://github.com/SecondMouseAU/SwiftPMX.git", + "state" : { + "revision" : "c19be503b765c0fd385be5d04fda5699f858fad3", + "version" : "1.1.1" + } + }, + { + "identity" : "swiftx", + "kind" : "remoteSourceControl", + "location" : "https://github.com/SecondMouseAU/SwiftX.git", + "state" : { + "revision" : "34660dd6ecd1573a2c2419d6b0dea26b4ca1e617", + "version" : "1.0.1" + } + }, + { + "identity" : "threemf", + "kind" : "remoteSourceControl", + "location" : "https://github.com/tomasf/ThreeMF.git", + "state" : { + "revision" : "dc0156a495932b05928fdacb9ff4e4644102f0a6", + "version" : "0.2.4" + } + }, + { + "identity" : "zip", + "kind" : "remoteSourceControl", + "location" : "https://github.com/tomasf/Zip.git", + "state" : { + "revision" : "3a22aaf3f449ceded0354695af96967d1df4e5e0", + "version" : "2.1.2" } } ], diff --git a/Package.swift b/Package.swift index d57b161..f2f97f3 100644 --- a/Package.swift +++ b/Package.swift @@ -30,19 +30,6 @@ func occtDep(_ name: String, from version: String) -> Package.Dependency { return .package(url: "https://github.com/SecondMouseAU/\(name).git", from: Version(version)!) } -// As occtDep, but pins to the package's minor line instead of an open major range. Used to cap a -// transitive dependency whose newer minors pull deps we don't want in the graph — OCCTSwiftIO 1.1.0+ -// pulls in the heavy mesh-IO stack (SwiftX/SwiftDXF/SwiftJWW/SwiftPMX/ThreeMF/SwiftGLTF/…), which the -// narrow GraphML/graphml usage here doesn't need and which breaks resolution for lean consumers that -// have no root package to override from (ecosystem issue: OCCTSwiftScripts#69). -func occtDepUpToNextMinor(_ name: String, from version: String) -> Package.Dependency { - let manifestDir = URL(fileURLWithPath: #filePath).deletingLastPathComponent().path - if isRealLocalSibling(manifestDir, name) { - return .package(path: "../\(name)") - } - return .package(url: "https://github.com/SecondMouseAU/\(name).git", .upToNextMinor(from: Version(version)!)) -} - let package = Package( name: "OCCTSwiftScripts", platforms: [ @@ -128,9 +115,32 @@ let package = Package( // v0.171.0 hoisted them out of the kernel. Pulled into GraphML and // graphml verbs only — the rest of the package keeps its existing // ScriptManifest type (with the `graphs` field) from ScriptHarness. - // Capped to the 1.0.x minor line (occtDepUpToNextMinor): 1.1.0+ pulls in the - // heavy mesh-IO stack this narrow usage doesn't need (#69). - occtDepUpToNextMinor("OCCTSwiftIO", from: "1.0.0"), + // + // Was capped to the 1.0.x minor line (occtDepUpToNextMinor(from: "1.0.0"), + // #69) because OCCTSwiftIO 1.1.0+ folds in a MeshIO target (SwiftPMX / + // SwiftX / ThreeMF / SwiftGLTF, plus SwiftJWW / SwiftDXF for 2D vector + // formats) that lean consumers didn't want in the graph. Raised to an + // open floor (OCCTSwiftScripts#80): OCCTSwiftTools >=1.6.1 now requires + // OCCTSwiftIO >=1.7.0 directly, so any consumer depending on both + // OCCTSwiftScripts and OCCTSwiftTools at once (e.g. OCCTMCP) hit an + // unsatisfiable version conflict against our <1.1.0 cap. Checked + // OCCTSwiftIO 1.7.5's Package.swift for a narrower product that could + // keep the cap's spirit: it now ships two library products, + // `OCCTSwiftIO` and `MeshIO`, but the `OCCTSwiftIO` target itself + // still lists `MeshIO` as a plain (unconditional) target dependency — + // not a product a consumer can decline. So depending on just the + // `OCCTSwiftIO` product still resolves and checks out the full + // SwiftPMX/SwiftX/ThreeMF/SwiftGLTF stack; there's no BREP/STEP-only + // product to opt into instead. Floored at 1.7.5 rather than the bare + // 1.7.0 Tools needs: 1.7.5 is OCCTSwiftIO's own TopologyGraph -> + // BRepGraph rename (mirroring OCCTSwift's 1.15.0 rename above and + // OCCTSwiftTools 1.6.1 / OCCTSwiftAIS 1.3.1's), and 1.7.1-1.7.4 are + // pure OCCTSwift-floor repins for the same OCCT kernel crash/hang + // fixes (#298/#310/#317/#318/#323) already required transitively via + // our own OCCTSwift >=1.15.0 floor above — no reason to admit an + // OCCTSwiftIO minor that predates fixes we already require elsewhere + // in the graph. + occtDep("OCCTSwiftIO", from: "1.7.5"), ], targets: [ .target( diff --git a/README.md b/README.md index 4c32133..c010502 100644 --- a/README.md +++ b/README.md @@ -269,4 +269,4 @@ The `occtkit` executable is a separate target — install via the `Makefile` abo - [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`) - [OCCTSwiftMesh](https://github.com/SecondMouseAU/OCCTSwiftMesh) `>= 1.0.0` (powers `simplify-mesh`) -- [OCCTSwiftIO](https://github.com/SecondMouseAU/OCCTSwiftIO) `>= 1.0.0` (powers `graph-ml`'s ML feature export) +- [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`)