gstack version: v1.55.0.0
Skill: /ios-qa
Discovered: 2026-06-01, fresh install of DebugBridge into the Dugout Sports iOS app (after our PR #342 had to surgically remove the previous DebugBridge to pass App Store review — see #5 below, which is the same failure mode).
A clean /ios-qa install of the DebugBridge stack currently does not build out of the box on Swift 6.x toolchains, and — most seriously — the generated Obj-C touch-synthesis target compiles private UIKit/IOKit SPIs into Release builds, which Apple's static scanner rejects. Five distinct template bugs below, in increasing severity. We've applied local patches for all five in our working tree; the corrected files are quoted/referenced inline.
1. gen-accessors-tool/Package.swift references a non-existent test target
ios-qa/scripts/gen-accessors-tool/Package.swift declares:
.testTarget(name: "GenAccessorsTests", path: "Tests/GenAccessorsTests")
but Tests/ does not exist in the package, so swift build fails:
error: invalid custom path 'Tests/GenAccessorsTests' for target 'GenAccessorsTests'
Fix: remove the .testTarget(...) block — no tests exist.
2. Package.swift.template puts the tools-version directive on line 21, not line 1
ios-qa/templates/Package.swift.template opens with a multi-line doc-comment block and only declares // swift-tools-version:5.9 on ~line 21. The directive must be the first line of the manifest. Swift 6.0+ rejects the misplaced directive:
error: manifest is backward-incompatible with Swift < 6.0
Fix: move // swift-tools-version:5.9 to line 1 (doc-comment block follows it). Our generated apps/ios/DebugBridge/Package.swift shows the correct ordering — directive on line 1, comment block lines 2–22.
3. Package.swift.template references a non-existent test target
Same template declares:
.testTarget(name: "DebugBridgeCoreTests", path: "Tests/DebugBridgeCoreTests")
/ios-qa never populates a Tests/ folder, so the install fails the same way as #1 (invalid custom path).
Fix: drop the .testTarget(...) block.
4. DebugBridgeWiring.swift.template is broken and redundant — delete it
ios-qa/templates/DebugBridgeWiring.swift.template does not compile and duplicates wiring that Bridges.swift.template already provides:
import DebugBridge — there is no DebugBridge module. The modules are DebugBridgeCore, DebugBridgeUI, DebugBridgeTouch.
- References
AccessibilityScanner, SnapshotCapture, MutationDispatcher — none of these symbols exist anywhere in the templates. Bridges.swift.template defines ElementsBridgeImpl, ScreenshotBridgeImpl, MutationBridgeImpl instead.
- Calls
DebugBridgeManager.shared.start(appState:recording:) — DebugBridgeManager only defines start(appState:).
Bridges.swift's DebugBridgeUIWiring.installAll() already performs the actual wiring (confirmed in our generated Sources/DebugBridgeUI/Bridges.swift — public enum DebugBridgeUIWiring { static func installAll() ... }).
Fix: delete DebugBridgeWiring.swift.template entirely.
5. ⚠️ DebugBridgeTouch.m.template compiles private SPIs into App Store Release builds
This is the critical one — it is the exact failure that got Dugout Sports v1.0 rejected (App Store Guideline 2.1, private API scan) and forced the surgical DebugBridge removal in our PR #342.
ios-qa/templates/DebugBridgeTouch.m.template gates its iOS implementation block with:
instead of:
#if TARGET_OS_IOS && defined(DEBUG)
The block references private UITouch/UIEvent/IOKit SPIs — _setLocationInWindow:resetPrevious:, _addTouch:forDelayedDelivery:, _clearTouches, _setHIDEvent:, _setIsFirstTouchForView:, _touchesEvent, IOHIDEventCreateDigitizer*. With only TARGET_OS_IOS, these compile into iOS Release builds and land in the App Store binary, where Apple's static scanner flags them.
Critically, the Package.swift Swift-side gate does not protect this file:
swiftSettings: [.define("DEBUG", .when(configuration: .debug))]
swiftSettings only affects Swift compile units. The Obj-C .m file is compiled with cSettings, which the template doesn't set — so DEBUG is never defined for this translation unit in a SwiftPM build, and the SPIs leak.
Fix (two parts):
- Change the gate to
#if TARGET_OS_IOS && defined(DEBUG). The existing #else stub (iOS Release / macOS / Catalyst) already provides the no-op implementations, so the non-DEBUG branch is already handled.
- Add a
cSettings DEBUG define to the DebugBridgeTouch target in Package.swift.template as belt-and-suspenders:
.target(
name: "DebugBridgeTouch",
...
cSettings: [
.define("DEBUG", to: "1", .when(configuration: .debug)),
],
...
)
Our patched apps/ios/DebugBridge/Sources/DebugBridgeTouch/DebugBridgeTouch.m now gates at line 28 (#if TARGET_OS_IOS && defined(DEBUG)), with the #else stub at line 294 and #endif at line 307; the patched Package.swift carries the cSettings define on the DebugBridgeTouch target.
Verification (passes with all five fixes applied)
cd "$APP/DebugBridge" && swift build -c release
nm -j .build/arm64-apple-macosx/release/DebugBridgeTouch.build/DebugBridgeTouch.m.o \
| grep -qE '_setLocationInWindow|_addTouch|_clearTouches|_setHIDEvent' \
&& exit 1 || echo "clean"
Expected: swift build -c release succeeds (fixes #1–#4) and the nm symbol scan prints clean (fix #5).
We have local patches for all five at apps/ios/DebugBridge/ in the Dugout repo (uncommitted, branch fix/data-accuracy-fixes) and can open a PR against the templates if useful — happy to do so once you confirm the approach.
gstack version: v1.55.0.0
Skill:
/ios-qaDiscovered: 2026-06-01, fresh install of DebugBridge into the Dugout Sports iOS app (after our PR #342 had to surgically remove the previous DebugBridge to pass App Store review — see #5 below, which is the same failure mode).
A clean
/ios-qainstall of the DebugBridge stack currently does not build out of the box on Swift 6.x toolchains, and — most seriously — the generated Obj-C touch-synthesis target compiles private UIKit/IOKit SPIs into Release builds, which Apple's static scanner rejects. Five distinct template bugs below, in increasing severity. We've applied local patches for all five in our working tree; the corrected files are quoted/referenced inline.1.
gen-accessors-tool/Package.swiftreferences a non-existent test targetios-qa/scripts/gen-accessors-tool/Package.swiftdeclares:but
Tests/does not exist in the package, soswift buildfails:Fix: remove the
.testTarget(...)block — no tests exist.2.
Package.swift.templateputs the tools-version directive on line 21, not line 1ios-qa/templates/Package.swift.templateopens with a multi-line doc-comment block and only declares// swift-tools-version:5.9on ~line 21. The directive must be the first line of the manifest. Swift 6.0+ rejects the misplaced directive:Fix: move
// swift-tools-version:5.9to line 1 (doc-comment block follows it). Our generatedapps/ios/DebugBridge/Package.swiftshows the correct ordering — directive on line 1, comment block lines 2–22.3.
Package.swift.templatereferences a non-existent test targetSame template declares:
/ios-qanever populates aTests/folder, so the install fails the same way as #1 (invalid custom path).Fix: drop the
.testTarget(...)block.4.
DebugBridgeWiring.swift.templateis broken and redundant — delete itios-qa/templates/DebugBridgeWiring.swift.templatedoes not compile and duplicates wiring thatBridges.swift.templatealready provides:import DebugBridge— there is noDebugBridgemodule. The modules areDebugBridgeCore,DebugBridgeUI,DebugBridgeTouch.AccessibilityScanner,SnapshotCapture,MutationDispatcher— none of these symbols exist anywhere in the templates.Bridges.swift.templatedefinesElementsBridgeImpl,ScreenshotBridgeImpl,MutationBridgeImplinstead.DebugBridgeManager.shared.start(appState:recording:)—DebugBridgeManageronly definesstart(appState:).Bridges.swift'sDebugBridgeUIWiring.installAll()already performs the actual wiring (confirmed in our generatedSources/DebugBridgeUI/Bridges.swift— publicenum DebugBridgeUIWiring { static func installAll() ... }).Fix: delete
DebugBridgeWiring.swift.templateentirely.5.⚠️
DebugBridgeTouch.m.templatecompiles private SPIs into App Store Release buildsThis is the critical one — it is the exact failure that got Dugout Sports v1.0 rejected (App Store Guideline 2.1, private API scan) and forced the surgical DebugBridge removal in our PR #342.
ios-qa/templates/DebugBridgeTouch.m.templategates its iOS implementation block with:#if TARGET_OS_IOSinstead of:
#if TARGET_OS_IOS && defined(DEBUG)The block references private UITouch/UIEvent/IOKit SPIs —
_setLocationInWindow:resetPrevious:,_addTouch:forDelayedDelivery:,_clearTouches,_setHIDEvent:,_setIsFirstTouchForView:,_touchesEvent,IOHIDEventCreateDigitizer*. With onlyTARGET_OS_IOS, these compile into iOS Release builds and land in the App Store binary, where Apple's static scanner flags them.Critically, the
Package.swiftSwift-side gate does not protect this file:swiftSettingsonly affects Swift compile units. The Obj-C.mfile is compiled withcSettings, which the template doesn't set — soDEBUGis never defined for this translation unit in a SwiftPM build, and the SPIs leak.Fix (two parts):
#if TARGET_OS_IOS && defined(DEBUG). The existing#elsestub (iOS Release / macOS / Catalyst) already provides the no-op implementations, so the non-DEBUG branch is already handled.cSettingsDEBUG define to theDebugBridgeTouchtarget inPackage.swift.templateas belt-and-suspenders:Our patched
apps/ios/DebugBridge/Sources/DebugBridgeTouch/DebugBridgeTouch.mnow gates at line 28 (#if TARGET_OS_IOS && defined(DEBUG)), with the#elsestub at line 294 and#endifat line 307; the patchedPackage.swiftcarries thecSettingsdefine on theDebugBridgeTouchtarget.Verification (passes with all five fixes applied)
Expected:
swift build -c releasesucceeds (fixes #1–#4) and thenmsymbol scan printsclean(fix #5).We have local patches for all five at
apps/ios/DebugBridge/in the Dugout repo (uncommitted, branchfix/data-accuracy-fixes) and can open a PR against the templates if useful — happy to do so once you confirm the approach.