mobile-debug-mcp 0.35.0 → 0.37.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (247) hide show
  1. package/.cursor-plugin/marketplace.json +1 -1
  2. package/.github/workflows/ci.yml +1 -1
  3. package/README.md +96 -24
  4. package/agent-plugin/.antigravity-plugin/README.md +48 -0
  5. package/agent-plugin/.antigravity-plugin/plugin.json +18 -0
  6. package/agent-plugin/.claude-plugin/plugin.json +2 -2
  7. package/agent-plugin/.codex-plugin/plugin.json +1 -1
  8. package/agent-plugin/.cursor-plugin/plugin.json +2 -2
  9. package/agent-plugin/.mcp.json +1 -1
  10. package/agent-plugin/README.md +37 -8
  11. package/agent-plugin/cursor/.cursor-plugin/plugin.json +23 -0
  12. package/agent-plugin/cursor/LICENSE +201 -0
  13. package/agent-plugin/cursor/README.md +9 -0
  14. package/agent-plugin/cursor/skills/mobile-debug-mcp/SKILL.md +261 -0
  15. package/agent-plugin/mcp.json +1 -1
  16. package/agent-plugin/mcp_config.json +13 -0
  17. package/agent-plugin/plugin.json +1 -1
  18. package/agent-plugin/skills/mobile-debug-mcp/SKILL.md +46 -18
  19. package/dist/contracts/device-readiness.js +1 -0
  20. package/dist/debugger/guard.js +4 -4
  21. package/dist/debugger/ios-worker.js +62 -0
  22. package/dist/debugger/ios.js +57 -0
  23. package/dist/debugger/sessions.js +33 -16
  24. package/dist/debugger/worker.js +6 -4
  25. package/dist/interact/index.js +12 -2
  26. package/dist/interact/waits/ui-change-wait.js +9 -2
  27. package/dist/interact/waits/ui-wait.js +7 -3
  28. package/dist/manage/index.js +3 -0
  29. package/dist/manage/ios.js +2 -0
  30. package/dist/observe/device-readiness.js +116 -0
  31. package/dist/observe/evidence.js +31 -0
  32. package/dist/observe/ios-trace/artifact.js +63 -0
  33. package/dist/observe/ios-trace/capabilities.js +86 -0
  34. package/dist/observe/ios-trace/native.js +93 -0
  35. package/dist/observe/ios-trace/notification.js +35 -0
  36. package/dist/observe/ios-trace/process.js +98 -0
  37. package/dist/observe/ios-trace/sessions.js +246 -0
  38. package/dist/observe/readiness-service.js +22 -10
  39. package/dist/observe/readiness.js +34 -4
  40. package/dist/observe/screenshot-encoding.js +4 -0
  41. package/dist/observe/snapshot-collection.js +7 -2
  42. package/dist/observe/system-trace-error.js +7 -0
  43. package/dist/observe/system-trace-router.js +81 -0
  44. package/dist/observe/system-trace.js +4 -8
  45. package/dist/server/definitions/manage.js +3 -2
  46. package/dist/server/handlers/action-execution.js +23 -14
  47. package/dist/server/handlers/compact-interaction.js +106 -0
  48. package/dist/server/handlers/compact-state.js +47 -0
  49. package/dist/server/handlers/debugger-handlers.js +27 -8
  50. package/dist/server/handlers/diagnostic.js +12 -4
  51. package/dist/server/handlers/input.js +2 -0
  52. package/dist/server/handlers/interact.js +2 -0
  53. package/dist/server/handlers/interaction-diagnostics.js +62 -0
  54. package/dist/server/handlers/journey.js +18 -20
  55. package/dist/server/handlers/observe.js +2 -1
  56. package/dist/server/handlers/tool-handlers.js +28 -14
  57. package/dist/server/schemas/debugger-schema.js +10 -7
  58. package/dist/server/schemas/interaction-diagnostics.js +9 -0
  59. package/dist/server/schemas/system-trace-schema.js +14 -9
  60. package/dist/server/tool-definitions.js +9 -4
  61. package/dist/server-core.js +5 -2
  62. package/dist/server.js +5 -5
  63. package/dist/system/android.js +19 -15
  64. package/dist/system/index.js +2 -1
  65. package/dist/utils/android/utils.js +7 -16
  66. package/dist/utils/app-installation.js +77 -0
  67. package/dist/utils/benchmark-metrics.js +43 -0
  68. package/dist/utils/exec.js +4 -0
  69. package/dist/utils/ios/utils.js +7 -11
  70. package/dist/utils/resolve-device.js +3 -2
  71. package/dist/utils/timing.js +3 -3
  72. package/docs/CHANGELOG.md +48 -1
  73. package/docs/agent-plugin-installation-verification.md +39 -0
  74. package/docs/benchmarks/README.md +1 -0
  75. package/docs/benchmarks/end-to-end-latency/README.md +98 -0
  76. package/docs/benchmarks/end-to-end-latency/android-snapshot-pair.json +6532 -0
  77. package/docs/benchmarks/end-to-end-latency/android-snapshot-pair.md +30 -0
  78. package/docs/benchmarks/end-to-end-latency/baseline-attempt-1.json +15901 -0
  79. package/docs/benchmarks/end-to-end-latency/baseline-attempt-1.md +14 -0
  80. package/docs/benchmarks/end-to-end-latency/baseline.json +233843 -0
  81. package/docs/benchmarks/end-to-end-latency/baseline.md +21 -0
  82. package/docs/benchmarks/end-to-end-latency/investigation.md +128 -0
  83. package/docs/benchmarks/end-to-end-latency/ios-smoke.json +84 -0
  84. package/docs/benchmarks/end-to-end-latency/ios-smoke.md +9 -0
  85. package/docs/benchmarks/end-to-end-latency/smoke.json +19601 -0
  86. package/docs/benchmarks/end-to-end-latency/smoke.md +21 -0
  87. package/docs/code-structure.md +3 -1
  88. package/docs/specs/031-ios-system-traces/intent.md +38 -0
  89. package/docs/specs/031-ios-system-traces/investigation.md +92 -0
  90. package/docs/specs/031-ios-system-traces/late-run-failure-evidence.json +32 -0
  91. package/docs/specs/031-ios-system-traces/plan.md +166 -0
  92. package/docs/specs/031-ios-system-traces/pr102-monitor-evidence.json +22 -0
  93. package/docs/specs/031-ios-system-traces/simulator-evidence.json +47 -0
  94. package/docs/specs/031-ios-system-traces/spec.md +135 -0
  95. package/docs/specs/032-ios-runtime-debugger/evidence.json +176 -0
  96. package/docs/specs/032-ios-runtime-debugger/intent.md +38 -0
  97. package/docs/specs/032-ios-runtime-debugger/plan.md +95 -0
  98. package/docs/specs/032-ios-runtime-debugger/report.md +205 -0
  99. package/docs/specs/032-ios-runtime-debugger/spec.md +153 -0
  100. package/docs/specs/033-device-readiness-blockers/android-evidence.json +437 -0
  101. package/docs/specs/033-device-readiness-blockers/android-physical-evidence.json +28 -0
  102. package/docs/specs/033-device-readiness-blockers/android-physical-power-evidence.json +29 -0
  103. package/docs/specs/033-device-readiness-blockers/intent.md +41 -0
  104. package/docs/specs/033-device-readiness-blockers/ios-investigation.md +55 -0
  105. package/docs/specs/033-device-readiness-blockers/ios-probe-evidence.json +24 -0
  106. package/docs/specs/033-device-readiness-blockers/ios-tool-evidence.json +73 -0
  107. package/docs/specs/033-device-readiness-blockers/plan.md +249 -0
  108. package/docs/specs/033-device-readiness-blockers/spec.md +134 -0
  109. package/docs/specs/034-app-installation-status/intent.md +41 -0
  110. package/docs/specs/034-app-installation-status/native-evidence.json +654 -0
  111. package/docs/specs/034-app-installation-status/plan.md +73 -0
  112. package/docs/specs/034-app-installation-status/spec.md +114 -0
  113. package/docs/specs/035-compact-interaction-results/baseline.md +45 -0
  114. package/docs/specs/035-compact-interaction-results/intent.md +38 -0
  115. package/docs/specs/035-compact-interaction-results/plan.md +43 -0
  116. package/docs/specs/035-compact-interaction-results/spec.md +118 -0
  117. package/docs/specs/035-compact-interaction-results/verification.md +111 -0
  118. package/docs/specs/036-end-to-end-interaction-latency/android-snapshot-amendment.md +60 -0
  119. package/docs/specs/036-end-to-end-interaction-latency/android-snapshot-plan.md +32 -0
  120. package/docs/specs/036-end-to-end-interaction-latency/intent.md +37 -0
  121. package/docs/specs/036-end-to-end-interaction-latency/plan.md +59 -0
  122. package/docs/specs/036-end-to-end-interaction-latency/spec.md +126 -0
  123. package/docs/specs/036-end-to-end-interaction-latency/verification.md +87 -0
  124. package/docs/tools/TOOLS.md +3 -2
  125. package/docs/tools/compact-interactions.md +56 -0
  126. package/docs/tools/correlated-evidence.md +6 -0
  127. package/docs/tools/debugger.md +45 -5
  128. package/docs/tools/interact.md +17 -8
  129. package/docs/tools/manage.md +10 -2
  130. package/docs/tools/observe.md +42 -2
  131. package/docs/tools/system-traces.md +81 -14
  132. package/docs/tools/system.md +6 -0
  133. package/package.json +2 -1
  134. package/scripts/agent-plugin.mjs +55 -5
  135. package/src/contracts/device-readiness.ts +8 -0
  136. package/src/debugger/android.ts +1 -1
  137. package/src/debugger/guard.ts +5 -5
  138. package/src/debugger/ios-worker.ts +49 -0
  139. package/src/debugger/ios.ts +45 -0
  140. package/src/debugger/lldb/breakpoints.py +51 -0
  141. package/src/debugger/lldb/inspection.py +109 -0
  142. package/src/debugger/lldb/worker.py +203 -0
  143. package/src/debugger/sessions.ts +24 -12
  144. package/src/debugger/worker.ts +7 -4
  145. package/src/interact/index.ts +13 -2
  146. package/src/interact/waits/ui-change-wait.ts +7 -2
  147. package/src/interact/waits/ui-wait.ts +6 -3
  148. package/src/manage/index.ts +2 -0
  149. package/src/manage/ios.ts +2 -0
  150. package/src/observe/device-readiness.ts +96 -0
  151. package/src/observe/evidence.ts +30 -1
  152. package/src/observe/ios-trace/artifact.ts +55 -0
  153. package/src/observe/ios-trace/capabilities.ts +74 -0
  154. package/src/observe/ios-trace/native.ts +72 -0
  155. package/src/observe/ios-trace/notification.ts +30 -0
  156. package/src/observe/ios-trace/process.ts +82 -0
  157. package/src/observe/ios-trace/sessions.ts +206 -0
  158. package/src/observe/readiness-service.ts +22 -10
  159. package/src/observe/readiness.ts +37 -4
  160. package/src/observe/screenshot-encoding.ts +4 -0
  161. package/src/observe/snapshot-collection.ts +7 -2
  162. package/src/observe/system-trace-error.ts +3 -0
  163. package/src/observe/system-trace-router.ts +61 -0
  164. package/src/observe/system-trace.ts +4 -4
  165. package/src/server/common.ts +2 -2
  166. package/src/server/definitions/manage.ts +3 -2
  167. package/src/server/handlers/action-execution.ts +22 -14
  168. package/src/server/handlers/compact-interaction.ts +91 -0
  169. package/src/server/handlers/compact-state.ts +43 -0
  170. package/src/server/handlers/debugger-handlers.ts +28 -9
  171. package/src/server/handlers/diagnostic.ts +11 -4
  172. package/src/server/handlers/input.ts +2 -0
  173. package/src/server/handlers/interact.ts +2 -0
  174. package/src/server/handlers/interaction-diagnostics.ts +50 -0
  175. package/src/server/handlers/journey.ts +15 -17
  176. package/src/server/handlers/observe.ts +2 -1
  177. package/src/server/handlers/payload.ts +2 -1
  178. package/src/server/handlers/tool-handlers.ts +29 -14
  179. package/src/server/schemas/debugger-schema.ts +10 -7
  180. package/src/server/schemas/interaction-diagnostics.ts +10 -0
  181. package/src/server/schemas/system-trace-schema.ts +15 -9
  182. package/src/server/tool-definitions.ts +8 -4
  183. package/src/server-core.ts +5 -2
  184. package/src/server.ts +4 -4
  185. package/src/system/android.ts +18 -11
  186. package/src/system/index.ts +2 -1
  187. package/src/types.ts +2 -0
  188. package/src/utils/android/utils.ts +8 -10
  189. package/src/utils/app-installation.ts +73 -0
  190. package/src/utils/benchmark-metrics.ts +42 -0
  191. package/src/utils/exec.ts +5 -0
  192. package/src/utils/ios/utils.ts +7 -10
  193. package/src/utils/resolve-device.ts +4 -2
  194. package/src/utils/timing.ts +3 -2
  195. package/test/device/automated/debugger/runtime.android.test.ts +5 -0
  196. package/test/device/automated/debugger/runtime.ios.test.ts +227 -0
  197. package/test/device/automated/interact/compact-results.smoke.ts +58 -0
  198. package/test/device/automated/latency/end-to-end-environment.ts +61 -0
  199. package/test/device/automated/latency/end-to-end-report.ts +90 -0
  200. package/test/device/automated/latency/end-to-end-session.ts +98 -0
  201. package/test/device/automated/latency/end-to-end.ts +149 -0
  202. package/test/device/automated/latency/owned-transport.ts +81 -0
  203. package/test/device/automated/latency/snapshot-pair.ts +143 -0
  204. package/test/device/automated/latency-ios/benchmark.ts +126 -0
  205. package/test/device/automated/observe/correlated-evidence.smoke.ts +7 -5
  206. package/test/device/automated/observe/device-readiness-cleanup.ts +14 -0
  207. package/test/device/automated/observe/device-readiness.android.smoke.ts +78 -0
  208. package/test/device/automated/observe/ios-system-trace.smoke.ts +119 -0
  209. package/test/device/automated/observe/system-trace.smoke.ts +2 -2
  210. package/test/fixtures/contracts/tool-definitions.json +243 -47
  211. package/test/fixtures/ios-debugger-app/Main.swift +95 -0
  212. package/test/fixtures/ios-debugger-app/README.md +27 -0
  213. package/test/fixtures/ios-debugger-app/build.ts +21 -0
  214. package/test/fixtures/latency-journey-app/build.ts +3 -3
  215. package/test/helpers/ios-trace-shutdown.ts +29 -0
  216. package/test/unit/debugger/handle-guards.test.ts +89 -0
  217. package/test/unit/debugger/ios-preparation.test.ts +57 -0
  218. package/test/unit/debugger/ios.test.ts +104 -0
  219. package/test/unit/debugger/lldb-worker.py +166 -0
  220. package/test/unit/debugger/lldb-worker.test.ts +10 -0
  221. package/test/unit/interact/ui-change-readiness-interruption.test.ts +37 -0
  222. package/test/unit/observe/capture_debug_snapshot.test.ts +66 -12
  223. package/test/unit/observe/device-readiness-cleanup.test.ts +24 -0
  224. package/test/unit/observe/device-readiness.test.ts +97 -0
  225. package/test/unit/observe/ios-trace-native.test.ts +90 -0
  226. package/test/unit/observe/ios-trace-sessions.test.ts +154 -0
  227. package/test/unit/observe/readiness-retained-blockers.test.ts +40 -0
  228. package/test/unit/observe/readiness.test.ts +1 -1
  229. package/test/unit/observe/system-trace-router.test.ts +49 -0
  230. package/test/unit/quality/agent-plugin-export.test.ts +38 -0
  231. package/test/unit/server/compact-interaction.test.ts +87 -0
  232. package/test/unit/server/compact-journey-evidence.test.ts +40 -0
  233. package/test/unit/server/compact-review-regressions.test.ts +78 -0
  234. package/test/unit/server/conditional_actions.test.ts +7 -3
  235. package/test/unit/server/correlated-evidence.test.ts +18 -6
  236. package/test/unit/server/end-to-end-report.test.ts +46 -0
  237. package/test/unit/server/input-device-readiness.test.ts +55 -0
  238. package/test/unit/server/interaction-diagnostics.test.ts +45 -0
  239. package/test/unit/server/owned-benchmark-transport.test.ts +32 -0
  240. package/test/unit/server/readiness-retained-deadline.test.ts +32 -0
  241. package/test/unit/server/readiness.test.ts +24 -1
  242. package/test/unit/server/run_journey.test.ts +2 -1
  243. package/test/unit/server/selector_tap_target.test.ts +2 -1
  244. package/test/unit/server/system-trace.test.ts +18 -7
  245. package/test/unit/utils/app-installation.test.ts +78 -0
  246. package/test/unit/utils/benchmark-metrics.test.ts +36 -0
  247. package/test/unit/utils/resolve_device.test.ts +11 -0
