Skip to content

fix(deps): cap OCCTSwiftIO minor + fix sibling-detection false-positive (#69)#70

Merged
gsdali merged 3 commits into
mainfrom
fix/cap-occtswiftio-minor
Jul 1, 2026
Merged

fix(deps): cap OCCTSwiftIO minor + fix sibling-detection false-positive (#69)#70
gsdali merged 3 commits into
mainfrom
fix/cap-occtswiftio-minor

Conversation

@gsdali

@gsdali gsdali commented Jul 1, 2026

Copy link
Copy Markdown
Collaborator

Closes #69. Two fixes — the reported one plus a deeper root cause found while reproducing it exactly.

1. Cap OCCTSwiftIO to its 1.0.x minor line (the reported bug)

occtDep("OCCTSwiftIO", from: "1.0.0") only bounds by major version, so a lean consumer with no root-level override (e.g. OCCTMCP's execute_script workspace) floats OCCTSwiftIO to whatever 1.x is newest — now v1.5.0, which drags in the heavy mesh-IO stack (SwiftX/SwiftDXF/SwiftJWW/SwiftPMX/ThreeMF/SwiftGLTF/…). This repo only uses OCCTSwiftIO for TopologyGraph.exportForML/exportJSON (GraphML/graphml verbs), which has needed nothing past 1.0.x. Adds occtDepUpToNextMinor (same helper OCCTMCP#53 already uses) and caps through it.

2. Fix a false-positive in the sibling-path detection (the actual remaining blocker)

Capping the version alone did not fix resolution for a lean consumer — I reproduced the exact failure with a standalone package depending only on OCCTSwiftScripts's ScriptHarness product (mirroring execute_script's workspace) and still hit error: exhausted attempts to resolve the dependencies graph, even with OCCTSwiftIO correctly computed at 1.0.1.

Root cause: occtDep's sibling probe (../<name>/Package.swift) is purely filesystem-based. SwiftPM lays every dependency's checkout out flat under one shared .build/checkouts/ directory — so once .build/checkouts/OCCTSwiftIO exists (as a side effect of resolving it), ../OCCTSwiftIO relative to .build/checkouts/OCCTSwiftScripts spuriously "exists" too, flipping this manifest's own dependency declaration from url to path mid-resolution. SwiftPM sees a non-deterministic manifest and reports the whole graph unresolvable — for any consumer that pulls OCCTSwiftScripts in transitively, not just ones affected by the version float.

Fix: the sibling check is now guarded on the manifest's own directory not being inside a /checkouts/ path — a real local dev clone (~/Projects/<repo>) never is; only a transitively-resolved SwiftPM checkout is.

Verified

  • swift package resolve in a standalone "depends on OCCTSwiftScripts only" package (before either fix): reproduces the reported failure exactly (OCCTSwiftIO floats to 1.5.0, pulls in tomasf/Zip, exhausted attempts).
  • After fix 1 alone: still exhausted attempts (OCCTSwiftIO correctly at 1.0.1, but the sibling false-positive still poisons the graph).
  • After both fixes: resolves and builds cleanly — OCCTSwiftIO pinned at 1.0.1, no heavy mesh-IO packages in the graph.
  • OCCTSwiftScripts' own swift build + swift test --no-parallel: clean, 3/3 tests pass.

Follow-up worth considering separately

The sibling-detection pattern (occtDep/occtDepUpToNextMinor) is copy-pasted across the ecosystem's Package.swift files. The same false-positive could latently affect any of them once used as a transitive dependency (as opposed to built directly from a real local clone) — happy to sweep the fleet with the same guard if useful.

🤖 Generated with Claude Code

gsdali and others added 3 commits July 1, 2026 20:28
occtDep("OCCTSwiftIO", from: "1.0.0") only bounds by major version, so a
lean consumer with no root-level override (e.g. OCCTMCP's execute_script
workspace) floats OCCTSwiftIO to whatever 1.x is newest — now v1.5.0, which
drags in the heavy mesh-IO stack (SwiftX/SwiftDXF/SwiftJWW/SwiftPMX/ThreeMF/
SwiftGLTF/...) and makes the graph unsolvable. This repo only uses OCCTSwiftIO
for TopologyGraph.exportForML/exportJSON (GraphML/graphml verbs), a surface
that has needed nothing past 1.0.x since it graduated.

Adds occtDepUpToNextMinor (same helper OCCTMCP#53 already uses at its own
root) and caps OCCTSwiftIO through it. Verified: swift package resolve now
pins OCCTSwiftIO at 1.0.1 (was floating to 1.5.0) with none of the heavy
mesh-IO checkouts pulled in; swift build succeeds.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…t layout

The occtDep sibling probe (../<name>/Package.swift) is filesystem-based and
fires whenever a same-named directory happens to exist next to this manifest
— including when THIS manifest is itself a transitively-resolved SwiftPM
checkout under .build/checkouts/OCCTSwiftScripts, where SwiftPM lays every
other dependency out as a flat sibling under the same checkouts/ directory.
Once .build/checkouts/OCCTSwiftIO exists (as a side effect of resolving it),
../OCCTSwiftIO spuriously matches, flipping this manifest's own dependency
declaration from url to path mid-resolution. SwiftPM then reports the whole
graph as unresolvable ('exhausted attempts to resolve the dependencies
graph') for any lean consumer that pulls OCCTSwiftScripts in transitively —
verified this is the actual remaining failure mode of #69 even after the
OCCTSwiftIO minor cap, via a standalone repro package depending only on
OCCTSwiftScripts's ScriptHarness product (mirroring OCCTMCP's execute_script
workspace).

Guards the sibling check on the manifest's own directory NOT being inside a
'/checkouts/' path — real local dev clones (~/Projects/<repo>) never are.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ild/ convention

Same fix, just matching the guard string OCCTSwiftIO already adopted
(2026-06-23) for consistency across the fleet being swept with this guard.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@gsdali gsdali merged commit 6ed14de into main Jul 1, 2026
0 of 3 checks passed
@gsdali gsdali deleted the fix/cap-occtswiftio-minor branch July 1, 2026 20:48
gsdali added a commit to SecondMouseAU/OCCTSwiftTools that referenced this pull request Jul 1, 2026
…itive (#30)

The occtDep helper used a local `.package(path: "../<name>")` whenever
`../<name>/Package.swift` existed. SwiftPM lays every transitive checkout out
flat under one `.build/checkouts/`, so when this manifest is itself resolved as
a dependency, `../<name>` spuriously exists and flips the dep to a path — which
conflicts with the same package resolved by URL elsewhere in the graph, so
SwiftPM emits a "Conflicting identity" warning (slated to become a hard error).

Guard the sibling branch with `!manifestDir.contains("/.build/")` so only a real
local dev clone takes the path dep. Mirrors SecondMouseAU/OCCTSwiftScripts#70.

Refs SecondMouseAU/ecosystem#14.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
gsdali added a commit to SecondMouseAU/OCCTSwiftMesh that referenced this pull request Jul 1, 2026
…itive (#9)

The occtDep helper used a local `.package(path: "../<name>")` whenever
`../<name>/Package.swift` existed. SwiftPM lays every transitive checkout out
flat under one `.build/checkouts/`, so when this manifest is itself resolved as
a dependency, `../<name>` spuriously exists and flips the dep to a path — which
conflicts with the same package resolved by URL elsewhere in the graph, so
SwiftPM emits a "Conflicting identity" warning (slated to become a hard error).

Guard the sibling branch with `!manifestDir.contains("/.build/")` so only a real
local dev clone takes the path dep. Mirrors SecondMouseAU/OCCTSwiftScripts#70.

Refs SecondMouseAU/ecosystem#14.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
gsdali added a commit to SecondMouseAU/OCCTSwiftAIS that referenced this pull request Jul 1, 2026
…itive (#27)

The occtDep helper used a local `.package(path: "../<name>")` whenever
`../<name>/Package.swift` existed. SwiftPM lays every transitive checkout out
flat under one `.build/checkouts/`, so when this manifest is itself resolved as
a dependency, `../<name>` spuriously exists and flips the dep to a path — which
conflicts with the same package resolved by URL elsewhere in the graph, so
SwiftPM emits a "Conflicting identity" warning (slated to become a hard error).

Guard the sibling branch with `!manifestDir.contains("/.build/")` so only a real
local dev clone takes the path dep. Mirrors SecondMouseAU/OCCTSwiftScripts#70.

Refs SecondMouseAU/ecosystem#14.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

OCCTSwiftIO dep uncapped (from: "1.0.0") — floats to 1.5.0 and breaks resolution for lean consumers

1 participant