Files
vphone-cli/research/0_binary_patch_comparison.md
Managed via Tart d042596cc0 Complete Swift firmware patcher parity and CLI wiring
Run SwiftFormat on firmware patcher

Remove legacy Python firmware patchers

Fix compare pipeline pyimg4 PATH handling

Restore Python patchers and prefer fresh restore

Update BinaryBuffer.swift

Avoid double scanning in patcher apply

Prefer Python TXM site before fallback

Retarget TXM trustcache finder for 26.1

Remove legacy Python firmware patchers

Fail fast on nested virtualization hosts

Return nonzero on fatal boot startup

Add amfidont helper for signed boot binary

Stage AMFI boot args for next host reboot

Add host preflight for boot entitlements

Fail fast when boot entitlements are unavailable

Switch firmware patch targets to Swift CLI

Record real Swift firmware parity results

Verify Swift firmware pipeline end-to-end parity

Fix Swift firmware pipeline JB dry-run
2026-03-11 15:05:49 +08:00

36 KiB

Patch Comparison: Regular / Development / Jailbreak

Boot Chain Patches

AVPBooter

# Patch Purpose Regular Dev JB
1 mov x0, #0 DGST signature validation bypass Y Y Y

iBSS

# Patch Purpose Regular Dev JB
1 Serial labels (2x) "Loaded iBSS" in serial log Y Y Y
2 image4_validate_property_callback Signature bypass (b.ne -> NOP, mov x0,x22 -> mov x0,#0) Y Y Y
3 Skip generate_nonce Keep apnonce stable for SHSH (tbz -> unconditional b) - - Y

iBEC

# Patch Purpose Regular Dev JB
1 Serial labels (2x) "Loaded iBEC" in serial log Y Y Y
2 image4_validate_property_callback Signature bypass Y Y Y
3 Boot-args redirect ADRP+ADD -> serial=3 -v debug=0x2014e %s Y Y Y

LLB

# Patch Purpose Regular Dev JB
1 Serial labels (2x) "Loaded LLB" in serial log Y Y Y
2 image4_validate_property_callback Signature bypass Y Y Y
3 Boot-args redirect ADRP+ADD -> serial=3 -v debug=0x2014e %s Y Y Y
4 Rootfs bypass (5 patches) Allow edited rootfs loading Y Y Y
5 Panic bypass NOP cbnz after mov w8,#0x328 check Y Y Y

TXM

# Patch Purpose Regular Dev JB
1 Trustcache binary-search bypass bl hash_cmp -> mov x0, #0 Y Y Y
2 Selector24 bypass: mov w0, #0xa1 Return PASS (byte 1 = 0) after prologue - Y Y
3 Selector24 bypass: b <epilogue> Skip validation, jump to register restore - Y Y
4 get-task-allow (selector 41|29) bl -> mov x0, #1 - Y Y
5 Selector42|29 shellcode: branch to cave Redirect dispatch stub to shellcode - Y Y
6 Selector42|29 shellcode: NOP pad UDF -> NOP in code cave - Y Y
7 Selector42|29 shellcode: mov x0, #1 Set return value to true - Y Y
8 Selector42|29 shellcode: strb w0, [x20, #0x30] Set manifest flag - Y Y
9 Selector42|29 shellcode: mov x0, x20 Restore context pointer - Y Y
10 Selector42|29 shellcode: branch back Return from shellcode to stub+4 - Y Y
11 Debugger entitlement (selector 42|37) bl -> mov w0, #1 - Y Y
12 Developer mode bypass NOP conditional guard before deny path - Y Y

Kernelcache

Base Patches (All Variants)

# Patch Function Purpose Regular Dev JB
1 NOP tbnz w8,#5 _apfs_vfsop_mount Skip root snapshot sealed-volume check Y Y Y
2 NOP conditional _authapfs_seal_is_broken Skip root volume seal panic Y Y Y
3 NOP conditional _bsd_init Skip rootvp not-authenticated panic Y Y Y
4-5 mov w0,#0; ret _proc_check_launch_constraints Bypass launch constraints Y Y Y
6-7 mov x0,#1 (2x) PE_i_can_has_debugger Enable kernel debugger Y Y Y
8 NOP _postValidation Skip AMFI post-validation Y Y Y
9 cmp w0,w0 _postValidation Force comparison true Y Y Y
10-11 mov w0,#1 (2x) _check_dyld_policy_internal Allow dyld loading Y Y Y
12 mov w0,#0 _apfs_graft Allow APFS graft Y Y Y
13 cmp x0,x0 _apfs_vfsop_mount Skip mount check Y Y Y
14 mov w0,#0 _apfs_mount_upgrade_checks Allow mount upgrade Y Y Y
15 mov w0,#0 _handle_fsioc_graft Allow fsioc graft Y Y Y
16 NOP (3x) handle_get_dev_by_role Bypass APFS role-lookup deny gates for boot mounts Y Y Y
17-26 mov x0,#0; ret (5 hooks) Sandbox MACF ops table Stub 5 sandbox hooks Y Y Y

JB-Only Kernel Methods (Reference List)

# Group Method Function Purpose JB Enabled
JB-01 A patch_amfi_cdhash_in_trustcache AMFIIsCDHashInTrustCache Always return true + store hash Y
JB-02 A patch_amfi_execve_kill_path AMFI execve kill return site Convert shared kill return from deny to allow (superseded by C21; standalone only) N
JB-03 C patch_cred_label_update_execve _cred_label_update_execve Reworked C21-v3: C21-v1 already boots; v3 keeps split late exits and additionally ORs success-only helper bits 0xC after clearing 0x3F00; still disabled pending boot validation N
JB-04 C patch_hook_cred_label_update_execve sandbox mpo_cred_label_update_execve wrapper (ops[18] -> sub_FFFFFE00093BDB64) Faithful upstream C23 trampoline: copy VSUID/VSGID owner state into pending cred, set P_SUGID, then branch back to wrapper Y
JB-05 C patch_kcall10 sysent[439] (SYS_kas_info replacement) Rebuilt ABI-correct kcall cave: target + 7 args -> uint64 x0; re-enabled after focused dry-run validation Y
JB-06 B patch_post_validation_additional _postValidation (additional) Disable SHA256-only hash-type reject Y
JB-07 C patch_syscallmask_apply_to_proc syscallmask apply wrapper (_proc_apply_syscall_masks path) Faithful upstream C22: mutate installed Unix/Mach/KOBJ masks to all-ones via structural cave, then continue into setter; distinct from NULL-mask alternative Y
JB-08 A patch_task_conversion_eval_internal _task_conversion_eval_internal Allow task conversion Y
JB-09 A patch_sandbox_hooks_extended Sandbox MACF ops (extended) Stub remaining 30+ sandbox hooks (incl. IOKit 201..210) Y
JB-10 A patch_iouc_failed_macf IOUC MACF shared gate A5-v2: patch only the post-mac_iokit_check_open deny gate (CBZ W0, allow -> B allow) and keep the rest of the IOUserClient open path intact Y
JB-11 B patch_proc_security_policy _proc_security_policy Bypass security policy Y
JB-12 B patch_proc_pidinfo _proc_pidinfo Allow pid 0 info Y
JB-13 B patch_convert_port_to_map _convert_port_to_map_with_flavor Skip kernel map panic Y
JB-14 B patch_bsd_init_auth _bsd_init rootauth-failure branch Ignore FSIOC_KERNEL_ROOTAUTH failure in bsd_init; same gate as base patch #3 when layered Y
JB-15 B patch_dounmount _dounmount Allow unmount via upstream coveredvp cleanup-call NOP Y
JB-16 B patch_io_secure_bsd_root AppleARMPE::callPlatformFunction ("SecureRootName" return select), called from IOSecureBSDRoot Force "SecureRootName" policy return to success without altering callback flow; implementation retargeted 2026-03-06 Y
JB-17 B patch_load_dylinker _load_dylinker Skip strict LC_LOAD_DYLINKER == "/usr/lib/dyld" gate Y
JB-18 B patch_mac_mount ___mac_mount Upstream mount-role wrapper bypass (tbnz NOP + role-byte zeroing) Y
JB-19 B patch_nvram_verify_permission _verifyPermission (NVRAM) Allow NVRAM writes Y
JB-20 B patch_shared_region_map _shared_region_map_and_slide_setup Force root-vs-process-root mount compare to succeed before Cryptex fallback Y
JB-21 B patch_spawn_validate_persona _spawn_validate_persona Upstream dual-cbz persona helper bypass Y
JB-22 B patch_task_for_pid _task_for_pid Allow task_for_pid via upstream early pid == 0 gate NOP Y
JB-23 B patch_thid_should_crash _thid_should_crash Prevent GUARD_TYPE_MACH_PORT crash Y
JB-24 B patch_vm_fault_enter_prepare _vm_fault_enter_prepare Force cs_bypass fast path in runtime fault validation Y
JB-25 B patch_vm_map_protect _vm_map_protect Skip upstream write-downgrade gate in vm_map_protect Y

CFW Installation Patches

Binary Patches Applied Over SSH Ramdisk

# Patch Binary Purpose Regular Dev JB
1 /%s.gl -> /AA.gl seputil Gigalocker UUID fix Y Y Y
2 NOP cache validation launchd_cache_loader Allow modified launchd.plist Y Y Y
3 mov x0,#1; ret mobileactivationd Activation bypass Y Y Y
4 Plist injection launchd.plist bash/dropbear/trollvnc/vphoned daemons Y Y Y
5 b (skip jetsam guard) launchd Prevent jetsam panic on boot - Y Y
6 LC_LOAD_DYLIB injection launchd Load short alias /b (copy of launchdhook.dylib) at launch - - Y

Installed Components

# Component Description Regular Dev JB
1 Cryptex SystemOS + AppOS Decrypt AEA + mount + copy to device Y Y Y
2 GPU driver AppleParavirtGPUMetalIOGPUFamily bundle Y Y Y
3 iosbinpack64 Jailbreak tools (base set) Y Y Y
4 iosbinpack64 dev overlay Replace rpcserver_ios with dev build - Y -
5 vphoned vsock HID/control daemon (built + signed) Y Y Y
6 LaunchDaemons bash/dropbear/trollvnc/rpcserver_ios/vphoned plists Y Y Y
7 Procursus bootstrap Bootstrap filesystem + optional Sileo deb - - Y
8 BaseBin hooks systemhook.dylib / launchdhook.dylib / libellekit.dylib -> /cores/ plus /b alias for launchdhook.dylib - - Y
9 TweakLoader.dylib Lean user-tweak loader built from source and installed to /var/jb/usr/lib/TweakLoader.dylib - - Y

CFW Installer Flow Matrix (Script-Level)

Flow Item Regular (cfw_install.sh) Dev (cfw_install_dev.sh) JB (cfw_install_jb.sh)
Base CFW phases (1/7 -> 7/7) Runs directly Runs directly Runs via CFW_SKIP_HALT=1 zsh cfw_install.sh
Dev overlay (rpcserver_ios replacement) - Y (apply_dev_overlay) -
SSH readiness wait before install Y (wait_for_device_ssh_ready) - Y (inherited from base run)
launchd jetsam patch (patch-launchd-jetsam) - Y (base-flow injection) Y (JB-1)
launchd dylib injection (inject-dylib /b) - - Y (JB-1)

| Procursus bootstrap deployment | - | - | Y (JB-2) | | BaseBin hook deployment (*.dylib -> /mnt1/cores) | - | - | Y (JB-3) | | First-boot JB finalization (vphone_jb_setup.sh) | - | - | Y (post-boot; now fails before done marker if TrollStore Lite install does not complete) | | Additional input resources | cfw_input | cfw_input + resources/cfw_dev/rpcserver_ios | cfw_input + cfw_jb_input | | Extra tool requirement beyond base | - | - | zstd | | Halt behavior | Halts unless CFW_SKIP_HALT=1 | Halts unless CFW_SKIP_HALT=1 | Always halts after JB phases |

Summary

Component Regular Dev JB
AVPBooter 1 1 1
iBSS 2 2 3
iBEC 3 3 3
LLB 6 6 6
TXM 1 12 12
Kernel (base) 28 28 28
Kernel (JB methods) - - 59
Boot chain total 41 52 112
CFW binary patches 4 5 6
CFW installed components 6 7 9
CFW total 10 12 15
Grand total 51 64 127

Ramdisk Variant Matrix

Variant Pre-step Ramdisk/txm.img4 Ramdisk/krnl.ramdisk.img4 Ramdisk/krnl.img4 Effective kernel used by ramdisk_send.sh
RAMDISK make fw_patch release TXM + base TXM patch (1) base kernel (28), legacy *.ramdisk preferred else derive from pristine CloudOS restore kernel from fw_patch (28) krnl.ramdisk.img4 preferred, fallback krnl.img4
DEV+RAMDISK make fw_patch_dev release TXM + base TXM patch (1) base kernel (28), same derivation rule restore kernel from fw_patch_dev (28) krnl.ramdisk.img4 preferred, fallback krnl.img4
JB+RAMDISK make fw_patch_jb release TXM + base TXM patch (1) base kernel (28), same derivation rule restore kernel from fw_patch_jb (28+59) krnl.ramdisk.img4 preferred, fallback krnl.img4

Cross-Version Dynamic Snapshot

Case TXM_JB_PATCHES KERNEL_JB_PATCHES
PCC 26.1 (23B85) 14 59
PCC 26.3 (23D128) 14 59
iOS 26.1 (23B85) 14 59
iOS 26.3 (23D127) 14 59

Swift Migration Notes (2026-03-10)

  • Swift FirmwarePatcher now matches the Python reference patch output across all checked components:
    • avpbooter 1/1
    • ibss 4/4
    • ibec 7/7
    • llb 13/13
    • txm 1/1
    • txm_dev 12/12
    • kernelcache 28/28
    • ibss_jb 1/1
    • kernelcache_jb 84/84
  • JB parity fixes completed in Swift:
    • C23 vnode_getattr resolution now follows the Python backward BL scan and resolves 0x00CD44F8.
    • C22 syscallmask cave encodings were corrected and centralized in ARM64Constants.swift.
    • Task-conversion matcher masks and kernel-text scan range were corrected, restoring the patch at 0x00B0C400.
    • jbDecodeBranchTarget() now correctly decodes cbz/cbnz, restoring the real _bsd_init rootauth gate at 0x00F7798C.
    • IOUC MACF matching now uses Python-equivalent disassembly semantics for the aggregator shape, restoring the deny-to-allow patch at 0x01260644.
  • C24 kcall10 cave instruction bytes were re-verified against macOS clang/as; no Swift byte changes were needed.
  • The Swift pipeline is now directly invokable from the product binary:
    • vphone-cli patch-firmware --vm-directory <dir> --variant {regular|dev|jb}
    • vphone-cli patch-component --component {txm|kernel-base} --input <file> --output <raw> is available for non-firmware tooling that still needs a single patched payload during ramdisk packaging
    • default loader now preserves IM4P containers via IM4PHandler
    • DeviceTree patching now uses the real Swift DeviceTreePatcher in the pipeline
    • project make fw_patch, make fw_patch_dev, and make fw_patch_jb targets now invoke this Swift pipeline via the unsigned debug vphone-cli build, while the signed release build remains reserved for VM boot/DFU paths
    • on 2026-03-11, the legacy Python firmware patcher entrypoints and patch modules were temporarily restored from pre-removal history for parity/debug work.
    • after byte-for-byte parity was revalidated against Python on 26.1 and 26.3 for regular, dev, and jb, those legacy firmware-patcher Python sources and transient comparison/export helpers were removed again so the repo keeps Swift as the single firmware-patching implementation.
  • Swift pipeline follow-up fixes completed after CLI bring-up:
    • findFile() now supports glob patterns such as AVPBooter*.bin instead of treating them as literal paths.
    • JB variant sequencing now runs base iBSS/kernel patchers first, then the JB extension patchers.
    • Sequential pipeline application now merges each patcher's PatchRecord writes onto the shared output buffer while keeping later patcher searches anchored to the original payload, matching the standalone Swift/Python validation model.
    • apply() now reuses an already-populated patches array instead of re-running findAll(), so patch-firmware / patch-component no longer double-scan or double-print the same component diagnostics on a single invocation.
    • unaligned integer reads across the firmware patcher now go through a shared safe Data.loadLE(...) helper, fixing the JB IM4P crash (Swift/UnsafeRawPointer.swift:449 misaligned raw pointer load).
    • TXMPatcher now preserves pristine Python parity by preferring the legacy trustcache binary-search site when present, and only falls back to the selector24 hash-flags call chain (ldr x1, [x20,#0x38] -> add x2, sp, #4 -> bl -> ldp x0, x1, [x20,#0x30] -> add x2, sp, #8 -> bl) when rerunning on a VM tree that already carries the dev/JB selector24 early-return patch.
    • scripts/fw_prepare.sh now deletes stale sibling *Restore* directories in the working VM directory before patching continues, so a fresh make fw_prepare && make fw_patch cannot accidentally select an older prepared firmware tree (for example 26.1) when a newer one (for example 26.3) was just generated.
  • IM4P/output parity fixes completed after synthetic full-pipeline comparison:
    • IM4PHandler.save() no longer forces a generic LZFSE re-encode.
    • Swift now rebuilds IM4Ps in the same effective shape as the Python patch flow and only preserves trailing PAYP metadata for TXM (trxm) and kernelcache (krnl).
    • IBootPatcher serial labels now match Python casing exactly (Loaded iBSS, Loaded iBEC, Loaded LLB).
    • DeviceTreePatcher now serializes the full patched flat tree, matching Python dtree.py, instead of relying on in-place property writes alone.
  • Synthetic CLI dry-run status on 2026-03-10 using IM4P-backed inputs under ipsws/patch_refactor_input:
    • regular: 58 patch records
    • dev: 69 patch records
    • jb: 154 patch records
  • Full synthetic Python-vs-Swift pipeline comparison status on 2026-03-10 using scripts/compare_swift_python_pipeline.py:
    • regular: all 7 component payloads match
    • dev: all 7 component payloads match
    • jb: all 7 component payloads match
  • Real prepared-firmware Python-vs-Swift pipeline comparison status on 2026-03-10 using vm/ after make fw_prepare:
    • historical note: the now-removed scripts/compare_swift_python_pipeline.py cloned only the prepared *Restore* tree plus AVPBooter*.bin, AVPSEPBooter*.bin, and config.plist, avoiding No space left on device failures from copying Disk.img after make vm_new.
    • regular: all 7 component payloads match
    • dev: all 7 component payloads match
    • jb: all 7 component payloads match
  • Runtime validation blocker observed on 2026-03-10:
    • NONE_INTERACTIVE=1 SKIP_PROJECT_SETUP=1 make setup_machine JB=1 reaches the Swift patch stage and reports [patch-firmware] applied 154 patches for jb, then fails when the flow transitions into make boot_dfu.
    • make boot_dfu originally failed at launch-policy time with exit 137 / signal 9 because the release vphone-cli could not launch on this host.
    • amfidont was then validated on-host:
      • it can attach to /usr/libexec/amfid
      • the initial path allow rule failed because AMFIPathValidator reports URL-encoded paths (/Volumes/My%20Shared%20Files/...)
      • rerunning amfidont with the encoded project path and the release-binary CDHash allows the signed release vphone-cli to launch
      • this workflow is now packaged as make amfidont_allow_vphone / scripts/start_amfidont_for_vphone.sh
    • With launch policy bypassed, make boot_dfu advances into VM setup, emits vm/udid-prediction.txt, and then fails with VZErrorDomain Code=2 "Virtualization is not available on this hardware."
    • VPhoneAppDelegate startup failure handling was tightened so these fatal boot/DFU startup errors now exit non-zero; make boot_dfu now reports make: *** [boot_dfu] Error 1 for the nested-virtualization failure instead of incorrectly returning success.
    • The host itself is a nested Apple VM (Model Name: Apple Virtual Machine 1, kern.hv_vmm_present=1), so the remaining blocker is lack of nested Virtualization.framework availability rather than firmware patching or AMFI bypass.
    • boot_binary_check now uses strict host preflight and fails earlier on this class of host with make: *** [boot_binary_check] Error 3, avoiding a wasted VM-start attempt once the nested-virtualization condition is already known.
    • Added make boot_host_preflight / scripts/boot_host_preflight.sh to capture this state in one command:
      • model: Apple Virtual Machine 1
      • kern.hv_vmm_present: 1
      • SIP: disabled
      • allow-research-guests: disabled
      • current kern.bootargs: empty
      • next-boot nvram boot-args: amfi_get_out_of_my_way=1 -v (staged on 2026-03-10; requires reboot before it affects launch policy)
      • spctl --status: assessments enabled
      • spctl --assess rejects the signed release binary
      • unsigned debug vphone-cli --help: exit 0
      • signed release vphone-cli --help: exit 137
      • freshly signed debug control binary --help: exit 137

Automation Notes (2026-03-06)

  • scripts/setup_machine.sh non-interactive flow fix: renamed local variable status to boot_state in first-boot log wait and boot-analysis wait helpers to avoid zsh status read-only special parameter collision.
  • scripts/setup_machine.sh non-interactive first-boot wait fix: replaced (( waited++ )) with (( ++waited )) in monitor_boot_log_until to avoid set -e abort when arithmetic expression evaluates to 0.
  • scripts/jb_patch_autotest.sh loop fix for sweep stability under set -e: replaced ((idx++)) with (( ++idx )).
  • scripts/jb_patch_autotest.sh zsh compatibility fix: renamed per-case result variable status to case_status to avoid status read-only special parameter collision.
  • scripts/jb_patch_autotest.sh selection logic update:
    • default run now excludes methods listed in KernelJBPatcher._DEV_SINGLE_WORKING_METHODS (pending-only sweep).
    • set JB_AUTOTEST_INCLUDE_WORKING=1 to include already-working methods and run the full list.
  • Sweep run record:
    • setup_logs/jb_patch_tests_20260306_114417 (2026-03-06): aborted at [1/20] with read-only variable: status in jb_patch_autotest.sh.
    • setup_logs/jb_patch_tests_20260306_115027 (2026-03-06): rerun after status fix, pending-only mode (Total methods: 19).
  • Final run result from jb_patch_tests_20260306_115027 at 2026-03-06 13:17:
    • Finished: 19/19 (PASS=15, FAIL=4, all fails rc=2).
    • Failing methods at that time: patch_bsd_init_auth, patch_io_secure_bsd_root, patch_vm_fault_enter_prepare, patch_cred_label_update_execve.
    • 2026-03-06 follow-up: patch_io_secure_bsd_root failure is now attributed to a wrong-site patch in AppleARMPE::callPlatformFunction ("SecureRoot" gate at 0xFFFFFE000836E1F0), not the intended "SecureRootName" deny-return path. The code was retargeted the same day to 0xFFFFFE000836E464 and re-enabled for the next restore/boot check.
    • 2026-03-06 follow-up: patch_bsd_init_auth was retargeted after confirming the old matcher was hitting unrelated code; keep disabled in default schedule until a fresh clean-baseline boot test passes.
    • Final case: [19/19] patch_syscallmask_apply_to_proc (PASS).
    • 2026-03-06 re-analysis: that historical PASS is now treated as a false positive for functionality, because the recorded bytes landed at 0xfffffe00093ae6e4/0xfffffe00093ae6e8 inside _profile_syscallmask_destroy underflow handling, not in _proc_apply_syscall_masks.
    • 2026-03-06 code update: scripts/patchers/kernel_jb_patch_syscallmask.py was rebuilt to target the real syscallmask apply wrapper structurally and now dry-runs on PCC-CloudOS-26.1-23B85 kernelcache.research.vphone600 with 3 writes: 0x02395530, 0x023955E8, and cave 0x00AB1720. User-side boot validation succeeded the same day.
  • 2026-03-06 follow-up: patch_kcall10 was rebuilt from the old ABI-unsafe pseudo-10-arg design into an ABI-correct sysent[439] cave. Focused dry-run on PCC-CloudOS-26.1-23B85 kernelcache.research.vphone600 now emits 4 writes: cave 0x00AB1720, sy_call 0x0073E180, sy_arg_munge32 0x0073E188, and metadata 0x0073E190; the method was re-enabled in _GROUP_C_METHODS.
    • Observed failure symptom in current failing set: first boot panic before command injection (or boot process early exit).
  • Post-run schedule change (per user request):
    • commented out failing methods from default KernelJBPatcher._PATCH_METHODS schedule in scripts/patchers/kernel_jb.py:
      • patch_bsd_init_auth
      • patch_io_secure_bsd_root
      • patch_vm_fault_enter_prepare
      • patch_cred_label_update_execve
  • 2026-03-06 re-research note for patch_cred_label_update_execve:
    • old entry-time early-return strategy was identified as boot-unsafe because it skipped AMFI exec-time csflags and entitlement propagation entirely.
    • implementation was reworked to a success-tail trampoline that preserves normal AMFI processing and only clears restrictive csflags bits on the success path.
    • default JB schedule still keeps the method disabled until the reworked strategy is boot-validated.
  • Manual DEV+single (setup_machine + PATCH=<method>) working set now includes:
    • patch_amfi_cdhash_in_trustcache
    • patch_amfi_execve_kill_path
    • patch_task_conversion_eval_internal
    • patch_sandbox_hooks_extended
    • patch_post_validation_additional
  • 2026-03-07 host-side note:
    • reviewed private Virtualization.framework display APIs against the recorder pipeline in sources/vphone-cli/VPhoneScreenRecorder.swift.
    • replaced the old AppKit-first recorder path with a private-display-only implementation built around hidden VZGraphicsDisplay._takeScreenshotWithCompletionHandler: capture.
    • added still screenshot actions that can copy the captured image to the pasteboard or save a PNG to disk using the same private capture path.
    • make build is used as the sanity check path; live VM validation is still needed to confirm the exact screenshot object type returned on macOS 15.