Skip to content

fix(mac): replace .inspector() to stop the default UIProbe sweep crash - #458

Merged
SergeSerb2 merged 1 commit into
mainfrom
surgecode/fix-probe-sweep-crash
Aug 3, 2026
Merged

fix(mac): replace .inspector() to stop the default UIProbe sweep crash#458
SergeSerb2 merged 1 commit into
mainfrom
surgecode/fix-probe-sweep-crash

Conversation

@SergeSerb2

Copy link
Copy Markdown
Owner

Summary

  • The default SERGECODE_UI_PROBE sweep crashed within seconds of presenting the trailing inspector, every run, via AppKit's "Update Constraints in Window" runaway-layout exception.
  • Root cause is a macOS 27 beta SDK bug in NavigationSplitView + .inspector() pane-width negotiation — confirmed content-independent, config-independent, and reproducible on a clean main checkout (predates the AppKit port, not caused by it). A method-swizzle diagnostic showed ~12,000 invalidations/second entirely inside SwiftUI-private NavigationPaneModifier/_ViewList_View types once the inspector opens; no app symbol appears anywhere in the churn.
  • Fix: RootView.splitShell no longer presents InspectorPanel via .inspector(isPresented:). The trailing panel is now a plain HStack sibling of the sidebar/detail NavigationSplitView, sized via ordinary .frame(width:) with a hand-rolled drag-resize over the same 300–480pt range .inspectorColumnWidth used to enforce. InspectorPanel's content is unchanged (it has zero @Environment reads and no dependency on .inspector() itself).
  • Also removes a dead subview-measurement call in WindowContentSizeClamp (unrelated cleanup — explicitly documented as not the crash fix, since removing it alone did not stop the crash when tested in isolation).
  • Adds a DEBUG-only, opt-in (SERGECODE_LAYOUT_LOOP_DEBUG=1) layout-loop diagnostic (Support/LayoutLoopDiagnostics.swift) that named the churn during root-causing and is kept for future layout-loop bugs.
  • Full root-cause writeup in docs/audits/appkit-migration-parity-matrix.md.

Test plan

  • swift test — 1439 tests pass (1107 SurgeCodeMacTests + 296 T3Kit + 36 SidecarKit)
  • Default SERGECODE_UI_PROBE sweep: 3 consecutive clean runs (previously crashed every run)
  • 90s soak with the layout-loop diagnostic attached: no crash, steady-state churn only
  • sidebar-outline and sidebar-menus probe scenarios: both pass
  • pnpm run verify --all: clean (one unrelated server-test flake reproduced the documented "workers starve into 401s" pattern from AGENTS.md, passed on rerun in isolation and on a full clean re-run)

🤖 Generated with Claude Code

NavigationSplitView + .inspector() triggers a busy loop inside SwiftUI's
private pane-negotiation machinery on the macOS 27 beta SDK, saturating
the main thread until AppKit's runaway-layout guard hard-crashes the app.
Confirmed content-independent, config-independent, and reproducible on a
clean main checkout (predates the AppKit port).

The trailing inspector panel is now a plain HStack sibling of the
sidebar/detail NavigationSplitView instead of an .inspector() pane, with
a hand-rolled drag-resize over the same 300-480pt range. InspectorPanel's
content is unchanged. Verified via 3 consecutive clean default-sweep runs
plus a 90s soak with a new method-swizzle layout-loop diagnostic
(Support/LayoutLoopDiagnostics.swift, DEBUG-only, opt-in via
SERGECODE_LAYOUT_LOOP_DEBUG=1) after 15+ runs of the old path crashed
every time.

Also drops a dead subview-measurement call in WindowContentSizeClamp
(unrelated cleanup; explicitly not the crash fix, per its updated doc
comment).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@SergeSerb2 SergeSerb2 added the size:M Normal feature or meaningful behavior change label Aug 3, 2026
@SergeSerb2
SergeSerb2 merged commit 203e14e into main Aug 3, 2026
1 of 2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M Normal feature or meaningful behavior change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant