mobile-debug-mcp 0.34.0 → 0.35.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 (432) hide show
  1. package/.agents/skills/mcp-builder/SKILL.md +44 -64
  2. package/.agents/skills/mcp-builder/references/build-flags.md +44 -43
  3. package/.agents/skills/mcp-builder/references/diagnostics-schema.md +4 -1
  4. package/.agents/skills/mcp-builder/references/toolchain-details.md +49 -62
  5. package/.agents/skills/spec-review/references/spec-review-checklist.md +7 -0
  6. package/.agents/skills/test-authoring/SKILL.md +7 -6
  7. package/.agents/skills/test-authoring/references/repo-test-layout.md +3 -1
  8. package/.agents/skills/test-authoring/references/test-authoring-workflow.md +16 -7
  9. package/.agents/skills/test-authoring/references/test-quality-checklist.md +2 -1
  10. package/.github/copilot-instructions.md +14 -36
  11. package/.github/workflows/ci.yml +4 -4
  12. package/AGENTS.md +12 -3
  13. package/CONTRIBUTING.md +79 -0
  14. package/README.md +156 -129
  15. package/agent-plugin/.claude-plugin/plugin.json +2 -2
  16. package/agent-plugin/.codex-plugin/plugin.json +1 -1
  17. package/agent-plugin/.cursor-plugin/plugin.json +2 -2
  18. package/agent-plugin/.mcp.json +1 -1
  19. package/agent-plugin/README.md +16 -6
  20. package/agent-plugin/mcp.json +1 -1
  21. package/agent-plugin/plugin.json +1 -1
  22. package/agent-plugin/skills/mobile-debug-mcp/SKILL.md +27 -2
  23. package/dist/contracts/execution-controls.js +24 -0
  24. package/dist/contracts/selector.js +8 -0
  25. package/dist/contracts/target.js +15 -0
  26. package/dist/contracts/ui.js +1 -0
  27. package/dist/debugger/android.js +2 -1
  28. package/dist/debugger/diagnostics.js +54 -0
  29. package/dist/debugger/protocol.js +33 -0
  30. package/dist/debugger/sessions.js +104 -62
  31. package/dist/debugger/worker.js +53 -42
  32. package/dist/interact/adjustment/adjustment-context.js +41 -0
  33. package/dist/interact/adjustment/adjustment-gestures.js +55 -0
  34. package/dist/interact/adjustment/adjustment-plan.js +18 -0
  35. package/dist/interact/adjustment/adjustment-resolution.js +127 -0
  36. package/dist/interact/adjustment/adjustment-result.js +19 -0
  37. package/dist/interact/adjustment/adjustment-semantic.js +64 -0
  38. package/dist/interact/adjustment/adjustment-verification.js +35 -0
  39. package/dist/interact/adjustment/adjustment.js +52 -0
  40. package/dist/interact/adjustment/control-geometry.js +87 -0
  41. package/dist/interact/adjustment/control-values.js +136 -0
  42. package/dist/interact/adjustment/slider-labels.js +84 -0
  43. package/dist/interact/assertions/screen-assertion.js +37 -0
  44. package/dist/interact/assertions/state-assertion-context.js +35 -0
  45. package/dist/interact/assertions/state-assertion.js +76 -0
  46. package/dist/interact/assertions/state-comparison.js +141 -0
  47. package/dist/interact/assertions/visibility-assertion.js +34 -0
  48. package/dist/interact/conditional-action.js +12 -7
  49. package/dist/interact/index.js +65 -3090
  50. package/dist/interact/input-service.js +1 -0
  51. package/dist/interact/interaction-trace.js +21 -0
  52. package/dist/interact/model.js +1 -0
  53. package/dist/interact/observation.js +1 -0
  54. package/dist/interact/targeting/candidate-ancestor.js +58 -0
  55. package/dist/interact/targeting/candidate-result.js +23 -0
  56. package/dist/interact/targeting/candidate-scoring.js +50 -0
  57. package/dist/interact/targeting/element-helpers.js +216 -0
  58. package/dist/interact/targeting/find-element.js +65 -0
  59. package/dist/interact/targeting/nearby-control.js +56 -0
  60. package/dist/interact/targeting/resolved-elements.js +21 -0
  61. package/dist/interact/targeting/tap-target.js +17 -0
  62. package/dist/interact/targeting/target-scope.js +104 -0
  63. package/dist/interact/waits/legacy-log-wait.js +38 -0
  64. package/dist/interact/waits/legacy-wait-observations.js +103 -0
  65. package/dist/interact/waits/legacy-wait-state.js +34 -0
  66. package/dist/interact/waits/legacy-wait.js +48 -0
  67. package/dist/interact/waits/screen-wait.js +49 -0
  68. package/dist/interact/waits/ui-change-helpers.js +157 -0
  69. package/dist/interact/waits/ui-change-state.js +18 -0
  70. package/dist/interact/waits/ui-change-wait.js +77 -0
  71. package/dist/interact/waits/ui-wait-condition.js +56 -0
  72. package/dist/interact/waits/ui-wait-state.js +38 -0
  73. package/dist/interact/waits/ui-wait.js +106 -0
  74. package/dist/manage/android.js +55 -51
  75. package/dist/manage/index.js +38 -75
  76. package/dist/manage/ios/build-types.js +1 -0
  77. package/dist/manage/ios/build.js +210 -0
  78. package/dist/manage/ios/project-discovery.js +29 -0
  79. package/dist/manage/ios/scheme.js +18 -0
  80. package/dist/manage/ios.js +42 -256
  81. package/dist/observe/android/context.js +1 -0
  82. package/dist/observe/android/current-screen.js +55 -0
  83. package/dist/observe/android/fingerprint.js +13 -0
  84. package/dist/observe/android/log-stream.js +132 -0
  85. package/dist/observe/android/logs.js +107 -0
  86. package/dist/observe/android/screenshot.js +70 -0
  87. package/dist/observe/android/ui-tree.js +107 -0
  88. package/dist/observe/android.js +16 -520
  89. package/dist/observe/evidence.js +114 -75
  90. package/dist/observe/index.js +16 -263
  91. package/dist/observe/ios/context.js +16 -0
  92. package/dist/observe/ios/fingerprint.js +12 -0
  93. package/dist/observe/ios/log-stream.js +105 -0
  94. package/dist/observe/ios/logs.js +168 -0
  95. package/dist/observe/ios/screenshot.js +22 -0
  96. package/dist/observe/ios/ui-elements.js +241 -0
  97. package/dist/observe/ios/ui-tree.js +137 -0
  98. package/dist/observe/ios.js +17 -715
  99. package/dist/observe/logs/model.js +1 -0
  100. package/dist/{network → observe/network}/index.js +2 -2
  101. package/dist/observe/readiness-service.js +4 -2
  102. package/dist/observe/readiness.js +29 -10
  103. package/dist/observe/screenshot-encoding.js +41 -0
  104. package/dist/observe/snapshot-collection.js +79 -0
  105. package/dist/observe/snapshot-logs.js +30 -0
  106. package/dist/observe/snapshot-metadata.js +43 -31
  107. package/dist/observe/snapshot-semantic.js +115 -0
  108. package/dist/observe/system-trace.js +22 -13
  109. package/dist/runtime/action-results.js +270 -0
  110. package/dist/runtime/clock.js +4 -0
  111. package/dist/server/common.js +1 -256
  112. package/dist/server/definitions/assert.js +162 -0
  113. package/dist/server/definitions/diagnostic.js +118 -0
  114. package/dist/server/definitions/input.js +274 -0
  115. package/dist/server/definitions/manage.js +194 -0
  116. package/dist/server/definitions/observe.js +149 -0
  117. package/dist/server/definitions/target.js +138 -0
  118. package/dist/server/definitions/wait.js +105 -0
  119. package/dist/server/handlers/action-execution.js +163 -0
  120. package/dist/server/handlers/correlation.js +23 -0
  121. package/dist/server/{debugger-handlers.js → handlers/debugger-handlers.js} +22 -12
  122. package/dist/server/handlers/debugger-response.js +9 -0
  123. package/dist/server/handlers/diagnostic.js +69 -0
  124. package/dist/server/handlers/handler-types.js +1 -0
  125. package/dist/server/handlers/input.js +154 -0
  126. package/dist/server/handlers/interact.js +113 -0
  127. package/dist/server/handlers/journey-assertions.js +35 -0
  128. package/dist/server/handlers/journey.js +147 -0
  129. package/dist/server/handlers/manage.js +119 -0
  130. package/dist/server/handlers/observe.js +95 -0
  131. package/dist/server/handlers/payload.js +4 -0
  132. package/dist/server/handlers/tool-handlers.js +160 -0
  133. package/dist/server/schemas/condition-schema.js +2 -0
  134. package/dist/server/{debugger-schema.js → schemas/debugger-schema.js} +11 -6
  135. package/dist/server/{journey-schema.js → schemas/journey-schema.js} +7 -22
  136. package/dist/server/tool-definitions.js +58 -1135
  137. package/dist/server-core.js +2 -2
  138. package/dist/system/android-status.js +101 -0
  139. package/dist/system/android.js +37 -27
  140. package/dist/system/index.js +13 -439
  141. package/dist/system/ios-status.js +132 -0
  142. package/dist/system/ios.js +11 -8
  143. package/dist/system/model.js +1 -0
  144. package/dist/system/probes.js +105 -0
  145. package/dist/system/status-summary.js +43 -0
  146. package/dist/system/unsupported-status.js +52 -0
  147. package/dist/utils/android/commands.js +89 -0
  148. package/dist/utils/android/gradle.js +139 -0
  149. package/dist/utils/android/logs.js +103 -0
  150. package/dist/utils/android/ui-tree.js +233 -0
  151. package/dist/utils/android/utils.js +6 -564
  152. package/dist/utils/cli/idb/idb-helper.js +4 -6
  153. package/dist/utils/cli/idb/install-idb.js +13 -9
  154. package/dist/utils/cli/ios/preflight-ios.js +42 -38
  155. package/dist/utils/ios/utils.js +45 -46
  156. package/dist/utils/java.js +65 -49
  157. package/dist/utils/resolve-device.js +4 -2
  158. package/dist/utils/ui/index.js +26 -26
  159. package/docs/CHANGELOG.md +44 -0
  160. package/docs/README.md +38 -0
  161. package/docs/benchmarks/README.md +18 -0
  162. package/docs/benchmarks/interaction-latency/README.md +14 -0
  163. package/docs/benchmarks/interaction-latency/final.md +4 -1
  164. package/docs/benchmarks/interaction-latency/ios-validation.md +2 -0
  165. package/docs/benchmarks/ui-tree-performance/README.md +24 -16
  166. package/docs/benchmarks/ui-tree-performance/comparison.md +11 -10
  167. package/docs/code-structure.md +118 -0
  168. package/docs/specs/001-state-verification/spec.md +16 -14
  169. package/docs/specs/002-richer-element-identity/spec.md +12 -10
  170. package/docs/specs/003-wait-and-synchronization-reliability/spec.md +12 -10
  171. package/docs/specs/004-action-verification-routing/spec.md +3 -3
  172. package/docs/specs/005-unified-action-execution-and-verification-model/spec.md +2 -0
  173. package/docs/specs/006-runtime-action-instrumentation-and-binding-layer/spec.md +2 -0
  174. package/docs/specs/007-actionability-resolution-and-executable-target-selection/spec.md +3 -1
  175. package/docs/specs/008-adjustable-control-support-and-semantic-value-manipulation/spec.md +3 -4
  176. package/docs/specs/009-semantic-control-modeling-for-custom-and-composite-controls/spec.md +2 -0
  177. package/docs/specs/010-verification-stabilization-and-temporal-convergence/spec.md +2 -2
  178. package/docs/specs/011-recovery-and-replanning-for-failed-or-ambiguous-interaction-flows/spec.md +2 -2
  179. package/docs/specs/011.1-recovery-contract-types-and-runtime-wiring-spec/spec.md +2 -0
  180. package/docs/specs/012-action-trace-and-xecution-observability/spec.md +2 -3
  181. package/docs/specs/013-wait-and-synchronization-reliability/spec.md +19 -19
  182. package/docs/specs/014-actionability-resolution/spec.md +20 -18
  183. package/docs/specs/015-adjustable-control-support/spec.md +17 -15
  184. package/docs/specs/016-environment-tools/spec.md +20 -20
  185. package/docs/specs/018-interaction-latency-and-batched-journeys/spec.md +2 -0
  186. package/docs/specs/019-ui-tree-observation-performance/spec.md +3 -1
  187. package/docs/specs/020-conditional-actions/intent.md +5 -3
  188. package/docs/specs/020-conditional-actions/plan.md +8 -9
  189. package/docs/specs/020-conditional-actions/spec.md +4 -2
  190. package/docs/specs/021-app-readiness-signals/intent.md +4 -2
  191. package/docs/specs/021-app-readiness-signals/plan.md +7 -6
  192. package/docs/specs/021-app-readiness-signals/spec.md +3 -1
  193. package/docs/specs/022-correlated-evidence/intent.md +4 -4
  194. package/docs/specs/022-correlated-evidence/plan.md +10 -11
  195. package/docs/specs/022-correlated-evidence/spec.md +3 -1
  196. package/docs/specs/023-android-system-traces/intent.md +3 -2
  197. package/docs/specs/023-android-system-traces/plan.md +5 -7
  198. package/docs/specs/023-android-system-traces/spec.md +3 -1
  199. package/docs/specs/024-android-heap-dump-capture/intent.md +3 -1
  200. package/docs/specs/025-android-runtime-debugger/intent.md +4 -3
  201. package/docs/specs/025-android-runtime-debugger/plan.md +3 -1
  202. package/docs/specs/025-android-runtime-debugger/spec.md +4 -3
  203. package/docs/specs/026-code-structure-and-quality-gates/health-plan.md +88 -0
  204. package/docs/specs/026-code-structure-and-quality-gates/intent.md +47 -0
  205. package/docs/specs/026-code-structure-and-quality-gates/plan.md +191 -0
  206. package/docs/specs/026-code-structure-and-quality-gates/spec.md +138 -0
  207. package/docs/specs/026-code-structure-and-quality-gates/verification-final.json +200 -0
  208. package/docs/specs/026-code-structure-and-quality-gates/verification-thin-facade.json +154 -0
  209. package/docs/specs/026-code-structure-and-quality-gates/verification.json +136 -0
  210. package/docs/specs/027-debugger-failure-diagnostics/intent.md +43 -0
  211. package/docs/specs/027-debugger-failure-diagnostics/plan.md +86 -0
  212. package/docs/specs/027-debugger-failure-diagnostics/spec.md +133 -0
  213. package/docs/specs/028-compact-debugger-responses/intent.md +41 -0
  214. package/docs/specs/028-compact-debugger-responses/plan.md +112 -0
  215. package/docs/specs/028-compact-debugger-responses/spec.md +108 -0
  216. package/docs/specs/029-kotlin-locals-validation/report.md +119 -0
  217. package/docs/specs/030-android-coroutine-validation/evidence.json +475 -0
  218. package/docs/specs/030-android-coroutine-validation/intent.md +47 -0
  219. package/docs/specs/030-android-coroutine-validation/plan.md +147 -0
  220. package/docs/specs/030-android-coroutine-validation/report.md +240 -0
  221. package/docs/specs/030-android-coroutine-validation/spec.md +107 -0
  222. package/docs/tools/TOOLS.md +31 -18
  223. package/docs/tools/{evidence.md → correlated-evidence.md} +9 -1
  224. package/docs/tools/debugger.md +76 -0
  225. package/docs/tools/interact.md +42 -20
  226. package/docs/tools/manage.md +25 -44
  227. package/docs/tools/observe.md +55 -23
  228. package/docs/tools/system-traces.md +9 -1
  229. package/docs/tools/system.md +12 -5
  230. package/package.json +11 -8
  231. package/scripts/architecture-graph.mjs +69 -0
  232. package/scripts/check-architecture.mjs +47 -0
  233. package/scripts/code-quality-baseline.json +1 -0
  234. package/scripts/code-quality.mjs +161 -0
  235. package/src/contracts/execution-controls.ts +26 -0
  236. package/src/contracts/selector.ts +17 -0
  237. package/src/contracts/target.ts +19 -0
  238. package/src/contracts/ui.ts +94 -0
  239. package/src/debugger/android.ts +2 -1
  240. package/src/debugger/diagnostics.ts +43 -0
  241. package/src/debugger/guard.ts +6 -1
  242. package/{worker → src/debugger/java}/DebuggerWorker.java +9 -3
  243. package/src/debugger/protocol.ts +37 -0
  244. package/src/debugger/sessions.ts +314 -155
  245. package/src/debugger/worker.ts +51 -38
  246. package/src/interact/adjustment/adjustment-context.ts +83 -0
  247. package/src/interact/adjustment/adjustment-gestures.ts +48 -0
  248. package/src/interact/adjustment/adjustment-plan.ts +23 -0
  249. package/src/interact/adjustment/adjustment-resolution.ts +104 -0
  250. package/src/interact/adjustment/adjustment-result.ts +34 -0
  251. package/src/interact/adjustment/adjustment-semantic.ts +53 -0
  252. package/src/interact/adjustment/adjustment-verification.ts +60 -0
  253. package/src/interact/adjustment/adjustment.ts +49 -0
  254. package/src/interact/adjustment/control-geometry.ts +120 -0
  255. package/src/interact/adjustment/control-values.ts +141 -0
  256. package/src/interact/adjustment/slider-labels.ts +84 -0
  257. package/src/interact/assertions/screen-assertion.ts +39 -0
  258. package/src/interact/assertions/state-assertion-context.ts +48 -0
  259. package/src/interact/assertions/state-assertion.ts +64 -0
  260. package/src/interact/assertions/state-comparison.ts +168 -0
  261. package/src/interact/assertions/visibility-assertion.ts +41 -0
  262. package/src/interact/conditional-action.ts +18 -12
  263. package/src/interact/index.ts +76 -3492
  264. package/src/interact/input-service.ts +11 -0
  265. package/src/interact/interaction-trace.ts +36 -0
  266. package/src/interact/model.ts +109 -0
  267. package/src/interact/observation.ts +7 -0
  268. package/src/interact/targeting/candidate-ancestor.ts +49 -0
  269. package/src/interact/targeting/candidate-result.ts +24 -0
  270. package/src/interact/targeting/candidate-scoring.ts +42 -0
  271. package/src/interact/targeting/element-helpers.ts +243 -0
  272. package/src/interact/targeting/find-element.ts +47 -0
  273. package/src/interact/targeting/nearby-control.ts +46 -0
  274. package/src/interact/targeting/resolved-elements.ts +20 -0
  275. package/src/interact/targeting/tap-target.ts +22 -0
  276. package/src/interact/targeting/target-scope.ts +121 -0
  277. package/src/interact/waits/legacy-log-wait.ts +30 -0
  278. package/src/interact/waits/legacy-wait-observations.ts +55 -0
  279. package/src/interact/waits/legacy-wait-state.ts +48 -0
  280. package/src/interact/waits/legacy-wait.ts +34 -0
  281. package/src/interact/waits/screen-wait.ts +37 -0
  282. package/src/interact/waits/ui-change-helpers.ts +184 -0
  283. package/src/interact/waits/ui-change-state.ts +26 -0
  284. package/src/interact/waits/ui-change-wait.ts +59 -0
  285. package/src/interact/waits/ui-wait-condition.ts +52 -0
  286. package/src/interact/waits/ui-wait-state.ts +55 -0
  287. package/src/interact/waits/ui-wait.ts +84 -0
  288. package/src/manage/android.ts +56 -50
  289. package/src/manage/index.ts +63 -93
  290. package/src/manage/ios/build-types.ts +14 -0
  291. package/src/manage/ios/build.ts +230 -0
  292. package/src/manage/ios/project-discovery.ts +26 -0
  293. package/src/manage/ios/scheme.ts +16 -0
  294. package/src/manage/ios.ts +65 -298
  295. package/src/observe/android/context.ts +1 -0
  296. package/src/observe/android/current-screen.ts +63 -0
  297. package/src/observe/android/fingerprint.ts +13 -0
  298. package/src/observe/android/log-stream.ts +127 -0
  299. package/src/observe/android/logs.ts +110 -0
  300. package/src/observe/android/screenshot.ts +79 -0
  301. package/src/observe/android/ui-tree.ts +113 -0
  302. package/src/observe/android.ts +17 -531
  303. package/src/observe/evidence.ts +122 -70
  304. package/src/observe/index.ts +24 -286
  305. package/src/observe/ios/context.ts +22 -0
  306. package/src/observe/ios/fingerprint.ts +12 -0
  307. package/src/observe/ios/log-stream.ts +103 -0
  308. package/src/observe/ios/logs.ts +179 -0
  309. package/src/observe/ios/screenshot.ts +26 -0
  310. package/src/observe/ios/ui-elements.ts +266 -0
  311. package/src/observe/ios/ui-tree.ts +143 -0
  312. package/src/observe/ios.ts +18 -749
  313. package/src/observe/logs/model.ts +11 -0
  314. package/src/{network → observe/network}/index.ts +2 -2
  315. package/src/observe/readiness-service.ts +5 -3
  316. package/src/observe/readiness.ts +39 -18
  317. package/src/observe/screenshot-encoding.ts +32 -0
  318. package/src/observe/snapshot-collection.ts +69 -0
  319. package/src/observe/snapshot-logs.ts +26 -0
  320. package/src/observe/snapshot-metadata.ts +51 -31
  321. package/src/observe/snapshot-semantic.ts +153 -0
  322. package/src/observe/system-trace.ts +24 -15
  323. package/src/runtime/action-results.ts +376 -0
  324. package/src/runtime/clock.ts +9 -0
  325. package/src/server/common.ts +9 -359
  326. package/src/server/definitions/assert.ts +164 -0
  327. package/src/server/definitions/diagnostic.ts +120 -0
  328. package/src/server/definitions/input.ts +276 -0
  329. package/src/server/definitions/manage.ts +196 -0
  330. package/src/server/definitions/observe.ts +151 -0
  331. package/src/server/definitions/target.ts +140 -0
  332. package/src/server/definitions/wait.ts +107 -0
  333. package/src/server/handlers/action-execution.ts +164 -0
  334. package/src/server/handlers/correlation.ts +20 -0
  335. package/src/server/handlers/debugger-handlers.ts +39 -0
  336. package/src/server/handlers/debugger-response.ts +7 -0
  337. package/src/server/handlers/diagnostic.ts +79 -0
  338. package/src/server/handlers/handler-types.ts +7 -0
  339. package/src/server/handlers/input.ts +173 -0
  340. package/src/server/handlers/interact.ts +135 -0
  341. package/src/server/handlers/journey-assertions.ts +39 -0
  342. package/src/server/handlers/journey.ts +132 -0
  343. package/src/server/handlers/manage.ts +141 -0
  344. package/src/server/handlers/observe.ts +116 -0
  345. package/src/server/handlers/payload.ts +36 -0
  346. package/src/server/handlers/tool-handlers.ts +159 -0
  347. package/src/server/schemas/condition-schema.ts +2 -0
  348. package/src/server/{debugger-schema.ts → schemas/debugger-schema.ts} +13 -7
  349. package/src/server/{journey-schema.ts → schemas/journey-schema.ts} +7 -22
  350. package/src/server/{system-trace-schema.ts → schemas/system-trace-schema.ts} +3 -3
  351. package/src/server/tool-definitions.ts +67 -1143
  352. package/src/server-core.ts +2 -2
  353. package/src/server.ts +1 -1
  354. package/src/system/android-status.ts +124 -0
  355. package/src/system/android.ts +33 -21
  356. package/src/system/index.ts +21 -525
  357. package/src/system/ios-status.ts +147 -0
  358. package/src/system/ios.ts +14 -10
  359. package/src/system/model.ts +41 -0
  360. package/src/system/probes.ts +114 -0
  361. package/src/system/status-summary.ts +47 -0
  362. package/src/system/unsupported-status.ts +55 -0
  363. package/src/types.ts +16 -106
  364. package/src/utils/android/commands.ts +81 -0
  365. package/src/utils/android/gradle.ts +132 -0
  366. package/src/utils/android/logs.ts +103 -0
  367. package/src/utils/android/ui-tree.ts +239 -0
  368. package/src/utils/android/utils.ts +16 -556
  369. package/src/utils/cli/idb/check-idb.ts +4 -4
  370. package/src/utils/cli/idb/idb-helper.ts +6 -8
  371. package/src/utils/cli/idb/install-idb.ts +15 -9
  372. package/src/utils/cli/ios/preflight-ios.ts +39 -31
  373. package/src/utils/cli/ios/run-ios-ui-tree-tap.ts +4 -4
  374. package/src/utils/ios/utils.ts +57 -61
  375. package/src/utils/java.ts +62 -43
  376. package/src/utils/resolve-device.ts +9 -6
  377. package/src/utils/ui/index.ts +28 -28
  378. package/test/device/automated/debugger/coroutine-lifecycle.ts +27 -0
  379. package/test/device/automated/debugger/coroutine-support.ts +140 -0
  380. package/test/device/automated/debugger/coroutine.android.test.ts +169 -0
  381. package/test/device/automated/debugger/kotlin.android.test.ts +127 -0
  382. package/test/device/automated/debugger/runtime.android.test.ts +19 -3
  383. package/test/device/automated/interact/interaction.android.test.ts +56 -0
  384. package/test/device/automated/observe/system-trace.smoke.ts +1 -1
  385. package/test/device/manual/interact/modul8_selector_tap.manual.ts +1 -1
  386. package/test/fixtures/contracts/tool-definitions.json +3536 -0
  387. package/test/fixtures/coroutine-app/MainActivity.kt +100 -0
  388. package/test/fixtures/coroutine-app/README.md +48 -0
  389. package/test/fixtures/coroutine-app/build.ts +35 -0
  390. package/test/fixtures/debugger-app/MainActivity.java +21 -0
  391. package/test/fixtures/debugger-app/MainActivity.kt +32 -0
  392. package/test/fixtures/debugger-app/README.md +52 -0
  393. package/test/fixtures/debugger-app/build.ts +25 -15
  394. package/test/fixtures/latency-journey-app/README.md +2 -0
  395. package/test/fixtures/readiness-app/README.md +2 -0
  396. package/test/unit/debugger/coroutine-lifecycle.test.ts +43 -0
  397. package/test/unit/debugger/diagnostic-sessions.test.ts +67 -0
  398. package/test/unit/debugger/diagnostics.test.ts +80 -0
  399. package/test/unit/debugger/guards.test.ts +4 -0
  400. package/test/unit/debugger/preparation.test.ts +32 -0
  401. package/test/unit/debugger/protocol.test.ts +15 -0
  402. package/test/unit/debugger/sessions.test.ts +1 -1
  403. package/test/unit/interact/adjustment_service.test.ts +42 -0
  404. package/test/unit/interact/adjustment_verification.test.ts +35 -0
  405. package/test/unit/interact/clock_dependencies.test.ts +63 -0
  406. package/test/unit/interact/element_helpers.test.ts +19 -0
  407. package/test/unit/interact/legacy_wait_service.test.ts +17 -0
  408. package/test/unit/interact/state_comparison.test.ts +20 -0
  409. package/test/unit/interact/target_scope.test.ts +35 -0
  410. package/test/unit/network/get_network_activity.test.ts +1 -1
  411. package/test/unit/observe/screenshot-encoding.test.ts +30 -0
  412. package/test/unit/observe/snapshot-logs.test.ts +14 -0
  413. package/test/unit/quality/architecture.test.ts +60 -0
  414. package/test/unit/quality/code-quality.test.ts +58 -0
  415. package/test/unit/quality/interaction_boundaries.test.ts +24 -0
  416. package/test/unit/server/conditional_actions.test.ts +1 -1
  417. package/test/unit/server/conditional_schema.test.ts +2 -2
  418. package/test/unit/server/debugger-response.test.ts +63 -0
  419. package/test/unit/server/tool_definitions_parity.test.ts +8 -0
  420. package/dist/server/tool-handlers.js +0 -1000
  421. package/docs/ROADMAP.md +0 -646
  422. package/docs/benchmarks/ui-tree-performance/bridge-probe.json +0 -29
  423. package/docs/benchmarks/ui-tree-performance/initial-baseline.json +0 -59560
  424. package/docs/specs/baseline-spec-v0.md +0 -312
  425. package/docs/specs/mcp-tooling-spec-v1.md +0 -446
  426. package/src/server/debugger-handlers.ts +0 -29
  427. package/src/server/tool-handlers.ts +0 -1008
  428. /package/dist/{server/condition-schema.js → contracts/condition.js} +0 -0
  429. /package/dist/server/{readiness-schema.js → schemas/readiness-schema.js} +0 -0
  430. /package/dist/server/{system-trace-schema.js → schemas/system-trace-schema.js} +0 -0
  431. /package/src/{server/condition-schema.ts → contracts/condition.ts} +0 -0
  432. /package/src/server/{readiness-schema.ts → schemas/readiness-schema.ts} +0 -0
@@ -22,11 +22,10 @@ async function findFirst(root, patterns, maxDepth = 4) {
22
22
  console.error('DEBUG findFirst: entries', ents.map(e => e.name));
23
23
  for (const e of ents) {
24
24
  const full = path.join(dir, e.name);
25
- for (const p of patterns) {
26
- if (e.name.endsWith(p)) {
27
- console.error('DEBUG findFirst: matched', full);
28
- return full;
29
- }
25
+ const matched = patterns.some(pattern => e.name.endsWith(pattern));
26
+ if (matched) {
27
+ console.error('DEBUG findFirst: matched', full);
28
+ return full;
30
29
  }
31
30
  if (e.isDirectory() && depth < maxDepth)
32
31
  queue.push({ dir: full, depth: depth + 1 });
@@ -52,26 +51,7 @@ function startCompanionIfNeeded(companionPath, udid) {
52
51
  }
53
52
  }
54
53
  async function main() {
55
- const args = process.argv.slice(2);
56
- let projectArg;
57
- let udid;
58
- let startCompanion = false;
59
- let kmpBuild = null;
60
- for (let i = 0; i < args.length; i++) {
61
- const a = args[i];
62
- if (a === '--project' && args[i + 1]) {
63
- projectArg = args[i + 1];
64
- i++;
65
- }
66
- else if (a === '--udid' && args[i + 1]) {
67
- udid = args[i + 1];
68
- i++;
69
- }
70
- else if (a === '--start-companion')
71
- startCompanion = true;
72
- else if (!projectArg)
73
- projectArg = a;
74
- }
54
+ const { projectArg, udid, startCompanion, kmpBuild } = argumentsForPreflight(process.argv.slice(2));
75
55
  const cwd = process.cwd();
76
56
  const projectRoot = projectArg ? path.resolve(projectArg) : cwd;
77
57
  // If user passed a direct .xcodeproj or .xcworkspace path, accept it as the projectFile
@@ -108,15 +88,8 @@ async function main() {
108
88
  // 4) idb_companion
109
89
  const companionPath = commandWhich('idb_companion');
110
90
  const companionAvailable = !!companionPath;
111
- const suggestions = [];
112
- if (!projectFile)
113
- suggestions.push('Provide correct project path or ensure .xcodeproj/.xcworkspace exists in project dir');
114
- if (!kmpFramework)
115
- suggestions.push('Run KMP Gradle task to produce Shared.framework before xcodebuild (e.g., :shared:embedAndSignAppleFrameworkForXcode)');
116
- if (!idbAvailable)
117
- suggestions.push('Ensure idb is in PATH or set MCP_IDB_PATH / IDB_PATH');
118
- if (!companionAvailable)
119
- suggestions.push('Install idb_companion and ensure it is in PATH');
91
+ const suggestions = preflightSuggestions(projectFile, kmpFramework, idbAvailable, companionAvailable);
92
+ const companionInfo = { cmd: companionPath, installed: companionAvailable };
120
93
  const result = {
121
94
  ok: !!projectFile && !!idbAvailable,
122
95
  project: {
@@ -133,10 +106,7 @@ async function main() {
133
106
  cmd: idbPath,
134
107
  installed: idbAvailable
135
108
  },
136
- idb_companion: {
137
- cmd: companionPath,
138
- installed: companionAvailable
139
- },
109
+ idb_companion: companionInfo,
140
110
  suggestions
141
111
  };
142
112
  if (startCompanion && udid) {
@@ -153,3 +123,37 @@ main().catch(e => {
153
123
  console.log(JSON.stringify({ ok: false, error: e instanceof Error ? e.message : String(e) }, null, 2));
154
124
  process.exit(2);
155
125
  });
126
+ function argumentsForPreflight(args) {
127
+ let projectArg;
128
+ let udid;
129
+ let startCompanion = false;
130
+ const kmpBuild = null;
131
+ for (let i = 0; i < args.length; i++) {
132
+ const a = args[i];
133
+ if (a === '--project' && args[i + 1]) {
134
+ projectArg = args[i + 1];
135
+ i++;
136
+ }
137
+ else if (a === '--udid' && args[i + 1]) {
138
+ udid = args[i + 1];
139
+ i++;
140
+ }
141
+ else if (a === '--start-companion')
142
+ startCompanion = true;
143
+ else if (!projectArg)
144
+ projectArg = a;
145
+ }
146
+ return { projectArg, udid, startCompanion, kmpBuild };
147
+ }
148
+ function preflightSuggestions(projectFile, kmpFramework, idbAvailable, companionAvailable) {
149
+ const suggestions = [];
150
+ if (!projectFile)
151
+ suggestions.push('Provide correct project path or ensure .xcodeproj/.xcworkspace exists in project dir');
152
+ if (!kmpFramework)
153
+ suggestions.push('Run KMP Gradle task to produce Shared.framework before xcodebuild (e.g., :shared:embedAndSignAppleFrameworkForXcode)');
154
+ if (!idbAvailable)
155
+ suggestions.push('Ensure idb is in PATH or set MCP_IDB_PATH / IDB_PATH');
156
+ if (!companionAvailable)
157
+ suggestions.push('Install idb_companion and ensure it is in PATH');
158
+ return suggestions;
159
+ }
@@ -19,16 +19,14 @@ export function getConfiguredIdbPath() {
19
19
  if (!p)
20
20
  continue;
21
21
  try {
22
- if (fs.existsSync(p)) {
23
- const raw = fs.readFileSync(p, 'utf8');
24
- const json = JSON.parse(raw);
25
- if (json) {
26
- if (json.idbPath)
27
- return json.idbPath;
28
- if (json.IDB_PATH)
29
- return json.IDB_PATH;
30
- }
31
- }
22
+ if (!fs.existsSync(p))
23
+ continue;
24
+ const raw = fs.readFileSync(p, 'utf8');
25
+ const json = JSON.parse(raw);
26
+ if (json?.idbPath)
27
+ return json.idbPath;
28
+ if (json?.IDB_PATH)
29
+ return json.IDB_PATH;
32
30
  }
33
31
  catch { }
34
32
  }
@@ -214,18 +212,18 @@ export async function getIOSDeviceMetadata(deviceId = "booted") {
214
212
  const devicesMap = data.devices || {};
215
213
  for (const runtime in devicesMap) {
216
214
  const devices = devicesMap[runtime];
217
- if (Array.isArray(devices)) {
218
- for (const device of devices) {
219
- if (deviceId === "booted" || device.udid === deviceId) {
220
- resolve({
221
- platform: "ios",
222
- id: device.udid,
223
- osVersion: parseRuntimeName(runtime),
224
- model: device.name,
225
- simulator: true,
226
- });
227
- return;
228
- }
215
+ if (!Array.isArray(devices))
216
+ continue;
217
+ for (const device of devices) {
218
+ if (deviceId === "booted" || device.udid === deviceId) {
219
+ resolve({
220
+ platform: "ios",
221
+ id: device.udid,
222
+ osVersion: parseRuntimeName(runtime),
223
+ model: device.name,
224
+ simulator: true,
225
+ });
226
+ return;
229
227
  }
230
228
  }
231
229
  }
@@ -257,36 +255,37 @@ export async function listIOSDevices(appId) {
257
255
  const bmap = bdata.devices || {};
258
256
  for (const rt in bmap) {
259
257
  const devs = bmap[rt];
260
- if (Array.isArray(devs))
261
- for (const d of devs)
262
- bootedSet.add(d.udid);
258
+ if (!Array.isArray(devs))
259
+ continue;
260
+ for (const d of devs)
261
+ bootedSet.add(d.udid);
263
262
  }
264
263
  }
265
264
  catch { }
266
265
  }
267
266
  for (const runtime in devicesMap) {
268
267
  const devices = devicesMap[runtime];
269
- if (Array.isArray(devices)) {
270
- for (const device of devices) {
271
- const info = {
272
- platform: 'ios',
273
- id: device.udid,
274
- osVersion: parseRuntimeName(runtime),
275
- model: device.name,
276
- simulator: true,
277
- booted: bootedSet.has(device.udid)
278
- };
279
- if (appId) {
280
- // check if installed
281
- const p = execCommand(['simctl', 'get_app_container', device.udid, appId, 'data'], device.udid)
282
- .then(() => { info.appInstalled = true; })
283
- .catch(() => { info.appInstalled = false; })
284
- .then(() => { out.push(info); });
285
- checks.push(p);
286
- }
287
- else {
288
- out.push(info);
289
- }
268
+ if (!Array.isArray(devices))
269
+ continue;
270
+ for (const device of devices) {
271
+ const info = {
272
+ platform: 'ios',
273
+ id: device.udid,
274
+ osVersion: parseRuntimeName(runtime),
275
+ model: device.name,
276
+ simulator: true,
277
+ booted: bootedSet.has(device.udid)
278
+ };
279
+ if (appId) {
280
+ // check if installed
281
+ const p = execCommand(['simctl', 'get_app_container', device.udid, appId, 'data'], device.udid)
282
+ .then(() => { info.appInstalled = true; })
283
+ .catch(() => { info.appInstalled = false; })
284
+ .then(() => { out.push(info); });
285
+ checks.push(p);
286
+ }
287
+ else {
288
+ out.push(info);
290
289
  }
291
290
  }
292
291
  }
@@ -39,27 +39,9 @@ export async function detectJavaHome(options = {}) {
39
39
  }
40
40
  debug('[java.detect] ANDROID_STUDIO_JDK present but java -version did not match expected versions');
41
41
  }
42
- // 2) Android Studio JBR candidates (prefer these over JAVA_HOME)
43
- const jbrCandidates = [
44
- '/Applications/Android Studio.app/Contents/jbr',
45
- '/Applications/Android Studio.app/Contents/jbr/Contents/Home',
46
- '/Applications/Android Studio Preview.app/Contents/jbr',
47
- '/Applications/Android Studio Preview.app/Contents/jbr/Contents/Home',
48
- '/Applications/Android Studio Preview 2022.3.app/Contents/jbr',
49
- '/Applications/Android Studio Preview 2022.3.app/Contents/jbr/Contents/Home',
50
- '/Applications/Android Studio Preview 2023.1.app/Contents/jbr',
51
- '/Applications/Android Studio Preview 2023.1.app/Contents/jbr/Contents/Home'
52
- ];
53
- for (const p of jbrCandidates) {
54
- const javaBin = path.join(p, 'bin', 'java');
55
- if (existsSync(javaBin)) {
56
- const v = javaVersionOf(javaBin);
57
- if (isJavaVersionAcceptable(v)) {
58
- debug('[java.detect] Found Android Studio JBR at:', p);
59
- return p;
60
- }
61
- }
62
- }
42
+ const jbr = findStudioJava(debug);
43
+ if (jbr)
44
+ return jbr;
63
45
  // 3) If JAVA_HOME set, validate it (accept 17 or 21)
64
46
  if (process.env.JAVA_HOME) {
65
47
  try {
@@ -96,40 +78,74 @@ export async function detectJavaHome(options = {}) {
96
78
  catch (e) {
97
79
  debug('[java.detect] /usr/libexec/java_home -v 21 failed: ' + String(e));
98
80
  }
99
- // 6) macOS common JDK locations
100
- try {
101
- const homes = execSync('ls -1 /Library/Java/JavaVirtualMachines || true', { stdio: ['ignore', 'pipe', 'inherit'] }).toString().split(/\r?\n/).filter(Boolean);
102
- for (const h of homes) {
103
- if (h.toLowerCase().includes('17') || h.toLowerCase().includes('jdk-17') || h.toLowerCase().includes('21') || h.toLowerCase().includes('jdk-21')) {
104
- const candidate = `/Library/Java/JavaVirtualMachines/${h}/Contents/Home`;
105
- return candidate;
106
- }
81
+ const commonHome = findMacJavaHome(debug);
82
+ if (commonHome)
83
+ return commonHome;
84
+ return findLinuxJavaHome(debug);
85
+ }
86
+ catch (e) {
87
+ debug('[java.detect] error detecting java home:', e instanceof Error ? e.message : String(e));
88
+ }
89
+ return undefined;
90
+ }
91
+ function findStudioJava(debug) {
92
+ // 2) Android Studio JBR candidates (prefer these over JAVA_HOME)
93
+ const jbrCandidates = [
94
+ '/Applications/Android Studio.app/Contents/jbr',
95
+ '/Applications/Android Studio.app/Contents/jbr/Contents/Home',
96
+ '/Applications/Android Studio Preview.app/Contents/jbr',
97
+ '/Applications/Android Studio Preview.app/Contents/jbr/Contents/Home',
98
+ '/Applications/Android Studio Preview 2022.3.app/Contents/jbr',
99
+ '/Applications/Android Studio Preview 2022.3.app/Contents/jbr/Contents/Home',
100
+ '/Applications/Android Studio Preview 2023.1.app/Contents/jbr',
101
+ '/Applications/Android Studio Preview 2023.1.app/Contents/jbr/Contents/Home'
102
+ ];
103
+ for (const p of jbrCandidates) {
104
+ const javaBin = path.join(p, 'bin', 'java');
105
+ if (existsSync(javaBin)) {
106
+ const v = javaVersionOf(javaBin);
107
+ if (isJavaVersionAcceptable(v)) {
108
+ debug('[java.detect] Found Android Studio JBR at:', p);
109
+ return p;
107
110
  }
108
111
  }
109
- catch (e) {
110
- debug('[java.detect] listing /Library/Java/JavaVirtualMachines failed: ' + String(e));
111
- }
112
- // 7) Linux locations
113
- const linuxCandidates = [
114
- '/usr/lib/jvm/java-17-openjdk-amd64',
115
- '/usr/lib/jvm/java-17-openjdk',
116
- '/usr/lib/jvm/zulu17',
117
- '/usr/lib/jvm/temurin-17-jdk',
118
- '/usr/lib/jvm/temurin-21-jdk',
119
- '/usr/lib/jvm/java-21-openjdk-amd64'
120
- ];
121
- for (const p of linuxCandidates) {
122
- try {
123
- if (existsSync(p))
124
- return p;
125
- }
126
- catch (e) {
127
- debug(`[java.detect] checking linux candidate ${p} failed: ${String(e)}`);
112
+ }
113
+ return undefined;
114
+ }
115
+ function findMacJavaHome(debug) {
116
+ // 6) macOS common JDK locations
117
+ try {
118
+ const homes = execSync('ls -1 /Library/Java/JavaVirtualMachines || true', { stdio: ['ignore', 'pipe', 'inherit'] }).toString().split(/\r?\n/).filter(Boolean);
119
+ for (const h of homes) {
120
+ if (h.toLowerCase().includes('17') || h.toLowerCase().includes('jdk-17') || h.toLowerCase().includes('21') || h.toLowerCase().includes('jdk-21')) {
121
+ const candidate = `/Library/Java/JavaVirtualMachines/${h}/Contents/Home`;
122
+ return candidate;
128
123
  }
129
124
  }
130
125
  }
131
126
  catch (e) {
132
- debug('[java.detect] error detecting java home:', e instanceof Error ? e.message : String(e));
127
+ debug('[java.detect] listing /Library/Java/JavaVirtualMachines failed: ' + String(e));
128
+ }
129
+ return undefined;
130
+ }
131
+ function findLinuxJavaHome(debug) {
132
+ // 7) Linux locations
133
+ const linuxCandidates = [
134
+ '/usr/lib/jvm/java-17-openjdk-amd64',
135
+ '/usr/lib/jvm/java-17-openjdk',
136
+ '/usr/lib/jvm/zulu17',
137
+ '/usr/lib/jvm/temurin-17-jdk',
138
+ '/usr/lib/jvm/temurin-21-jdk',
139
+ '/usr/lib/jvm/java-21-openjdk-amd64'
140
+ ];
141
+ for (const p of linuxCandidates) {
142
+ try {
143
+ if (existsSync(p))
144
+ return p;
145
+ }
146
+ catch (e) {
147
+ debug(`[java.detect] checking linux candidate ${p} failed: ${String(e)}`);
148
+ }
133
149
  }
134
150
  return undefined;
135
151
  }
@@ -66,6 +66,9 @@ async function resolveDevice(opts) {
66
66
  throw new Error(`Device '${deviceId}' not found for platform ${platform}`);
67
67
  return found;
68
68
  }
69
+ return selectDevice(devices, platform, appId, prefer);
70
+ }
71
+ function selectDevice(devices, platform, appId, prefer) {
69
72
  let candidates = devices.slice();
70
73
  if (prefer === "physical")
71
74
  candidates = candidates.filter(d => !d.simulator);
@@ -99,8 +102,7 @@ async function resolveDevice(opts) {
99
102
  return candidates[0];
100
103
  }
101
104
  const list = candidates.map(d => ({ id: d.id, platform: d.platform, osVersion: d.osVersion, model: d.model, simulator: d.simulator, appInstalled: d.appInstalled }));
102
- const err = new Error(`Multiple matching devices found: ${JSON.stringify(list, null, 2)}`);
103
- err.devices = list;
105
+ const err = Object.assign(new Error(`Multiple matching devices found: ${JSON.stringify(list, null, 2)}`), { devices: list });
104
106
  throw err;
105
107
  }
106
108
  throw new Error(`No devices found for platform ${platform}`);
@@ -73,36 +73,11 @@ export function computeScreenFingerprint(tree, current, platform, limit = 50) {
73
73
  }
74
74
  export async function scrollToElementShared(opts) {
75
75
  const { selector, direction = 'down', maxScrolls = 10, scrollAmount = 0.7, deviceId, fetchTree, swipe, stabilizationDelayMs = 350 } = opts;
76
- const matchElement = (el) => {
77
- if (!el)
78
- return false;
79
- if (selector.text !== undefined && selector.text !== el.text)
80
- return false;
81
- if (selector.resourceId !== undefined && selector.resourceId !== el.resourceId)
82
- return false;
83
- if (selector.contentDesc !== undefined && selector.contentDesc !== el.contentDescription)
84
- return false;
85
- if (selector.className !== undefined && selector.className !== el.type)
86
- return false;
87
- return true;
88
- };
89
- const isVisible = (el, resolution) => {
90
- if (!el)
91
- return false;
92
- if (el.visible === false)
93
- return false;
94
- if (!el.bounds || !resolution || !resolution.width || !resolution.height)
95
- return (el.visible === undefined ? true : !!el.visible);
96
- const [left, top, right, bottom] = el.bounds;
97
- const withinY = bottom > 0 && top < resolution.height;
98
- const withinX = right > 0 && left < resolution.width;
99
- return withinX && withinY;
100
- };
101
76
  const findVisibleMatch = (elements, resolution) => {
102
77
  if (!Array.isArray(elements))
103
78
  return null;
104
79
  for (const e of elements) {
105
- if (matchElement(e) && isVisible(e, resolution))
80
+ if (matchElement(selector, e) && isVisible(e, resolution))
106
81
  return e;
107
82
  }
108
83
  return null;
@@ -169,3 +144,28 @@ export async function scrollToElementShared(opts) {
169
144
  }
170
145
  return { success: false, reason: 'Element not found after scrolling', scrollsPerformed: scrollsPerformed };
171
146
  }
147
+ function matchElement(selector, el) {
148
+ if (!el)
149
+ return false;
150
+ if (selector.text !== undefined && selector.text !== el.text)
151
+ return false;
152
+ if (selector.resourceId !== undefined && selector.resourceId !== el.resourceId)
153
+ return false;
154
+ if (selector.contentDesc !== undefined && selector.contentDesc !== el.contentDescription)
155
+ return false;
156
+ if (selector.className !== undefined && selector.className !== el.type)
157
+ return false;
158
+ return true;
159
+ }
160
+ function isVisible(el, resolution) {
161
+ if (!el)
162
+ return false;
163
+ if (el.visible === false)
164
+ return false;
165
+ if (!el.bounds || !resolution || !resolution.width || !resolution.height)
166
+ return (el.visible === undefined ? true : !!el.visible);
167
+ const [left, top, right, bottom] = el.bounds;
168
+ const withinY = bottom > 0 && top < resolution.height;
169
+ const withinX = right > 0 && left < resolution.width;
170
+ return withinX && withinY;
171
+ }
package/docs/CHANGELOG.md CHANGED
@@ -1,9 +1,53 @@
1
1
  # Changelog
2
2
 
3
+ [Documentation](README.md)
4
+
5
+ Entries describe their release at the time it was recorded. Historical source
6
+ paths and commands may have moved; use the [contribution guide](../CONTRIBUTING.md)
7
+ and [tool reference](tools/TOOLS.md) for the current checkout.
8
+
3
9
  All notable changes to the **Mobile Debug MCP** project will be documented in this file.
4
10
 
5
11
  ## Unreleased
6
12
 
13
+ ## [0.35.0]
14
+
15
+ - Updated the agent plugin to `0.0.4`, pinned to MCP `0.35.0`.
16
+
17
+ - Added an opt-in isolated Android coroutine debugger assessment fixture for
18
+ suspension, dispatcher changes, nested work, stepping and cancellation, with
19
+ explicit local dependencies. This does not add coroutine reconstruction.
20
+ - Added an opt-in isolated Kotlin debugger validation journey for named locals
21
+ before/after assignment, compiler scope tables, stale references and app recovery.
22
+ This adds evidence and regression coverage without changing debugger behaviour.
23
+ - Added opt-in debugger `responseMode: "compact"` to omit repeated target metadata
24
+ from routine commands while retaining diagnostics, execution state and cleanup.
25
+ Existing full responses remain the default; discovery and state stay complete.
26
+ - Android debugger failures now include bounded, sanitized stage/reason diagnostics
27
+ and static recovery guidance while preserving error codes. Capability probes
28
+ report ordered prerequisite diagnostics; terminal summaries retain failure evidence.
29
+ Raw stderr, exception messages and app locals are excluded from diagnostics.
30
+
31
+ - **Runtime requirement:** Node.js 22 or newer is now required. Updated Sharp,
32
+ Zod and transitive dependencies to clear the dependency audit findings; CI
33
+ configuration now uses Node 22. Public tool definitions remain unchanged.
34
+ - Split observation, snapshot, iOS build, Android utility and system diagnostic
35
+ responsibilities into typed services. Removed all 136 legacy quality exceptions;
36
+ production source meets the default size, complexity, nesting and explicit-any
37
+ limits. Added screenshot encoding and snapshot log normalization regressions.
38
+
39
+ - Split server handlers by capability, share target/execution-control contracts, and inject clocks into interaction polling services while preserving tool contracts. Added deterministic timing tests and an Android labelled-slider convergence journey.
40
+
41
+ - Added ArchUnitTS architecture checks to lint and CI for shared contracts, server boundaries, pure interaction calculations and runtime dependency cycles. Negative controls cover NodeNext resolution, aliases, dynamic imports and re-exports.
42
+
43
+ - Group interaction services by adjustment, targeting, waits and assertions; separate server schemas and handlers, and place log-derived network observations under `observe/network`. Tool contracts and behaviour are unchanged.
44
+
45
+ - Reduced `ToolsInteract` to a typed composition facade within the enforced class budget. Extracted adjustment, candidate resolution, synchronization and assertion services without new legacy exceptions, and added an isolated Android interaction journey plus a permanent default-budget regression check.
46
+
47
+ - Added code-quality gates to lint and CI for source/class/function size, complexity, nesting, explicit `any`, and interaction/runtime import boundaries. Legacy exceptions have per-symbol ceilings that cannot grow unnoticed.
48
+ - Extracted typed UI/control helpers, bounded handle storage, action-result construction and capability-specific tool definitions; clarified and typed debugger session operations and worker protocol messages while retaining public tool contracts.
49
+ - Fixed the debugger device check to fingerprint Java sources in `src/debugger/java/` after the worker relocation.
50
+
7
51
  ## [0.34.0]
8
52
  - Added optional Android JDI runtime debugging: explicit device/process attach, source breakpoints/events, bounded stacks and shallow locals, stepping/resume, stale-reference rejection, pause-aware UI guards/readiness, expiry and owned detach/cleanup. Requires a host JDK 17+ and a running debuggable app; evaluation, mutation, native/coroutine and iOS debugging remain unsupported.
9
53
  - Added optional bounded Android Perfetto capture with capability/start/status/stop/cancel tools, explicit journey trace linkage, local artifacts, process-ownership checks and retryable cleanup. iOS tracing and automatic trace analysis remain unsupported.
package/docs/README.md ADDED
@@ -0,0 +1,38 @@
1
+ # Documentation
2
+
3
+ Mobile Debug MCP provides tools for building, controlling, and inspecting Android
4
+ and iOS apps. Start with the [project README](../README.md) for requirements,
5
+ installation, and client configuration.
6
+
7
+ ## Choose a starting point
8
+
9
+ - **New to the server?** See the [project overview and installation options](../README.md#start-here).
10
+ - **Looking up a tool?** Use the [tool reference](tools/TOOLS.md) for inputs,
11
+ responses, examples, and shared interaction principles.
12
+ - **Troubleshooting setup?** Check [environment diagnostics](tools/system.md) and
13
+ the [tool path settings](../README.md#environment-setup).
14
+ - **Investigating an app failure?** Start with [observations](tools/observe.md)
15
+ and [evidence correlation](tools/correlated-evidence.md). For deeper Android
16
+ investigation, use [system traces](tools/system-traces.md) or the
17
+ [runtime debugger](tools/debugger.md).
18
+ - **Installing a client plugin?** See [client installation](../README.md#agent-plugin)
19
+ and the [plugin guide](../agent-plugin/README.md) for packaging and versioning.
20
+
21
+ ## Contributing
22
+
23
+ - [Contribution guide](../CONTRIBUTING.md): local setup, validation, and documentation conventions.
24
+ - [Code structure and quality checks](code-structure.md): module ownership, enforced limits, and existing debt.
25
+ - [Development process](specs/process.md): maintenance and feature workflows.
26
+ - [Agent entrypoint](../AGENTS.md) and [repository skills](../.agents/skills/README.md).
27
+
28
+ ## Design and evidence
29
+
30
+ - [Design records](specs/): feature intent, specifications, and dated verification
31
+ records, grouped by feature.
32
+ - [Changelog](CHANGELOG.md): release history.
33
+ - [Benchmark index](benchmarks/README.md): reproducible performance checks and recorded limits.
34
+
35
+ The tool reference describes the current checkout. Specifications record design
36
+ intent and may contain earlier contracts; approval alone does not establish that
37
+ a feature shipped. Verification records describe the named build and environment,
38
+ not every supported platform or the currently published npm package.
@@ -0,0 +1,18 @@
1
+ # Benchmarks
2
+
3
+ [Documentation](../README.md)
4
+
5
+ Use these guides to run a benchmark or inspect its recorded results. Each
6
+ benchmark has one directory containing its instructions, report, and supporting
7
+ data. Generated filenames are retained so the harness can update them directly.
8
+
9
+ These reports describe particular builds and devices. Passing a smoke check does
10
+ not establish a performance improvement, and Android timings do not establish
11
+ iOS latency.
12
+
13
+ | Benchmark | Protocol | Recorded results | Design |
14
+ | --- | --- | --- | --- |
15
+ | Interaction latency | [Run the benchmark](interaction-latency/README.md) | [Android measurements](interaction-latency/final.md), [iOS interaction validation](interaction-latency/ios-validation.md) | [018](../specs/018-interaction-latency-and-batched-journeys/spec.md) |
16
+ | UI-tree observation | [Run the paired benchmark](ui-tree-performance/README.md) | [Comparison and limitations](ui-tree-performance/comparison.md) | [019](../specs/019-ui-tree-observation-performance/spec.md) |
17
+
18
+ Fixture instructions: [latency journey app](../../test/fixtures/latency-journey-app/README.md).
@@ -1,5 +1,7 @@
1
1
  # Interaction latency benchmark
2
2
 
3
+ [Benchmark index](../README.md) · [Documentation](../../README.md)
4
+
3
5
  Run after `npm run verify`:
4
6
 
5
7
  ```sh
@@ -24,3 +26,15 @@ See [iOS simulator validation](ios-validation.md) for the interaction checks.
24
26
  The process exits unsuccessfully on >10% full p95 regression or <30% light p50
25
27
  improvement. A failed run is reported and excluded from percentiles as the spec
26
28
  requires; inspect its selector and tool or step before accepting the result.
29
+
30
+ ## Recorded results
31
+
32
+ - [Android measurements](final.md): latency summaries and acceptance gates.
33
+ - [Raw Android report](final.json): requests, timing components, and per-run outcomes.
34
+ - [iOS interaction validation](ios-validation.md): correctness checks, separate
35
+ from the Android latency measurements.
36
+
37
+ The harness overwrites `final.md` and `final.json` when run. These checked-in
38
+ results describe the recorded build and environment; they do not establish the
39
+ performance of the current checkout. Review generated reports and preserve any
40
+ unresolved limitations when recording a new run.
@@ -1,5 +1,7 @@
1
1
  # Interaction latency benchmark
2
2
 
3
+ [Benchmark index](../README.md) · [Documentation](../../README.md)
4
+
3
5
  Commit: d3e6ae720db1ad1da294795790689df5a80b56b0 (working tree candidate). Fixture: 1.0, SHA-256 98244deeeba0a21da7d99a3e4b43c97806d6f8a8787ad7fe38249e5d311a6fb6.
4
6
 
5
7
  Environment: Pixel_9_Pro, Android 16, API 36. Three warm-ups and ten measured runs per mode. Failed runs excluded.
@@ -14,4 +16,5 @@ First failure by mode: baseline: none; full: none; light: none.
14
16
 
15
17
  Full p95 gate: true. Light p50 gate: true.
16
18
 
17
- See final.json for requests, timing components, and failure selectors.
19
+ See the [raw report](final.json) for requests, timing components, and failure selectors.
20
+ See the [benchmark instructions](README.md) to run a new measurement.
@@ -1,5 +1,7 @@
1
1
  # Spec 018 iOS device validation
2
2
 
3
+ [Benchmark index](../README.md) · [Documentation](../../README.md)
4
+
3
5
  Validated on 27 September 2026 with the booted iPhone Air simulator (iOS 26.4.1).
4
6
 
5
7
  - `npm run test:device` passed all six Android and iOS screenshot, log, and UI-tree smoke checks.