@@ -0,0 +1,176 @@
1
+ {
2
+ "date": "2026-11-04",
3
+ "status": "PASS",
4
+ "transport": "MCP stdio",
5
+ "runtime": "v23.11.0",
6
+ "deviceId": "F9243BAF-62A8-4990-8A99-17F527F56FDA",
7
+ "server_sha256": "6a00a33d994a449ecbb54d5dbf894780f48a1c0e5a89fc871b91dd7048f4ecdc",
8
+ "source_sha256": "295ff0f30f5670530f9cdd7073b958917c1c574ccca9c7b921e295d0d902b699",
9
+ "xcode": "Xcode 27.2\nBuild version 27B52",
10
+ "lldb": "lldb-2103.0.34.407\nApple Swift version 6.4.2 (swiftlang-6.4.2.1.9 clang-2100.4.1.1)",
11
+ "fixture": "test/fixtures/ios-debugger-app/Main.swift",
12
+ "fixture_triggers": "Atomic command file; installed idb HID backend unavailable; not proof of successful MCP tap injection",
13
+ "extended_pause_expiry": true,
14
+ "process_exit": true,
15
+ "server_shutdown_recovery": true,
16
+ "tests_sha256": "37fbda265b5735b1b826aa448aa937359c45db0e55f8f1998a169b1aa3073acc",
17
+ "observations": [
18
+ {
19
+ "reason": "breakpoint",
20
+ "line": 49,
21
+ "method": "DebuggerFixture.Controller.calculate() -> ()"
22
+ },
23
+ {
24
+ "reason": "step",
25
+ "line": 8,
26
+ "method": "DebuggerFixture.helper(Swift.Int) -> Swift.Int"
27
+ },
28
+ {
29
+ "reason": "step",
30
+ "line": 9,
31
+ "method": "DebuggerFixture.helper(Swift.Int) -> Swift.Int"
32
+ },
33
+ {
34
+ "reason": "step",
35
+ "line": 49,
36
+ "method": "DebuggerFixture.Controller.calculate() -> ()"
37
+ },
38
+ {
39
+ "reason": "breakpoint",
40
+ "line": 20,
41
+ "method": "(1) suspend resume partial function for DebuggerFixture.AsyncWork.calculate(Swift.Int) async -> Swift.Int"
42
+ },
43
+ {
44
+ "reason": "breakpoint",
45
+ "line": 21,
46
+ "method": "(3) suspend resume partial function for DebuggerFixture.AsyncWork.calculate(Swift.Int) async -> Swift.Int"
47
+ },
48
+ {
49
+ "reason": "breakpoint",
50
+ "line": 20,
51
+ "method": "(1) suspend resume partial function for DebuggerFixture.AsyncWork.calculate(Swift.Int) async -> Swift.Int"
52
+ },
53
+ {
54
+ "reason": "step",
55
+ "line": 21,
56
+ "method": "(3) suspend resume partial function for DebuggerFixture.AsyncWork.calculate(Swift.Int) async -> Swift.Int"
57
+ },
58
+ {
59
+ "reason": "breakpoint",
60
+ "line": 66,
61
+ "method": "(3) suspend resume partial function for closure #1 () async -> () in DebuggerFixture.Controller.startCancellation() -> ()"
62
+ },
63
+ {
64
+ "reason": "breakpoint",
65
+ "line": 49,
66
+ "method": "DebuggerFixture.Controller.calculate() -> ()"
67
+ },
68
+ {
69
+ "reason": "breakpoint",
70
+ "line": 49,
71
+ "method": "DebuggerFixture.Controller.calculate() -> ()"
72
+ }
73
+ ],
74
+ "locals": [
75
+ [
76
+ {
77
+ "name": "known",
78
+ "type": "Swift.Int",
79
+ "value": "41"
80
+ }
81
+ ],
82
+ [
83
+ {
84
+ "name": "seed",
85
+ "type": "Swift.Int",
86
+ "value": "42"
87
+ },
88
+ {
89
+ "name": "known",
90
+ "type": "Swift.Int",
91
+ "value": "42"
92
+ }
93
+ ],
94
+ [
95
+ {
96
+ "name": "seed",
97
+ "type": "Swift.Int",
98
+ "value": "42"
99
+ },
100
+ {
101
+ "name": "known",
102
+ "type": "Swift.Int",
103
+ "value": "42"
104
+ },
105
+ {
106
+ "name": "after",
107
+ "type": "Swift.Int",
108
+ "value": "43"
109
+ }
110
+ ],
111
+ [
112
+ {
113
+ "name": "cancelled",
114
+ "type": "Swift.Bool",
115
+ "value": "true"
116
+ }
117
+ ]
118
+ ],
119
+ "async_boundary_step": {
120
+ "expected_line": 21,
121
+ "observed": {
122
+ "source_file": "test/fixtures/ios-debugger-app/Main.swift",
123
+ "line": 21,
124
+ "method_name": "(3) suspend resume partial function for DebuggerFixture.AsyncWork.calculate(Swift.Int) async -> Swift.Int",
125
+ "class_name": null
126
+ }
127
+ },
128
+ "assertions": [
129
+ "Exact source binding and pending source creation",
130
+ "Known primitive locals",
131
+ "Into/over/out",
132
+ "Stop/frame stale rejection",
133
+ "Paused tap rejected before dispatch",
134
+ "Paused readiness without UI acquisition",
135
+ "Cancelled event wait preserves session",
136
+ "Before/after await values and nested async child",
137
+ "Step over await reaches after-await source line",
138
+ "Task cancellation and fresh Task cancelled UI",
139
+ "Real 60-second pause expiry and fresh result UI",
140
+ "Target self-exit, disconnected state and complete cleanup",
141
+ "Idempotent detach with no remaining resources",
142
+ "Server shutdown while paused then independent UI recovery"
143
+ ],
144
+ "unrun": [
145
+ "physical iOS devices",
146
+ "other Xcode/Swift versions",
147
+ "optimized apps",
148
+ "installed/published package",
149
+ "forced host termination",
150
+ "real device disconnect",
151
+ "live idle/absolute expiry",
152
+ "late-loaded-image binding"
153
+ ],
154
+ "scope": "Focused real MCP iOS simulator debugger journey, including extended pause expiry",
155
+ "repository_verification": {
156
+ "status": "PASS",
157
+ "unit_files": 96,
158
+ "command": "npm run verify"
159
+ },
160
+ "broader_device_suite": {
161
+ "status": "FAIL",
162
+ "observations": [
163
+ "Initial Android interaction SDK timeout; isolated unchanged retry passed",
164
+ "Retry failed Android Perfetto shutdown-artifact assertion; isolated baseline and current checks passed"
165
+ ],
166
+ "root_cause": "unestablished",
167
+ "full_suite_pass_claimed": false
168
+ },
169
+ "cleanup": {
170
+ "ios_simulator": "restored to initial shutdown state",
171
+ "swift_fixture_build_directories_remaining": 0,
172
+ "owned_adb_forwards_remaining": 0,
173
+ "owned_perfetto_artifacts_remaining": 0,
174
+ "unrelated_installed_fixtures": "preserved"
175
+ }
176
+ }
@@ -0,0 +1,38 @@
1
+ # iOS runtime debugger — intent
2
+
3
+ - Source: [issue #70](https://github.com/clivejefferies/mobile-debug-tools/issues/70), and the user's 2026-11-04 request to take the next Ready ticket with Android-equivalent functionality, including async debugging.
4
+ - Originator: user in this chat.
5
+ - Captured: 2026-11-04.
6
+ - Status: intent approved by the user's “ok” on 2026-11-04 in response to the scope and approval request in this chat. Specification also approved in this chat on 2026-11-04; see spec.md. Issue #70 matches the roadmap and current branch; Ready-column membership could not be checked because GitHub authentication lacks `read:project`.
7
+
8
+ ## Problem and outcome
9
+
10
+ MCP clients can debug Android development apps but lack equivalent iOS runtime
11
+ inspection. Add an LLDB-backed debugger for iOS simulator development apps,
12
+ reusing the existing debugger tools and session/evidence conventions where
13
+ appropriate. Support attach, source breakpoints and events, bounded stacks and
14
+ shallow locals, stepping, resume and detach, with explicit capabilities and
15
+ actionable setup failures.
16
+
17
+ ## Async parity and success
18
+
19
+ Verify a deterministic Swift concurrency fixture with source stops and useful
20
+ locals before and after `await`, resumed execution, nested task work, task
21
+ cancellation and application recovery. Assess stepping across suspension and
22
+ report its observed limits. Android's existing coroutine assessment establishes
23
+ execution inspection, not reconstruction of suspended tasks or logical async
24
+ stacks; distinguish those capabilities explicitly on iOS too.
25
+
26
+ Preserve stale-reference rejection, pause-aware interaction guards, bounded
27
+ waits/cancellation, session isolation, expiry and owned cleanup. Prove the journey
28
+ through actual MCP calls and independent fixture outcomes, and retain Android
29
+ regression coverage. Report unavailable environments honestly.
30
+
31
+ ## Constraints and questions
32
+
33
+ Physical-device support follows separately. Evaluation, mutation, arbitrary LLDB
34
+ commands and generic suspended-task reconstruction are excluded from this initial
35
+ scope. Inspect LLDB/Xcode support for async frames and stepping before proposing
36
+ the exact capability contract. Debug values remain bounded and sensitive; avoid
37
+ persisting app data in public evidence. Specification approval follows intent
38
+ acceptance under the repository process.
@@ -0,0 +1,95 @@
1
+ # iOS runtime debugger — implementation and verification
2
+
3
+ Scope: [intent](intent.md) and [specification](spec.md), both approved by the user
4
+ on 2026-11-04. Use the repository MCP Builder and Test Authoring skills.
5
+
6
+ ## Implementation
7
+
8
+ - [x] Establish LLDB Python loading and explicit simulator/process attribution.
9
+ - [x] Add structured LLDB worker, safe inspection, exact breakpoints and watchdogs.
10
+ - [x] Reuse session lifecycle with platform-specific native/worker configuration;
11
+ update schemas, dispatch, diagnostics, guards and readiness.
12
+ - [x] Add deterministic Swift simulator fixture and MCP runtime/async journeys.
13
+ - [x] Add contract, identity, lifecycle and guard regression tests; update tool
14
+ compatibility golden only for approved schema changes.
15
+ - [x] Align debugger guide, tool reference, README, changelog and packaging.
16
+ - [x] Review diff, execute required verification and record actual results below.
17
+ Full-suite success remains unestablished; see the failed checks below.
18
+
19
+ ## Verification matrix
20
+
21
+ | Spec criterion | Check |
22
+ | --- | --- |
23
+ | Core runtime flow | `MCP_IOS_DEBUGGER_DEVICE=<UDID> node --import tsx test/device/automated/debugger/runtime.ios.test.ts` through built stdio server |
24
+ | Async/cancellation | Same journey with controlled before/after-await values, nested work, cancellation and fresh UI assertions; separate step-boundary result |
25
+ | Identity, failure, references and guards | Focused `test/unit/debugger/*.test.ts`, simulator invalid PID/foreign target, stale frame/stop, guarded input/readiness, event cancellation and detach |
26
+ | Expiry and shutdown | Worker watchdog unit checks plus real pause expiry and server EOF cleanup in fixture journey |
27
+ | Contract/Android regression | `npm run verify`; existing runtime, Kotlin and coroutine Android MCP checks on explicit emulator |
28
+ | Broader device compatibility | `npm run test:device` with selected targets; report the actual covered platforms and skipped prerequisites |
29
+
30
+ Required: Node 22+, installed Xcode 27.2/Swift 6.4.2/LLDB 2103.0.34.407,
31
+ simulator runtime, development fixture compiled with debug metadata and no
32
+ optimisation. Android regressions require existing JDK/SDK/Kotlin dependencies.
33
+ No physical-device iOS support is claimed. Hosted CI is separate from local checks.
34
+
35
+ Select existing simulator F9243BAF-62A8-4990-8A99-17F527F56FDA (iPhone 17 Pro,
36
+ iOS 26.4), initially shut down. Boot it for the fixture; preserve existing apps
37
+ and settings, install/remove only fixture-owned app/build files, detach owned
38
+ debuggers, and restore the initial shutdown state. Record exact server/fixture
39
+ hashes, observed stops/locals, independent UI state and cleanup. Simulator access
40
+ requires outside-sandbox native commands; the authorised inventory read succeeded.
41
+ If a prerequisite is unavailable, retain the acceptance criterion and record a
42
+ concrete blocker. Do not treat mock/native readiness checks as live verification.
43
+
44
+ ## Results
45
+
46
+ - **PASS** `npm run verify`: lint/quality/architecture, build, all 96 unit files,
47
+ plugin consistency, Node 23.11.0. Log `/tmp/ios-debugger-final-verify.log`.
48
+ - **PASS** `MCP_IOS_DEBUGGER_DEVICE=F9243BAF-62A8-4990-8A99-17F527F56FDA MCP_IOS_DEBUGGER_EXTENDED=1 node --import tsx test/device/automated/debugger/runtime.ios.test.ts`.
49
+ Exact stable-build hash, stops, locals and asserted cleanup/recovery are in
50
+ [evidence.json](evidence.json). No HID success is inferred from fixture control.
51
+ - **PASS** focused Android runtime, Kotlin locals and coroutine MCP regressions
52
+ using the existing fixture/compiler dependencies. The broader suite also reran
53
+ the final Android runtime debugger successfully.
54
+ - **PASS** unchanged standalone iOS screenshot, log and UI-tree smoke checks.
55
+ - **PASS** package dry-run contents, plugin generation/consistency and diff/link
56
+ checks. No publication or installed-package verification occurred.
57
+ - **FAIL** broader `ADB_PATH=/Users/clivejefferies/Library/Android/sdk/platform-tools/adb MCP_DEBUGGER_DEVICE=emulator-5554 npm run test:device`: initial Android
58
+ interaction request timeout; focused unchanged retry passed. The full-suite
59
+ retry passed that branch and both-platform observations/correlated evidence,
60
+ then failed Android Perfetto active-shutdown artifact removal. The isolated
61
+ Perfetto check passed on both unchanged HEAD and current build. These failures
62
+ remain unreproduced and unexplained; no full-suite pass is claimed.
63
+ - Full-suite opt-in Kotlin/coroutine/iOS debugger checks were **UNRUN** in that
64
+ invocation; each passed its separate focused run above. iOS system tracing was
65
+ **UNRUN** (no `IOS_SYSTEM_TRACE_DEVICE` supplied); it is outside this feature.
66
+ - **PASS** owned cleanup: no MCP device trace files or ADB forwards remained;
67
+ debugger/coroutine packages and Swift build directories removed. Unrelated
68
+ fixtures preserved; iOS simulator restored to shutdown; Android emulator left
69
+ running. Temporary baseline source/build copy removed.
70
+
71
+ See [verification report](report.md) for evidence boundaries, resolved findings,
72
+ unrun variants and original failed observations.
73
+
74
+
75
+ ## PR #103 review repair
76
+
77
+ - [x] Cache shared iOS preparation and reset rejected preparation for retry.
78
+ - [x] Add fake-toolchain coverage for concurrent reuse, retry and worker creation.
79
+ - [x] Check real Xcode cached preparation and rerun the focused iOS MCP journey.
80
+ - [x] Complete quiet repository verification (97 unit files); publish the repair to PR #103.
81
+
82
+ See the [report follow-up](report.md#pr-103-preparation-cache-follow-up--2026-11-04)
83
+ for exact evidence and retained broader-suite limitations.
84
+
85
+
86
+ ## PR #103 stored-handle pause guard repair
87
+
88
+ - [x] Validate guard targets through the stored-handle execution lookup.
89
+ - [x] Cover omitted/partial hints, known/racing pauses, platform/device isolation,
90
+ and explicit mismatches; prove regression detects the original route.
91
+ - [x] Run `npm run verify` (98 unit files) and the updated real iOS MCP journey.
92
+ - [x] Restore fixture/device state and prepare the narrow repair for PR publication.
93
+
94
+ The finding is in an outside-diff review summary, with no new inline thread to
95
+ resolve. See the [report](report.md) for exact evidence and retained limitations.
@@ -0,0 +1,205 @@
1
+ # iOS runtime debugger verification — issue #70
2
+
3
+ Date: 2026-11-04. Scope: [approved specification](spec.md).
4
+ Implementation: existing eleven MCP debugger tools gain the optional simulator
5
+ LLDB backend; Android remains on JDI. This is local source/build verification,
6
+ not hosted CI, an installed package, a publication or physical-device evidence.
7
+
8
+ ## Environment and method
9
+
10
+ macOS, Node 23.11.0 (repository requires >=22; hosted CI selects Node 22),
11
+ Xcode 27.2/27B52, LLDB 2103.0.34.407 and Swift 6.4.2. Simulator:
12
+ F9243BAF-62A8-4990-8A99-17F527F56FDA, iPhone 17 Pro, iOS 26.4.
13
+ The disposable Swift fixture uses `-g -Onone`, targeting iOS 18 simulator.
14
+
15
+ The runner communicates with a freshly built stdio MCP server. It checks actual
16
+ source stops, stack frames and synthetic known-value locals; independent fresh
17
+ MCP UI-tree assertions establish completion/cancellation and recovery. It does
18
+ not infer logical task identity from opaque thread IDs or task/thread names.
19
+
20
+ Installed idb can read UI trees but cannot inject HID with this Xcode: its
21
+ SimulatorKit framework path is absent. Therefore fixture actions use a private
22
+ command file, delivered by atomic rename and handled by the fixture main-loop
23
+ timer. This is independent fixture control, not proof of successful MCP tap
24
+ injection. Paused MCP taps are checked for rejection before dispatch. No
25
+ production app instrumentation, source evaluation or security changes are used.
26
+
27
+ ## Evidence and results
28
+
29
+ The final stable-build simulator journey **PASS**ed with real pause expiry enabled.
30
+ [Compact evidence](evidence.json) records the exact server/fixture/test hashes,
31
+ source stops and bounded synthetic values. Recomputing the final source/build hash
32
+ matched the runtime fingerprint. Log: `/tmp/ios-debugger-final.log`.
33
+
34
+ | Check | Result |
35
+ | --- | --- |
36
+ | Exact source binding; pending source; non-executable line rejection | PASS |
37
+ | Core stack/locals and into/over/out | PASS: known=41, fresh result=42 UI |
38
+ | Pause guard/readiness and stale references | PASS |
39
+ | Cancelled event wait and usable running session | PASS |
40
+ | Before/after await with nested async child and actor/main-actor transitions | PASS: known=42, after=43, fresh Async result 44 UI |
41
+ | Step over await | PASS: source line 20 to line 21 in the resumed partial function |
42
+ | Task cancellation | PASS: cancelled=true and fresh Task cancelled UI |
43
+ | Real 60-second pause expiry | PASS: pause_limit, complete cleanup and fresh result UI |
44
+ | Target process exit | PASS: disconnected state, complete cleanup and fixture relaunch |
45
+ | Idempotent detach and server shutdown while paused | PASS: no remaining resources; independent fresh result UI |
46
+
47
+ `npm run verify` **PASS**: lint/structural/architecture checks, TypeScript build,
48
+ all 96 unit files and generated plugin consistency. Log:
49
+ `/tmp/ios-debugger-final-verify.log`. The portable usage skill and generated Cursor
50
+ copy now describe the advertised iOS backend; this does not install/update a
51
+ connected or pinned published server.
52
+
53
+ The broader device suite passed the final Android debugger regression, then
54
+ **FAIL**ed on an Android interaction SDK request timeout (120000 ms); its original
55
+ log does not identify the call. A focused assertion-identical retry with tool-name
56
+ and elapsed-time logging **PASS**ed every call (approximately 47 seconds total).
57
+ The timeout was not reproduced and its cause is unknown; no assertion, timeout,
58
+ retry policy or interaction implementation was changed. Original and retry logs:
59
+ `/tmp/ios-debugger-device-suite.log` and
60
+ `/tmp/ios-debugger-interaction-retest.log`. The unchanged full-suite retry passed the Android debugger/interaction checks and
61
+ both-platform screenshot/log/tree/correlated-evidence checks, then **FAIL**ed the
62
+ last Android Perfetto active-shutdown cleanup assertion (one owned capture file
63
+ still existed). Log: `/tmp/ios-debugger-device-suite-retry.log`.
64
+
65
+ The same isolated Perfetto test then **PASS**ed on both unmodified HEAD
66
+ `8bafc318a6342cf4585621d2108353836d40f72d` (archived and compiled in a temporary
67
+ copy using the same dependencies) and the current build. Logs:
68
+ `/tmp/ios-debugger-trace-baseline.log`, `/tmp/ios-debugger-trace-current.log`.
69
+ This does not establish the original timeout/cleanup cause or prove it fixed.
70
+ No tracing source, assertion or deadline was changed; no full device-suite pass
71
+ is claimed. The failed check's exact owned artifact was removed through the
72
+ existing identity-checking trace adapter. Final checks found no MCP capture files
73
+ or ADB forwards. Debugger/coroutine test packages and Swift build directories were
74
+ removed; unrelated installed fixtures were preserved. The iOS simulator was
75
+ returned to its initial shutdown state; the Android emulator remains running.
76
+
77
+ Independent unchanged iOS screenshot, log and UI-tree smoke checks **PASS**ed.
78
+ Log: `/tmp/ios-debugger-ios-observations.log`. These establish observation delivery
79
+ and structure, not a layout claim or successful HID input.
80
+
81
+ The initial Android runtime, Kotlin locals and coroutine MCP regressions passed
82
+ on emulator-5554, Android 16/API 36. Kotlin/stdlib 2.0.21, coroutines 1.9.0 and
83
+ fixture JDK 17.0.11 used existing cached dependencies and `/tmp/pr96-kotlinc`.
84
+ The debugger uses its ordinary Android Studio JBR discovery. Raw local logs:
85
+ `/tmp/ios-debugger-android-regression.log`,
86
+ `/tmp/ios-debugger-kotlin-regression.log`,
87
+ `/tmp/ios-debugger-coroutine-regression.log`.
88
+
89
+ `npm pack --dry-run --json` and explicit contents assertions passed for all three
90
+ LLDB Python modules and compiled iOS backend modules. CI packaging assertions now
91
+ cover these resources. This does not establish installed-package loading.
92
+
93
+ ## Findings resolved during development
94
+
95
+ - Ignore internal LLDB transitions without stopped-thread evidence; consume LLDB
96
+ process events before reading public process/thread snapshots.
97
+ - Keep fixture variables live across await. The original constant's scope had no
98
+ location in a resume partial function; requiring its later use preserved actual
99
+ `known=42` inspection. Assertions were retained, not replaced by availability.
100
+ - Use LLDB's invalid-line sentinel for the error-reporting StepInto overload;
101
+ line zero is not that sentinel. Check native step errors before acknowledging.
102
+ - Normalize Swift Bool static storage to textual true/false; never evaluate a
103
+ getter, formatter, expression or object description.
104
+ - Preserve known suspension when a stale/invalid step is rejected. Diagnostic
105
+ lifecycle fallbacks cannot bypass pause guards.
106
+ - Bound and reuse frame references; preserve cleanup uncertainty after lost worker
107
+ or process handles instead of treating process closure as confirmed release.
108
+ - Classify signals/exceptions separately from completed steps. A synchronous
109
+ `simctl terminate` probe timed out while attached; the fixture now exits itself
110
+ to test actual process-exit cleanup without blocking the runner on a signal stop.
111
+ - URL-based fixture control encountered a system confirmation. The simulator was
112
+ rebooted to clear this fixture-created prompt; URL control was removed. Atomic
113
+ file delivery avoids the timer observing a partially written command.
114
+
115
+ These failed development observations remain distinct from successful reruns;
116
+ none is represented as evidence that all environments or timings are covered.
117
+
118
+ ## Limits and review
119
+
120
+ Physical iOS devices, other Xcode/Swift/runtime versions, optimized builds,
121
+ installed/published-package operation, real device disconnect, forced host kill,
122
+ long idle/absolute expiry and a late-loaded-image binding journey remain unrun.
123
+ Pause expiry is checked live; idle/absolute expiry logic also has deterministic
124
+ worker/host unit coverage. Pending source creation is checked independently.
125
+
126
+ Swift strings and other aggregate locals expose type/opaque reference summaries;
127
+ standard supported numeric/bool wrappers use static storage. Missing debug values
128
+ remain explicitly unavailable. No suspended-task enumeration or complete logical
129
+ async-stack reconstruction is exposed. Async stepping evidence is the tested
130
+ step-over-await route, not every Swift concurrency construct.
131
+
132
+ Focused review covers target membership/start identity, source resolution, strict
133
+ schema/dispatch parity, bounded IPC/inspection, stop epochs, diagnostic privacy,
134
+ platform guards, expiry and owned teardown. Android contract compatibility remains
135
+ covered by its existing fixture and unit tests; iOS scope is simulator-only.
136
+
137
+
138
+ ## PR #103 preparation-cache follow-up — 2026-11-04
139
+
140
+ [Review comment](https://github.com/clivejefferies/mobile-debug-tools/pull/103#discussion_r4470121366)
141
+ identified duplicated prerequisite subprocesses during attach. Preparation now
142
+ shares its in-flight/successful promise per server process and clears a rejected
143
+ promise, preserving platform checks, readiness validation and worker configuration.
144
+ No tool schema, timeout or inspection behaviour changes.
145
+
146
+ - **PASS** isolated fake-toolchain regression: concurrent calls share preparation,
147
+ failure permits retry, successful configuration is reused, and worker creation
148
+ adds no extra prerequisite probes.
149
+ - **PASS** real Xcode preparation followed by cached reuse within a 100 ms budget;
150
+ no app was attached by that probe.
151
+ - **PASS** focused real iOS MCP runtime/async/cancellation/process-exit/shutdown
152
+ journey on the same simulator/toolchain. Build fingerprint:
153
+ `0200deeb0cff9f04b54ed929258ebd19185c8be86e2badb6cdcbfa21f798fdb1`.
154
+ Source fingerprint remains `295ff0f30f5670530f9cdd7073b958917c1c574ccca9c7b921e295d0d902b699`.
155
+ Log: `/tmp/pr103-cache-ios.log`. Extended pause expiry was not repeated for
156
+ this preparation-only fix; the earlier extended evidence remains above.
157
+ - **PASS** quiet `npm run verify`: lint/quality/architecture, build, all 97 unit
158
+ files and plugin consistency. Log: `/tmp/pr103-cache-verify-final.log`.
159
+ A prior run alongside native testing failed the unchanged conditional-action
160
+ timing assertion. Its isolated retry passed, as did the quiet full verification;
161
+ no assertion or timeout was modified. Original/retry logs:
162
+ `/tmp/pr103-cache-verify.log`, `/tmp/pr103-cache-conditional-retest.log`.
163
+
164
+ The regression child loads its TypeScript toolchain before platform emulation,
165
+ so the host retains its native compiler selection on Linux. This test-only ordering
166
+ adjustment also passed all 97 files in `npm run verify` (log:
167
+ `/tmp/pr103-cache-portable-verify.log`). The preparation fix was published in
168
+ `f00e9fd`, and its review thread was resolved; both hosted unit-test runs passed
169
+ that commit. Later PR-head checks must be assessed separately.
170
+
171
+ The broader device-suite failures above remain separate; this fix does not claim
172
+ that their causes were established or corrected. Simulator shutdown was restored.
173
+
174
+
175
+ ## PR #103 stored-handle guard follow-up — 2026-11-04
176
+
177
+ [Outside-diff review finding](https://github.com/clivejefferies/mobile-debug-tools/pull/103#pullrequestreview-5772655824):
178
+ `tap_element` could execute on its stored iOS handle's device while the central
179
+ guard selected Android when platform hints were omitted. The guard now obtains
180
+ its target through the same handle/platform/device validation used by execution.
181
+ Other tool defaults remain unchanged; explicit conflicting hints still reject
182
+ handle use rather than retargeting input.
183
+
184
+ - **PASS** regression using real handle creation with mocked device/UI/input
185
+ boundaries: omitted/partial hints select the stored iOS device, known pauses
186
+ prevent UI reads/input, a racing pause prevents native dispatch, and unrelated
187
+ platforms/devices remain usable. Mismatched and missing handles retain rejection.
188
+ - **PASS** mutation check: restoring the original Android-default guard route
189
+ makes that regression fail; fixed source was restored before verification.
190
+ - **PASS** `npm run verify`: lint/quality/architecture, build, all 98 unit files,
191
+ and plugin consistency. Log: `/tmp/pr103-handle-verify.log`.
192
+ - **PASS** updated real simulator MCP journey: obtain an iOS handle while running,
193
+ stop at a source breakpoint, then call `tap_element` with only that handle and
194
+ controls, omitting both platform and device ID. Observed `DEBUGGER_PAUSED`,
195
+ `delivery_status: not_delivered`, `dispatch_started: false`, and the correct
196
+ iOS debugger/device metadata. This proves pause rejection, not successful HID
197
+ injection. The existing core/async/cancellation/process-exit/shutdown journey
198
+ also passed on the same Xcode/LLDB/Swift/runtime matrix.
199
+
200
+ Native build fingerprint:
201
+ `28e56d77b9ba4caad778c223306609c3bb284b210b1ea996b927aca47134cf55`.
202
+ Log: `/tmp/pr103-handle-ios.log`. No fixture source change or timeout/assertion
203
+ weakening was needed. Device tests were run after repository verification to keep
204
+ the checks separate. The fixture was removed and simulator shutdown restored.
205
+ The earlier broader-suite limitations remain recorded above.