Skip to content

core+agents: JIT bundle resolution stage 1 — R03 flips - #440

Merged
obj-p merged 1 commit into
mainfrom
jit-bundle-stage1
Jul 21, 2026
Merged

core+agents: JIT bundle resolution stage 1 — R03 flips#440
obj-p merged 1 commit into
mainfrom
jit-bundle-stage1

Conversation

@obj-p

@obj-p obj-p commented Jul 21, 2026

Copy link
Copy Markdown
Owner

What

Stage 1 of docs/jit-bundle-resolution.md: imageless JIT-compiled classes get their Bundle(for:) redirected to the target's built framework wrapper, closing R03's resource half (the last row of the dissolved resource-staging cluster).

  • The hook lives in each agent binary — a BundleRedirect objc_library on macOS (alwayslink, ARC-verified via aquery) and a keep-in-sync Swift mirror in the iOS agent app — because bridge generations can be torn down while the swizzled IMP must outlive them.
  • The generated bridge declares the agent's setter via @_silgen_name (the set_preview_vc precedent) and calls it before setup and before every render, unconditionally: a nil wrapper emits a clearing call, so an agent surviving a mid-session build-system identity flip cannot keep a stale path.
  • The wrapper rides BuildContext.resourceWrapperPath from CODESIGNING_FOLDER_PATH on both Xcode capture paths; SwiftPM and Bazel stay nil so the hook never installs there.
  • Predicate decided by the stage-opening diagnostic through the real JIT: ORC-materialized classes report class_getImageName == NULL with Bundle(for:) falling back to the agent's main bundle — the hook redirects exactly that combination.

Verification

  • Unit: BundleRedirectTests pins the hook decision table (redirect, real-class passthrough, replace, missing-path fallback, clear); BridgeGeneratorRedirectTests pins emission (set call before the view, clearing call on nil, setup-entry ordering, escaping). iOS agent builder hash re-pinned.
  • Manual matrix: R03 flipsXcode resources loaded, plist, Core Data model, and the generated color on macOS and iOS; R02 stays Spanish with the hook code present (inert on SPM); B04's real-image framework class keeps its own wrapper.
  • Gates: 4-angle /simplify + 4-angle adversarial review (runtime safety incl. ARC/deadlock/re-entrancy probes, plumbing/lifecycle incl. refresh and literal paths — all findings folded: @_silgen_name over dlsym, nil-clearing call, setup-entry ordering, iOS nil-class guard, doc placement); both local tiers + manual RegressToolGuardTests green; lint exit 0.

Follow-ups (in the design doc)

Stage 2 retires the Generated*Symbols.swift text rewrite once the hook's record is clean; stage 3 adds R03's macOS half to RegressGuardTests. Known accepted behaviors documented: runtime-generated imageless classes (KVO subclasses) over-redirect harmlessly; Xcode-embedded resource-bearing SwiftPM packages need their own matrix row before that combination ships.

🤖 Generated with Claude Code

Imageless JIT-compiled classes get their Bundle(for:) redirected to the
target's built framework wrapper. The hook lives in each agent binary
(BundleRedirect objc_library on macOS, AgentApp.swift mirror on iOS)
because bridge generations can be torn down while the swizzled IMP must
outlive them; the bridge calls previewsmcp_set_resource_wrapper via
dlsym before each render, installing once per process and refreshing
the path. The wrapper rides BuildContext.resourceWrapperPath from
CODESIGNING_FOLDER_PATH on both Xcode capture paths; SwiftPM and Bazel
stay nil so the hook never installs there.

The stage-opening diagnostic (probe preview through the real JIT)
decided the predicate: ORC-materialized classes report
class_getImageName == NULL with Bundle(for:) falling back to the
agent's main bundle, so the hook redirects exactly that combination.

Manual matrix: R03 flips on macOS and iOS (localized title, plist,
Core Data model, generated color); R02 stays Spanish with the hook code
present; B04's real-image framework class keeps its own wrapper. Unit
rows pin the hook decision table (BundleRedirectTests) and the
generator emission (BridgeGeneratorRedirectTests); the iOS agent
builder hash is re-pinned.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@obj-p obj-p added the merge Run CI and auto-merge (squash) on success label Jul 21, 2026
@obj-p
obj-p enabled auto-merge (squash) July 21, 2026 20:27
@obj-p
obj-p merged commit e62ad2d into main Jul 21, 2026
3 checks passed
@obj-p
obj-p deleted the jit-bundle-stage1 branch July 21, 2026 20:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge Run CI and auto-merge (squash) on success

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant