mobster-cli 0.4.3__py3-none-any.whl

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 (1009) hide show
  1. mobile_agent/__init__.py +4 -0
  2. mobile_agent/__main__.py +598 -0
  3. mobile_agent/accounts/__init__.py +1 -0
  4. mobile_agent/accounts/context.py +80 -0
  5. mobile_agent/accounts/mcp.py +55 -0
  6. mobile_agent/accounts/pacing.py +318 -0
  7. mobile_agent/accounts/register.py +78 -0
  8. mobile_agent/accounts/routes.py +212 -0
  9. mobile_agent/accounts/routing.py +69 -0
  10. mobile_agent/accounts/screen.py +273 -0
  11. mobile_agent/accounts/stats.py +54 -0
  12. mobile_agent/accounts/store.py +394 -0
  13. mobile_agent/agent_hooks.py +123 -0
  14. mobile_agent/ai_plans/__init__.py +7 -0
  15. mobile_agent/ai_plans/agents.py +96 -0
  16. mobile_agent/ai_plans/claude_code.py +208 -0
  17. mobile_agent/ai_plans/cli.py +400 -0
  18. mobile_agent/ai_plans/codex.py +258 -0
  19. mobile_agent/ai_plans/compat_chat.py +307 -0
  20. mobile_agent/ai_plans/device_login.py +164 -0
  21. mobile_agent/ai_plans/draft_client.py +68 -0
  22. mobile_agent/ai_plans/gemini.py +137 -0
  23. mobile_agent/ai_plans/instructions.py +65 -0
  24. mobile_agent/ai_plans/mcp_http.py +160 -0
  25. mobile_agent/ai_plans/phone_tools.py +892 -0
  26. mobile_agent/ai_plans/providers.py +235 -0
  27. mobile_agent/ai_plans/routes.py +160 -0
  28. mobile_agent/ai_plans/runner.py +400 -0
  29. mobile_agent/ai_plans/vault.py +114 -0
  30. mobile_agent/alerts.py +337 -0
  31. mobile_agent/android/__init__.py +18 -0
  32. mobile_agent/android/adb.py +268 -0
  33. mobile_agent/android/conditions.py +128 -0
  34. mobile_agent/android/doctor.py +54 -0
  35. mobile_agent/android/driver.py +137 -0
  36. mobile_agent/android/emulator.py +216 -0
  37. mobile_agent/android/logs.py +85 -0
  38. mobile_agent/android/manager.py +225 -0
  39. mobile_agent/android/records.py +31 -0
  40. mobile_agent/android/tree.py +96 -0
  41. mobile_agent/answer_shapes.py +230 -0
  42. mobile_agent/api_devices.py +333 -0
  43. mobile_agent/api_errors.py +17 -0
  44. mobile_agent/api_get.py +249 -0
  45. mobile_agent/api_http.py +467 -0
  46. mobile_agent/api_post.py +453 -0
  47. mobile_agent/api_routes.py +173 -0
  48. mobile_agent/app_api/__init__.py +4 -0
  49. mobile_agent/app_api/cli.py +151 -0
  50. mobile_agent/app_api/endpoints.py +193 -0
  51. mobile_agent/app_api/mcp.py +54 -0
  52. mobile_agent/app_api/openapi.py +146 -0
  53. mobile_agent/app_api/reading.py +172 -0
  54. mobile_agent/app_api/register.py +10 -0
  55. mobile_agent/app_api/screen.py +216 -0
  56. mobile_agent/app_api/service.py +382 -0
  57. mobile_agent/app_api/sessions.py +404 -0
  58. mobile_agent/app_api/tokens.py +167 -0
  59. mobile_agent/app_choice.py +131 -0
  60. mobile_agent/app_icons.py +183 -0
  61. mobile_agent/app_killer.py +69 -0
  62. mobile_agent/artifacts.py +606 -0
  63. mobile_agent/attach/__init__.py +13 -0
  64. mobile_agent/attach/cli.py +46 -0
  65. mobile_agent/attach/flutter.py +28 -0
  66. mobile_agent/attach/score.py +119 -0
  67. mobile_agent/attach/web.py +13 -0
  68. mobile_agent/attachments/__init__.py +1 -0
  69. mobile_agent/attachments/agent.py +418 -0
  70. mobile_agent/attachments/extract.py +217 -0
  71. mobile_agent/attachments/mcp.py +104 -0
  72. mobile_agent/attachments/register.py +73 -0
  73. mobile_agent/attachments/routes.py +326 -0
  74. mobile_agent/attachments/service.py +170 -0
  75. mobile_agent/attachments/sniff.py +152 -0
  76. mobile_agent/attachments/store.py +441 -0
  77. mobile_agent/audit_verify.py +436 -0
  78. mobile_agent/bench/README.md +410 -0
  79. mobile_agent/bench/__init__.py +0 -0
  80. mobile_agent/bench/__main__.py +394 -0
  81. mobile_agent/bench/ab.py +168 -0
  82. mobile_agent/bench/actuation.py +368 -0
  83. mobile_agent/bench/agents/__init__.py +9 -0
  84. mobile_agent/bench/agents/base.py +105 -0
  85. mobile_agent/bench/agents/plan_clients.py +245 -0
  86. mobile_agent/bench/agents/smart.py +533 -0
  87. mobile_agent/bench/checks.py +358 -0
  88. mobile_agent/bench/decide_gate.py +214 -0
  89. mobile_agent/bench/diagnose.py +181 -0
  90. mobile_agent/bench/evals/__init__.py +14 -0
  91. mobile_agent/bench/evals/build.py +565 -0
  92. mobile_agent/bench/evals/checkpoint.py +214 -0
  93. mobile_agent/bench/evals/irt.py +219 -0
  94. mobile_agent/bench/evals/l0.py +647 -0
  95. mobile_agent/bench/evals/l1.py +866 -0
  96. mobile_agent/bench/evals/models.py +124 -0
  97. mobile_agent/bench/evals/pairwise.py +189 -0
  98. mobile_agent/bench/evals/proxy.py +90 -0
  99. mobile_agent/bench/evals/sets.py +149 -0
  100. mobile_agent/bench/evals/traces.py +446 -0
  101. mobile_agent/bench/fixtures.py +176 -0
  102. mobile_agent/bench/guard_replay.py +129 -0
  103. mobile_agent/bench/h2-manifest.json +20 -0
  104. mobile_agent/bench/h3-manifest.json +20 -0
  105. mobile_agent/bench/heldout-manifest.json +32 -0
  106. mobile_agent/bench/heldout.py +375 -0
  107. mobile_agent/bench/iosworld.py +901 -0
  108. mobile_agent/bench/iosworld_stats.py +510 -0
  109. mobile_agent/bench/llm_units.py +116 -0
  110. mobile_agent/bench/manifest.json +93 -0
  111. mobile_agent/bench/metrics.py +66 -0
  112. mobile_agent/bench/phone.py +44 -0
  113. mobile_agent/bench/replay.py +172 -0
  114. mobile_agent/bench/report.py +207 -0
  115. mobile_agent/bench/runner.py +456 -0
  116. mobile_agent/bench/safety.py +310 -0
  117. mobile_agent/bench/stream_timing.py +213 -0
  118. mobile_agent/bench/suite.py +444 -0
  119. mobile_agent/bench/sweep.py +176 -0
  120. mobile_agent/bench/tape.py +798 -0
  121. mobile_agent/bench/tape_replay.py +88 -0
  122. mobile_agent/bench/trace_evals.py +128 -0
  123. mobile_agent/bench/trace_view.py +81 -0
  124. mobile_agent/bench/truth/iphone15pro.json +138 -0
  125. mobile_agent/bench/truth.py +340 -0
  126. mobile_agent/bench/tuning.py +543 -0
  127. mobile_agent/bench/tuning_analysis.py +656 -0
  128. mobile_agent/bench/vague-heldout-manifest.json +12 -0
  129. mobile_agent/bench/vague_rubric.py +135 -0
  130. mobile_agent/bench/vague_run.py +243 -0
  131. mobile_agent/brand.py +454 -0
  132. mobile_agent/brand_fonts.py +756 -0
  133. mobile_agent/build_identity.py +21 -0
  134. mobile_agent/cable_bt.py +623 -0
  135. mobile_agent/cable_bt_runtime.py +128 -0
  136. mobile_agent/catalog.py +69 -0
  137. mobile_agent/chart_svg.py +415 -0
  138. mobile_agent/chat_here.py +189 -0
  139. mobile_agent/cli_constants.py +5 -0
  140. mobile_agent/cli_parser.py +611 -0
  141. mobile_agent/cli_run.py +115 -0
  142. mobile_agent/compiled_read/__init__.py +21 -0
  143. mobile_agent/compiled_read/delta.py +89 -0
  144. mobile_agent/compiled_read/extractors.py +202 -0
  145. mobile_agent/compiled_read/routes.py +56 -0
  146. mobile_agent/completion.py +267 -0
  147. mobile_agent/compose.py +48 -0
  148. mobile_agent/config.py +114 -0
  149. mobile_agent/connectors/__init__.py +1 -0
  150. mobile_agent/connectors/api_session.py +76 -0
  151. mobile_agent/connectors/callback_page.py +146 -0
  152. mobile_agent/connectors/client.py +582 -0
  153. mobile_agent/connectors/github_app.py +55 -0
  154. mobile_agent/connectors/graph_api.py +396 -0
  155. mobile_agent/connectors/imports.py +170 -0
  156. mobile_agent/connectors/issue.py +66 -0
  157. mobile_agent/connectors/keystore.py +85 -0
  158. mobile_agent/connectors/marks.py +222 -0
  159. mobile_agent/connectors/oauth.py +476 -0
  160. mobile_agent/connectors/picker.py +228 -0
  161. mobile_agent/connectors/presets.py +591 -0
  162. mobile_agent/connectors/register.py +48 -0
  163. mobile_agent/connectors/routes.py +153 -0
  164. mobile_agent/connectors/service.py +966 -0
  165. mobile_agent/connectors/shared.py +136 -0
  166. mobile_agent/connectors/skill.py +446 -0
  167. mobile_agent/connectors/slack_api.py +269 -0
  168. mobile_agent/connectors/steps.py +92 -0
  169. mobile_agent/connectors/store.py +144 -0
  170. mobile_agent/connectors/vault.py +72 -0
  171. mobile_agent/console.py +178 -0
  172. mobile_agent/content_queue/__init__.py +1 -0
  173. mobile_agent/content_queue/client.py +263 -0
  174. mobile_agent/content_queue/importing.py +153 -0
  175. mobile_agent/content_queue/media_check.py +224 -0
  176. mobile_agent/content_queue/prompt.py +64 -0
  177. mobile_agent/content_queue/register.py +91 -0
  178. mobile_agent/content_queue/routes.py +370 -0
  179. mobile_agent/content_queue/runner.py +475 -0
  180. mobile_agent/content_queue/store.py +521 -0
  181. mobile_agent/contract.py +996 -0
  182. mobile_agent/contract_asks.py +248 -0
  183. mobile_agent/contract_prompt.py +45 -0
  184. mobile_agent/contract_screen.py +981 -0
  185. mobile_agent/contract_view.py +84 -0
  186. mobile_agent/corpus/__init__.py +26 -0
  187. mobile_agent/corpus/cli.py +63 -0
  188. mobile_agent/corpus/consent.py +55 -0
  189. mobile_agent/corpus/listener.py +76 -0
  190. mobile_agent/corpus/register.py +9 -0
  191. mobile_agent/corpus/skeleton.py +72 -0
  192. mobile_agent/corpus/store.py +143 -0
  193. mobile_agent/costs.py +161 -0
  194. mobile_agent/decider_scope.py +40 -0
  195. mobile_agent/decision_provider.py +189 -0
  196. mobile_agent/deeplinks.py +352 -0
  197. mobile_agent/device_info.py +116 -0
  198. mobile_agent/device_manager.py +978 -0
  199. mobile_agent/device_status.py +195 -0
  200. mobile_agent/device_targets.py +217 -0
  201. mobile_agent/devices.py +676 -0
  202. mobile_agent/devkit/__init__.py +64 -0
  203. mobile_agent/devkit/account_cli.py +90 -0
  204. mobile_agent/devkit/asc.py +562 -0
  205. mobile_agent/devkit/asc_cli.py +214 -0
  206. mobile_agent/devkit/ci.py +737 -0
  207. mobile_agent/devkit/ci_cli.py +196 -0
  208. mobile_agent/devkit/ci_hosts.py +194 -0
  209. mobile_agent/devkit/es256.py +197 -0
  210. mobile_agent/devkit/expo.py +440 -0
  211. mobile_agent/devkit/expo_cli.py +405 -0
  212. mobile_agent/devkit/expo_dev.py +203 -0
  213. mobile_agent/devkit/expo_routes.py +90 -0
  214. mobile_agent/devkit/fixtures_cli.py +133 -0
  215. mobile_agent/devkit/fixtures_routes.py +82 -0
  216. mobile_agent/devkit/links.py +375 -0
  217. mobile_agent/devkit/links_cli.py +123 -0
  218. mobile_agent/devkit/links_routes.py +83 -0
  219. mobile_agent/devkit/nightly.py +152 -0
  220. mobile_agent/devkit/shots.py +203 -0
  221. mobile_agent/devkit/testflight.py +155 -0
  222. mobile_agent/devkit/testflight_cli.py +127 -0
  223. mobile_agent/devkit/testflight_routes.py +111 -0
  224. mobile_agent/devkit/xcode.py +236 -0
  225. mobile_agent/devkit/xcode_cli.py +101 -0
  226. mobile_agent/devtools.py +419 -0
  227. mobile_agent/doctor.py +509 -0
  228. mobile_agent/doctor_fix.py +467 -0
  229. mobile_agent/downloads.py +55 -0
  230. mobile_agent/drivers.py +793 -0
  231. mobile_agent/dry_run.py +102 -0
  232. mobile_agent/effect_ledger.py +83 -0
  233. mobile_agent/engine_health.py +378 -0
  234. mobile_agent/engine_hooks.py +96 -0
  235. mobile_agent/engines.py +408 -0
  236. mobile_agent/env_file.py +63 -0
  237. mobile_agent/env_secrets.py +149 -0
  238. mobile_agent/errors.py +15 -0
  239. mobile_agent/evals/__init__.py +3 -0
  240. mobile_agent/evals/app_survey.py +149 -0
  241. mobile_agent/evals/development/__init__.py +1 -0
  242. mobile_agent/evals/development/score.py +276 -0
  243. mobile_agent/evals/latency_report.py +312 -0
  244. mobile_agent/evals/offline_report.py +374 -0
  245. mobile_agent/evals/oracles.py +298 -0
  246. mobile_agent/evals/redteam/__init__.py +15 -0
  247. mobile_agent/evals/redteam/__main__.py +72 -0
  248. mobile_agent/evals/redteam/cases.py +730 -0
  249. mobile_agent/evals/redteam/harness.py +604 -0
  250. mobile_agent/evals/redteam/live.py +139 -0
  251. mobile_agent/evals/redteam/plain.py +85 -0
  252. mobile_agent/evals/vision/__init__.py +0 -0
  253. mobile_agent/evals/vision/images/dog_001.jpg +0 -0
  254. mobile_agent/evals/vision/images/dog_002.jpg +0 -0
  255. mobile_agent/evals/vision/images/dog_003.jpg +0 -0
  256. mobile_agent/evals/vision/images/dog_004.jpg +0 -0
  257. mobile_agent/evals/vision/images/dog_005.jpg +0 -0
  258. mobile_agent/evals/vision/images/dog_006.jpg +0 -0
  259. mobile_agent/evals/vision/images/dog_007.jpg +0 -0
  260. mobile_agent/evals/vision/images/dog_010.jpg +0 -0
  261. mobile_agent/evals/vision/images/dog_011.jpg +0 -0
  262. mobile_agent/evals/vision/images/dog_013.jpg +0 -0
  263. mobile_agent/evals/vision/images/dog_014.jpg +0 -0
  264. mobile_agent/evals/vision/images/dog_015.jpg +0 -0
  265. mobile_agent/evals/vision/images/dog_016.jpg +0 -0
  266. mobile_agent/evals/vision/images/dog_017.jpg +0 -0
  267. mobile_agent/evals/vision/images/dog_019.jpg +0 -0
  268. mobile_agent/evals/vision/images/dog_020.jpg +0 -0
  269. mobile_agent/evals/vision/images/dog_021.jpg +0 -0
  270. mobile_agent/evals/vision/images/dog_022.jpg +0 -0
  271. mobile_agent/evals/vision/images/dog_023.jpg +0 -0
  272. mobile_agent/evals/vision/images/dog_024.jpg +0 -0
  273. mobile_agent/evals/vision/images/dog_026.jpg +0 -0
  274. mobile_agent/evals/vision/images/dog_027.jpg +0 -0
  275. mobile_agent/evals/vision/images/dog_034.jpg +0 -0
  276. mobile_agent/evals/vision/images/dog_035.jpg +0 -0
  277. mobile_agent/evals/vision/images/dog_038.jpg +0 -0
  278. mobile_agent/evals/vision/images/dog_042.jpg +0 -0
  279. mobile_agent/evals/vision/images/dog_047.jpg +0 -0
  280. mobile_agent/evals/vision/images/dog_052.jpg +0 -0
  281. mobile_agent/evals/vision/images/dog_058.jpg +0 -0
  282. mobile_agent/evals/vision/images/dog_062.jpg +0 -0
  283. mobile_agent/evals/vision/images/eyes_000.jpg +0 -0
  284. mobile_agent/evals/vision/images/eyes_010.jpg +0 -0
  285. mobile_agent/evals/vision/images/eyes_011.jpg +0 -0
  286. mobile_agent/evals/vision/images/eyes_015.jpg +0 -0
  287. mobile_agent/evals/vision/images/eyes_016.jpg +0 -0
  288. mobile_agent/evals/vision/images/eyes_017.jpg +0 -0
  289. mobile_agent/evals/vision/images/eyes_019.jpg +0 -0
  290. mobile_agent/evals/vision/images/eyes_021.jpg +0 -0
  291. mobile_agent/evals/vision/images/eyes_025.jpg +0 -0
  292. mobile_agent/evals/vision/images/eyes_026.jpg +0 -0
  293. mobile_agent/evals/vision/images/eyes_027.jpg +0 -0
  294. mobile_agent/evals/vision/images/eyes_030.jpg +0 -0
  295. mobile_agent/evals/vision/images/eyes_032.jpg +0 -0
  296. mobile_agent/evals/vision/images/eyes_033.jpg +0 -0
  297. mobile_agent/evals/vision/images/eyes_034.jpg +0 -0
  298. mobile_agent/evals/vision/images/eyes_035.jpg +0 -0
  299. mobile_agent/evals/vision/images/eyes_036.jpg +0 -0
  300. mobile_agent/evals/vision/images/eyes_037.jpg +0 -0
  301. mobile_agent/evals/vision/images/eyes_039.jpg +0 -0
  302. mobile_agent/evals/vision/images/eyes_040.jpg +0 -0
  303. mobile_agent/evals/vision/images/eyes_041.jpg +0 -0
  304. mobile_agent/evals/vision/images/eyes_042.jpg +0 -0
  305. mobile_agent/evals/vision/images/eyes_043.jpg +0 -0
  306. mobile_agent/evals/vision/images/eyes_044.jpg +0 -0
  307. mobile_agent/evals/vision/images/eyes_046.jpg +0 -0
  308. mobile_agent/evals/vision/images/eyes_047.jpg +0 -0
  309. mobile_agent/evals/vision/images/eyes_048.jpg +0 -0
  310. mobile_agent/evals/vision/images/eyes_049.jpg +0 -0
  311. mobile_agent/evals/vision/images/eyes_051.jpg +0 -0
  312. mobile_agent/evals/vision/images/eyes_053.jpg +0 -0
  313. mobile_agent/evals/vision/images/eyes_054.jpg +0 -0
  314. mobile_agent/evals/vision/images/eyes_055.jpg +0 -0
  315. mobile_agent/evals/vision/images/eyes_058.jpg +0 -0
  316. mobile_agent/evals/vision/images/eyes_059.jpg +0 -0
  317. mobile_agent/evals/vision/images/receipt_002.jpg +0 -0
  318. mobile_agent/evals/vision/images/receipt_003.jpg +0 -0
  319. mobile_agent/evals/vision/images/receipt_004.jpg +0 -0
  320. mobile_agent/evals/vision/images/receipt_007.jpg +0 -0
  321. mobile_agent/evals/vision/images/receipt_009.jpg +0 -0
  322. mobile_agent/evals/vision/images/receipt_010.jpg +0 -0
  323. mobile_agent/evals/vision/images/receipt_011.jpg +0 -0
  324. mobile_agent/evals/vision/images/receipt_012.jpg +0 -0
  325. mobile_agent/evals/vision/images/receipt_013.jpg +0 -0
  326. mobile_agent/evals/vision/images/receipt_014.jpg +0 -0
  327. mobile_agent/evals/vision/images/receipt_016.jpg +0 -0
  328. mobile_agent/evals/vision/images/receipt_017.jpg +0 -0
  329. mobile_agent/evals/vision/images/receipt_023.jpg +0 -0
  330. mobile_agent/evals/vision/images/receipt_027.jpg +0 -0
  331. mobile_agent/evals/vision/images/receipt_029.jpg +0 -0
  332. mobile_agent/evals/vision/images/receipt_032.jpg +0 -0
  333. mobile_agent/evals/vision/images/receipt_033.jpg +0 -0
  334. mobile_agent/evals/vision/images/receipt_036.jpg +0 -0
  335. mobile_agent/evals/vision/images/receipt_041.jpg +0 -0
  336. mobile_agent/evals/vision/images/receipt_043.jpg +0 -0
  337. mobile_agent/evals/vision/images/receipt_047.jpg +0 -0
  338. mobile_agent/evals/vision/images/receipt_049.jpg +0 -0
  339. mobile_agent/evals/vision/images/receipt_051.jpg +0 -0
  340. mobile_agent/evals/vision/images/receipt_053.jpg +0 -0
  341. mobile_agent/evals/vision/images/receipt_056.jpg +0 -0
  342. mobile_agent/evals/vision/images/receipt_057.jpg +0 -0
  343. mobile_agent/evals/vision/images/receipt_058.jpg +0 -0
  344. mobile_agent/evals/vision/images/receipt_059.jpg +0 -0
  345. mobile_agent/evals/vision/images/receipt_060.jpg +0 -0
  346. mobile_agent/evals/vision/images/receipt_061.jpg +0 -0
  347. mobile_agent/evals/vision/images/receipt_062.jpg +0 -0
  348. mobile_agent/evals/vision/images/receipt_063.jpg +0 -0
  349. mobile_agent/evals/vision/images/receipt_064.jpg +0 -0
  350. mobile_agent/evals/vision/images/receipt_065.jpg +0 -0
  351. mobile_agent/evals/vision/images/receipt_066.jpg +0 -0
  352. mobile_agent/evals/vision/images/receipt_067.jpg +0 -0
  353. mobile_agent/evals/vision/images/receipt_068.jpg +0 -0
  354. mobile_agent/evals/vision/images/receipt_069.jpg +0 -0
  355. mobile_agent/evals/vision/images/receipt_070.jpg +0 -0
  356. mobile_agent/evals/vision/images/receipt_071.jpg +0 -0
  357. mobile_agent/evals/vision/images/sunglasses_000.jpg +0 -0
  358. mobile_agent/evals/vision/images/sunglasses_001.jpg +0 -0
  359. mobile_agent/evals/vision/images/sunglasses_002.jpg +0 -0
  360. mobile_agent/evals/vision/images/sunglasses_004.jpg +0 -0
  361. mobile_agent/evals/vision/images/sunglasses_005.jpg +0 -0
  362. mobile_agent/evals/vision/images/sunglasses_008.jpg +0 -0
  363. mobile_agent/evals/vision/images/sunglasses_009.jpg +0 -0
  364. mobile_agent/evals/vision/images/sunglasses_010.jpg +0 -0
  365. mobile_agent/evals/vision/images/sunglasses_012.jpg +0 -0
  366. mobile_agent/evals/vision/images/sunglasses_013.jpg +0 -0
  367. mobile_agent/evals/vision/images/sunglasses_015.jpg +0 -0
  368. mobile_agent/evals/vision/images/sunglasses_016.jpg +0 -0
  369. mobile_agent/evals/vision/images/sunglasses_017.jpg +0 -0
  370. mobile_agent/evals/vision/images/sunglasses_018.jpg +0 -0
  371. mobile_agent/evals/vision/images/sunglasses_021.jpg +0 -0
  372. mobile_agent/evals/vision/images/sunglasses_022.jpg +0 -0
  373. mobile_agent/evals/vision/images/sunglasses_023.jpg +0 -0
  374. mobile_agent/evals/vision/images/sunglasses_024.jpg +0 -0
  375. mobile_agent/evals/vision/images/sunglasses_030.jpg +0 -0
  376. mobile_agent/evals/vision/images/sunglasses_031.jpg +0 -0
  377. mobile_agent/evals/vision/images/sunglasses_032.jpg +0 -0
  378. mobile_agent/evals/vision/images/sunglasses_033.jpg +0 -0
  379. mobile_agent/evals/vision/images/sunglasses_034.jpg +0 -0
  380. mobile_agent/evals/vision/images/sunglasses_036.jpg +0 -0
  381. mobile_agent/evals/vision/images/sunglasses_038.jpg +0 -0
  382. mobile_agent/evals/vision/images/sunglasses_039.jpg +0 -0
  383. mobile_agent/evals/vision/images/sunglasses_040.jpg +0 -0
  384. mobile_agent/evals/vision/images/sunglasses_041.jpg +0 -0
  385. mobile_agent/evals/vision/manifest.json +2355 -0
  386. mobile_agent/eventbus.py +110 -0
  387. mobile_agent/explain.py +34 -0
  388. mobile_agent/failure_line.py +197 -0
  389. mobile_agent/fanout.py +663 -0
  390. mobile_agent/feedback/__init__.py +2 -0
  391. mobile_agent/feedback/bundle.py +204 -0
  392. mobile_agent/feedback/outbox.py +196 -0
  393. mobile_agent/feedback/register.py +9 -0
  394. mobile_agent/feedback/routes.py +177 -0
  395. mobile_agent/fleet.py +841 -0
  396. mobile_agent/fleet_health.py +729 -0
  397. mobile_agent/fleet_phone.py +186 -0
  398. mobile_agent/frontier/__init__.py +79 -0
  399. mobile_agent/frontier/act.py +380 -0
  400. mobile_agent/frontier/actions.py +70 -0
  401. mobile_agent/frontier/agent.py +256 -0
  402. mobile_agent/frontier/approvals.py +366 -0
  403. mobile_agent/frontier/hooks.py +199 -0
  404. mobile_agent/frontier/interrupts.py +125 -0
  405. mobile_agent/frontier/observe.py +331 -0
  406. mobile_agent/frontier/phases.py +381 -0
  407. mobile_agent/frontier/pipeline.py +61 -0
  408. mobile_agent/frontier/prompt.py +384 -0
  409. mobile_agent/frontier/protocol.py +91 -0
  410. mobile_agent/frontier/safety.py +467 -0
  411. mobile_agent/frontier/saved.py +375 -0
  412. mobile_agent/frontier/screen.py +419 -0
  413. mobile_agent/frontier/skills.py +147 -0
  414. mobile_agent/frontier/stages/__init__.py +1 -0
  415. mobile_agent/frontier/stages/after.py +192 -0
  416. mobile_agent/frontier/stages/approve.py +138 -0
  417. mobile_agent/frontier/stages/controls.py +115 -0
  418. mobile_agent/frontier/stages/ends.py +102 -0
  419. mobile_agent/frontier/stages/gate.py +92 -0
  420. mobile_agent/frontier/stages/guards.py +132 -0
  421. mobile_agent/frontier/stages/points.py +155 -0
  422. mobile_agent/frontier/stages/send.py +177 -0
  423. mobile_agent/frontier/turn.py +151 -0
  424. mobile_agent/full_disk_access.py +83 -0
  425. mobile_agent/gemini.py +69 -0
  426. mobile_agent/genuine.py +120 -0
  427. mobile_agent/graph/__init__.py +4 -0
  428. mobile_agent/graph/catalog.py +789 -0
  429. mobile_agent/graph/chain.py +306 -0
  430. mobile_agent/graph/dispatch.py +98 -0
  431. mobile_agent/graph/draft.py +373 -0
  432. mobile_agent/graph/edit.py +76 -0
  433. mobile_agent/graph/estimate.py +189 -0
  434. mobile_agent/graph/expr.py +562 -0
  435. mobile_agent/graph/functions.py +271 -0
  436. mobile_agent/graph/infer.py +144 -0
  437. mobile_agent/graph/nodes.py +936 -0
  438. mobile_agent/graph/phone_steps.py +178 -0
  439. mobile_agent/graph/rerun.py +327 -0
  440. mobile_agent/graph/run.py +899 -0
  441. mobile_agent/graph/schema.py +842 -0
  442. mobile_agent/graph/state.py +161 -0
  443. mobile_agent/graph/values.py +198 -0
  444. mobile_agent/harness/__init__.py +2 -0
  445. mobile_agent/harness/checkpoints.py +468 -0
  446. mobile_agent/harness/control.py +101 -0
  447. mobile_agent/harness/prewarm.py +213 -0
  448. mobile_agent/harness/register.py +43 -0
  449. mobile_agent/harness/routes.py +114 -0
  450. mobile_agent/harness/settings.py +66 -0
  451. mobile_agent/harness/tools/__init__.py +67 -0
  452. mobile_agent/harness/tools/ask_user.py +102 -0
  453. mobile_agent/harness/tools/watch.py +120 -0
  454. mobile_agent/harness_api.py +815 -0
  455. mobile_agent/hedge.py +203 -0
  456. mobile_agent/help_topics.py +305 -0
  457. mobile_agent/hints.py +248 -0
  458. mobile_agent/history.py +69 -0
  459. mobile_agent/home.py +214 -0
  460. mobile_agent/http_pool.py +175 -0
  461. mobile_agent/image_policy.py +139 -0
  462. mobile_agent/inbox.py +148 -0
  463. mobile_agent/installed_apps.py +344 -0
  464. mobile_agent/integrations/__init__.py +1 -0
  465. mobile_agent/integrations/cli.py +472 -0
  466. mobile_agent/integrations/client_files.py +65 -0
  467. mobile_agent/integrations/clients.py +998 -0
  468. mobile_agent/integrations/doctor.py +185 -0
  469. mobile_agent/integrations/jsonc.py +383 -0
  470. mobile_agent/integrations/routes.py +135 -0
  471. mobile_agent/integrations/rules.py +112 -0
  472. mobile_agent/integrations/server_options.py +46 -0
  473. mobile_agent/integrations/skill.py +152 -0
  474. mobile_agent/integrations/skill_files.py +10 -0
  475. mobile_agent/integrations/textedit.py +309 -0
  476. mobile_agent/intents/__init__.py +17 -0
  477. mobile_agent/intents/atlas.py +216 -0
  478. mobile_agent/intents/callback.py +44 -0
  479. mobile_agent/intents/cli.py +55 -0
  480. mobile_agent/intents/harvest.py +91 -0
  481. mobile_agent/intents/plan.py +93 -0
  482. mobile_agent/ios/__init__.py +1 -0
  483. mobile_agent/ios/guide.py +16 -0
  484. mobile_agent/ios/kb.py +212 -0
  485. mobile_agent/ios/kb_data.py +1588 -0
  486. mobile_agent/ios/mcp.py +44 -0
  487. mobile_agent/ios/register.py +8 -0
  488. mobile_agent/ios/system.py +369 -0
  489. mobile_agent/journal.py +531 -0
  490. mobile_agent/keychain_acl.py +374 -0
  491. mobile_agent/keys.py +395 -0
  492. mobile_agent/latency_overlap.py +36 -0
  493. mobile_agent/latency_trace.py +170 -0
  494. mobile_agent/learned/__init__.py +15 -0
  495. mobile_agent/learned/app_path.py +160 -0
  496. mobile_agent/learned/code_read.py +38 -0
  497. mobile_agent/learned/parts.py +546 -0
  498. mobile_agent/learned/programs.py +691 -0
  499. mobile_agent/learned/register.py +171 -0
  500. mobile_agent/learned/routes.py +61 -0
  501. mobile_agent/learned/taught.py +329 -0
  502. mobile_agent/learned/teach.py +538 -0
  503. mobile_agent/learned/workflows.py +647 -0
  504. mobile_agent/learned/zero.py +41 -0
  505. mobile_agent/links.py +37 -0
  506. mobile_agent/listen.py +607 -0
  507. mobile_agent/lock_spike.py +278 -0
  508. mobile_agent/lockscreen.py +526 -0
  509. mobile_agent/login.py +354 -0
  510. mobile_agent/longform/__init__.py +15 -0
  511. mobile_agent/longform/ads.py +191 -0
  512. mobile_agent/longform/blocks.py +117 -0
  513. mobile_agent/longform/budget.py +265 -0
  514. mobile_agent/longform/context.py +285 -0
  515. mobile_agent/longform/costs.py +93 -0
  516. mobile_agent/longform/digest.py +145 -0
  517. mobile_agent/longform/extract.py +508 -0
  518. mobile_agent/longform/feed.py +505 -0
  519. mobile_agent/longform/followup.py +168 -0
  520. mobile_agent/longform/frames.py +82 -0
  521. mobile_agent/longform/identity.py +87 -0
  522. mobile_agent/longform/inbox.py +221 -0
  523. mobile_agent/longform/items.py +425 -0
  524. mobile_agent/longform/models.py +115 -0
  525. mobile_agent/longform/notebook.py +329 -0
  526. mobile_agent/longform/plan.py +614 -0
  527. mobile_agent/longform/recall.py +195 -0
  528. mobile_agent/longform/receipts.py +81 -0
  529. mobile_agent/longform/register.py +124 -0
  530. mobile_agent/longform/report.py +343 -0
  531. mobile_agent/longform/routes.py +102 -0
  532. mobile_agent/longform/session.py +644 -0
  533. mobile_agent/longform/store.py +146 -0
  534. mobile_agent/longform/synthesis.py +347 -0
  535. mobile_agent/mac_tools.py +223 -0
  536. mobile_agent/manual_control.py +143 -0
  537. mobile_agent/maps.py +149 -0
  538. mobile_agent/marks.py +92 -0
  539. mobile_agent/mcp_server/__init__.py +3 -0
  540. mobile_agent/mcp_server/__main__.py +29 -0
  541. mobile_agent/mcp_server/action_journal.py +24 -0
  542. mobile_agent/mcp_server/action_tools.py +638 -0
  543. mobile_agent/mcp_server/approvals.py +219 -0
  544. mobile_agent/mcp_server/catalog.py +92 -0
  545. mobile_agent/mcp_server/cli.py +194 -0
  546. mobile_agent/mcp_server/codes.py +147 -0
  547. mobile_agent/mcp_server/device_tools.py +306 -0
  548. mobile_agent/mcp_server/direct.py +272 -0
  549. mobile_agent/mcp_server/expo_tools.py +105 -0
  550. mobile_agent/mcp_server/phone_tools.py +510 -0
  551. mobile_agent/mcp_server/protocol.py +364 -0
  552. mobile_agent/mcp_server/registry.py +55 -0
  553. mobile_agent/mcp_server/run_tools.py +531 -0
  554. mobile_agent/mcp_server/schemas.py +425 -0
  555. mobile_agent/mcp_server/screen_tools.py +168 -0
  556. mobile_agent/mcp_server/session.py +469 -0
  557. mobile_agent/mcp_server/support.py +145 -0
  558. mobile_agent/mcp_server/tools.py +493 -0
  559. mobile_agent/memory/__init__.py +9 -0
  560. mobile_agent/memory/cli.py +207 -0
  561. mobile_agent/memory/extract.py +191 -0
  562. mobile_agent/memory/listener.py +100 -0
  563. mobile_agent/memory/model.py +144 -0
  564. mobile_agent/memory/project.py +96 -0
  565. mobile_agent/memory/provider.py +127 -0
  566. mobile_agent/memory/register.py +21 -0
  567. mobile_agent/memory/retrieval.py +172 -0
  568. mobile_agent/memory/routes.py +216 -0
  569. mobile_agent/memory/runs.py +124 -0
  570. mobile_agent/memory/store.py +806 -0
  571. mobile_agent/memory/writer.py +278 -0
  572. mobile_agent/mirroring.py +585 -0
  573. mobile_agent/mirroring_runtime.py +221 -0
  574. mobile_agent/model_clients.py +604 -0
  575. mobile_agent/narrate.py +813 -0
  576. mobile_agent/native_helpers.py +84 -0
  577. mobile_agent/netxray/__init__.py +1 -0
  578. mobile_agent/netxray/analyze.py +322 -0
  579. mobile_agent/netxray/attribution.py +62 -0
  580. mobile_agent/netxray/capture.py +88 -0
  581. mobile_agent/netxray/cli.py +142 -0
  582. mobile_agent/netxray/job.py +219 -0
  583. mobile_agent/netxray/mobster-pcap.c +560 -0
  584. mobile_agent/netxray/packets.py +410 -0
  585. mobile_agent/netxray/pcapng.py +223 -0
  586. mobile_agent/netxray/register.py +93 -0
  587. mobile_agent/netxray/report.py +214 -0
  588. mobile_agent/netxray/store.py +48 -0
  589. mobile_agent/netxray/summary.py +157 -0
  590. mobile_agent/netxray/target.py +67 -0
  591. mobile_agent/netxray/tool.py +66 -0
  592. mobile_agent/netxray/trackers.py +194 -0
  593. mobile_agent/notify_triggers/__init__.py +1 -0
  594. mobile_agent/notify_triggers/rules.py +39 -0
  595. mobile_agent/notify_triggers/sources.py +315 -0
  596. mobile_agent/notify_triggers/watch.py +135 -0
  597. mobile_agent/offers.py +86 -0
  598. mobile_agent/orchestrate.py +215 -0
  599. mobile_agent/outlets/__init__.py +1 -0
  600. mobile_agent/outlets/connect.py +249 -0
  601. mobile_agent/outlets/folder.py +180 -0
  602. mobile_agent/outlets/hooks.py +453 -0
  603. mobile_agent/outlets/inbound.py +472 -0
  604. mobile_agent/outlets/inbound_reply.py +57 -0
  605. mobile_agent/outlets/inbound_routes.py +81 -0
  606. mobile_agent/outlets/kinds.py +308 -0
  607. mobile_agent/outlets/mail.py +110 -0
  608. mobile_agent/outlets/net.py +86 -0
  609. mobile_agent/outlets/notion.py +244 -0
  610. mobile_agent/outlets/register.py +56 -0
  611. mobile_agent/outlets/routes.py +135 -0
  612. mobile_agent/outlets/service.py +580 -0
  613. mobile_agent/outlets/sheets.py +169 -0
  614. mobile_agent/outlets/slack.py +177 -0
  615. mobile_agent/outlets/store.py +194 -0
  616. mobile_agent/outlets/vault.py +80 -0
  617. mobile_agent/outlets/webhook.py +316 -0
  618. mobile_agent/output_contract.py +141 -0
  619. mobile_agent/owner_presence.py +211 -0
  620. mobile_agent/ownership.py +219 -0
  621. mobile_agent/packs/__init__.py +1 -0
  622. mobile_agent/packs/calendar.py +243 -0
  623. mobile_agent/packs/context.py +68 -0
  624. mobile_agent/packs/core.py +757 -0
  625. mobile_agent/packs/front_door.py +316 -0
  626. mobile_agent/packs/heal.py +214 -0
  627. mobile_agent/packs/health.py +122 -0
  628. mobile_agent/packs/insights.py +76 -0
  629. mobile_agent/packs/instagram.py +640 -0
  630. mobile_agent/packs/linkedin.py +106 -0
  631. mobile_agent/packs/maps.py +196 -0
  632. mobile_agent/packs/mcp.py +149 -0
  633. mobile_agent/packs/messages.py +270 -0
  634. mobile_agent/packs/notes.py +226 -0
  635. mobile_agent/packs/photos.py +166 -0
  636. mobile_agent/packs/pins.py +47 -0
  637. mobile_agent/packs/reddit.py +110 -0
  638. mobile_agent/packs/register.py +276 -0
  639. mobile_agent/packs/rows.py +108 -0
  640. mobile_agent/packs/safari.py +143 -0
  641. mobile_agent/packs/settings.py +253 -0
  642. mobile_agent/packs/social.py +300 -0
  643. mobile_agent/packs/threads.py +97 -0
  644. mobile_agent/packs/tiktok.py +455 -0
  645. mobile_agent/packs/tools.py +290 -0
  646. mobile_agent/packs/x.py +127 -0
  647. mobile_agent/packs/youtube.py +199 -0
  648. mobile_agent/parity.py +270 -0
  649. mobile_agent/paths.py +99 -0
  650. mobile_agent/perception.py +470 -0
  651. mobile_agent/permissions/__init__.py +32 -0
  652. mobile_agent/permissions/consequence.py +535 -0
  653. mobile_agent/permissions/exceptions.py +99 -0
  654. mobile_agent/permissions/gate.py +316 -0
  655. mobile_agent/permissions/outside.py +316 -0
  656. mobile_agent/permissions/policy.py +288 -0
  657. mobile_agent/permissions/project_policy.py +411 -0
  658. mobile_agent/permissions/register.py +148 -0
  659. mobile_agent/permissions/rules.py +291 -0
  660. mobile_agent/phone_io/__init__.py +146 -0
  661. mobile_agent/phone_io/cli.py +427 -0
  662. mobile_agent/phone_io/clipboard.py +78 -0
  663. mobile_agent/phone_io/controls.py +78 -0
  664. mobile_agent/phone_io/files.py +289 -0
  665. mobile_agent/phone_io/handoff.py +123 -0
  666. mobile_agent/phone_io/icloud.py +118 -0
  667. mobile_agent/phone_io/install.py +188 -0
  668. mobile_agent/phone_io/network_capture.py +188 -0
  669. mobile_agent/phone_io/network_cli.py +138 -0
  670. mobile_agent/phone_io/network_profiles.py +138 -0
  671. mobile_agent/phone_io/photos.py +512 -0
  672. mobile_agent/phone_io/recording.py +115 -0
  673. mobile_agent/phone_io/secrets.py +146 -0
  674. mobile_agent/phone_io/transfer.py +895 -0
  675. mobile_agent/phone_io/tunnel.py +129 -0
  676. mobile_agent/phone_ready.py +91 -0
  677. mobile_agent/pinning.py +158 -0
  678. mobile_agent/plan_gate.py +807 -0
  679. mobile_agent/plugins/__init__.py +3 -0
  680. mobile_agent/plugins/install.py +163 -0
  681. mobile_agent/plugins/manifest.py +242 -0
  682. mobile_agent/plugins/register.py +15 -0
  683. mobile_agent/plugins/routes.py +82 -0
  684. mobile_agent/plugins/service.py +322 -0
  685. mobile_agent/plugins/skills.py +76 -0
  686. mobile_agent/plugins/store.py +79 -0
  687. mobile_agent/pool.py +285 -0
  688. mobile_agent/power_watch.py +275 -0
  689. mobile_agent/premium_model.py +22 -0
  690. mobile_agent/project_env.py +291 -0
  691. mobile_agent/project_env_cli.py +74 -0
  692. mobile_agent/project_env_routes.py +55 -0
  693. mobile_agent/projects/__init__.py +27 -0
  694. mobile_agent/projects/ci.py +332 -0
  695. mobile_agent/projects/clone.py +339 -0
  696. mobile_agent/projects/drafts.py +158 -0
  697. mobile_agent/projects/folder.py +436 -0
  698. mobile_agent/projects/github.py +131 -0
  699. mobile_agent/projects/register.py +31 -0
  700. mobile_agent/projects/revisions.py +253 -0
  701. mobile_agent/projects/routes.py +234 -0
  702. mobile_agent/projects/runs.py +297 -0
  703. mobile_agent/projects/service.py +695 -0
  704. mobile_agent/projects/setup.py +84 -0
  705. mobile_agent/projects/store.py +379 -0
  706. mobile_agent/projects/sync.py +380 -0
  707. mobile_agent/projects/workflow_files.py +270 -0
  708. mobile_agent/replay_core/__init__.py +26 -0
  709. mobile_agent/replay_core/checks.py +594 -0
  710. mobile_agent/replay_core/engine.py +596 -0
  711. mobile_agent/replay_core/heal.py +364 -0
  712. mobile_agent/replay_core/path.py +240 -0
  713. mobile_agent/replay_core/recorder.py +206 -0
  714. mobile_agent/replay_core/store.py +171 -0
  715. mobile_agent/result_blocks.py +941 -0
  716. mobile_agent/run.py +642 -0
  717. mobile_agent/run_delivery.py +123 -0
  718. mobile_agent/run_executor.py +200 -0
  719. mobile_agent/run_export.py +284 -0
  720. mobile_agent/run_gif.py +891 -0
  721. mobile_agent/runner_hints.py +86 -0
  722. mobile_agent/runner_renewal.py +205 -0
  723. mobile_agent/runtime_create.py +549 -0
  724. mobile_agent/runtime_driver.py +458 -0
  725. mobile_agent/runtime_limits.py +319 -0
  726. mobile_agent/runtime_queue.py +394 -0
  727. mobile_agent/runtime_runs.py +383 -0
  728. mobile_agent/runtime_status.py +181 -0
  729. mobile_agent/runtime_teach.py +295 -0
  730. mobile_agent/runtime_work.py +599 -0
  731. mobile_agent/screen_text.py +101 -0
  732. mobile_agent/secret_filter.py +113 -0
  733. mobile_agent/serve.py +160 -0
  734. mobile_agent/server.py +363 -0
  735. mobile_agent/service_support.py +42 -0
  736. mobile_agent/settle/__init__.py +1 -0
  737. mobile_agent/settle/predict.py +102 -0
  738. mobile_agent/settle/replay.py +92 -0
  739. mobile_agent/settle/store.py +93 -0
  740. mobile_agent/settle/stream.py +43 -0
  741. mobile_agent/setup_cli.py +225 -0
  742. mobile_agent/setup_errors.py +87 -0
  743. mobile_agent/setup_service.py +527 -0
  744. mobile_agent/share.py +104 -0
  745. mobile_agent/signing.py +184 -0
  746. mobile_agent/sim/__init__.py +6 -0
  747. mobile_agent/sim/__main__.py +26 -0
  748. mobile_agent/sim/api.py +952 -0
  749. mobile_agent/sim/apps.py +172 -0
  750. mobile_agent/sim/biometrics.py +84 -0
  751. mobile_agent/sim/cli.py +271 -0
  752. mobile_agent/sim/doctor.py +293 -0
  753. mobile_agent/sim/governor.py +90 -0
  754. mobile_agent/sim/holders.py +88 -0
  755. mobile_agent/sim/models.py +62 -0
  756. mobile_agent/sim/registry.py +161 -0
  757. mobile_agent/sim/simctl.py +269 -0
  758. mobile_agent/sim/wda.py +618 -0
  759. mobile_agent/sim/xcode.py +74 -0
  760. mobile_agent/skills/__init__.py +12 -0
  761. mobile_agent/skills/codes.py +597 -0
  762. mobile_agent/skills/notifications.py +281 -0
  763. mobile_agent/skills/open_url.py +127 -0
  764. mobile_agent/smart_events.py +588 -0
  765. mobile_agent/smart_result.py +490 -0
  766. mobile_agent/smart_run.py +413 -0
  767. mobile_agent/state.py +662 -0
  768. mobile_agent/states.py +217 -0
  769. mobile_agent/steering.py +70 -0
  770. mobile_agent/style.py +178 -0
  771. mobile_agent/supervised.py +234 -0
  772. mobile_agent/swift/helper_bt_hid.swift +534 -0
  773. mobile_agent/swift/helper_doc_text.swift +184 -0
  774. mobile_agent/swift/helper_draft_reply.swift +170 -0
  775. mobile_agent/swift/helper_map.swift +110 -0
  776. mobile_agent/swift/helper_mirroring.swift +1099 -0
  777. mobile_agent/swift/helper_mjpeg_mp4.swift +103 -0
  778. mobile_agent/swift/helper_pdf.swift +100 -0
  779. mobile_agent/swift/helper_phone_audio.swift +993 -0
  780. mobile_agent/swift/helper_phone_screen.swift +416 -0
  781. mobile_agent/swift/helper_screen_text.swift +24 -0
  782. mobile_agent/swift/helper_transfer.swift +246 -0
  783. mobile_agent/swift/ocr.swift +22 -0
  784. mobile_agent/task_policy.py +337 -0
  785. mobile_agent/team_signing/__init__.py +34 -0
  786. mobile_agent/team_signing/apple_ca.py +37 -0
  787. mobile_agent/team_signing/bundle.py +136 -0
  788. mobile_agent/team_signing/cli.py +208 -0
  789. mobile_agent/team_signing/identity.py +248 -0
  790. mobile_agent/team_signing/ledger.py +105 -0
  791. mobile_agent/team_signing/prebuilt.py +61 -0
  792. mobile_agent/team_signing/resign.py +256 -0
  793. mobile_agent/team_signing/service.py +382 -0
  794. mobile_agent/team_signing/tooling.py +243 -0
  795. mobile_agent/team_signing/writes.py +268 -0
  796. mobile_agent/terminal_image.py +81 -0
  797. mobile_agent/testkit/__init__.py +1 -0
  798. mobile_agent/testkit/a11y_baseline.py +132 -0
  799. mobile_agent/testkit/api.py +403 -0
  800. mobile_agent/testkit/capsule.py +400 -0
  801. mobile_agent/testkit/capsule_cli.py +57 -0
  802. mobile_agent/testkit/cli.py +948 -0
  803. mobile_agent/testkit/cli_arguments.py +193 -0
  804. mobile_agent/testkit/comparison.py +288 -0
  805. mobile_agent/testkit/comparison_cli.py +41 -0
  806. mobile_agent/testkit/discover.py +257 -0
  807. mobile_agent/testkit/editor.py +243 -0
  808. mobile_agent/testkit/execute.py +515 -0
  809. mobile_agent/testkit/github_checks.py +248 -0
  810. mobile_agent/testkit/gitref.py +66 -0
  811. mobile_agent/testkit/heal_review.py +176 -0
  812. mobile_agent/testkit/health.py +480 -0
  813. mobile_agent/testkit/history.py +255 -0
  814. mobile_agent/testkit/hosted_results.py +321 -0
  815. mobile_agent/testkit/input_files.py +173 -0
  816. mobile_agent/testkit/jobs.py +285 -0
  817. mobile_agent/testkit/junit_verdict.py +33 -0
  818. mobile_agent/testkit/maestro.py +802 -0
  819. mobile_agent/testkit/mcp.py +562 -0
  820. mobile_agent/testkit/mcp_comparison.py +88 -0
  821. mobile_agent/testkit/minimize.py +471 -0
  822. mobile_agent/testkit/minimizer_cli.py +48 -0
  823. mobile_agent/testkit/notify.py +212 -0
  824. mobile_agent/testkit/phone_video.py +191 -0
  825. mobile_agent/testkit/pr.py +491 -0
  826. mobile_agent/testkit/pr_report.py +562 -0
  827. mobile_agent/testkit/prbuild.py +148 -0
  828. mobile_agent/testkit/proof_report.py +55 -0
  829. mobile_agent/testkit/provenance.py +119 -0
  830. mobile_agent/testkit/prrun.py +244 -0
  831. mobile_agent/testkit/recent.py +166 -0
  832. mobile_agent/testkit/recipes.py +146 -0
  833. mobile_agent/testkit/record.py +204 -0
  834. mobile_agent/testkit/register.py +288 -0
  835. mobile_agent/testkit/reports.py +998 -0
  836. mobile_agent/testkit/repro.py +432 -0
  837. mobile_agent/testkit/scenario.py +440 -0
  838. mobile_agent/testkit/scenario_cli.py +37 -0
  839. mobile_agent/testkit/snapshots_cli.py +60 -0
  840. mobile_agent/testkit/suite.py +670 -0
  841. mobile_agent/testkit/targets.py +497 -0
  842. mobile_agent/testkit/xctest.py +378 -0
  843. mobile_agent/threads/__init__.py +1 -0
  844. mobile_agent/threads/chat_once.py +264 -0
  845. mobile_agent/threads/cli.py +740 -0
  846. mobile_agent/threads/client.py +326 -0
  847. mobile_agent/threads/context.py +246 -0
  848. mobile_agent/threads/mcp.py +739 -0
  849. mobile_agent/threads/recent.py +34 -0
  850. mobile_agent/threads/register.py +54 -0
  851. mobile_agent/threads/routes.py +188 -0
  852. mobile_agent/threads/service.py +975 -0
  853. mobile_agent/threads/store.py +361 -0
  854. mobile_agent/threads/summary.py +117 -0
  855. mobile_agent/threads/term.py +101 -0
  856. mobile_agent/threads/workflow_cli.py +104 -0
  857. mobile_agent/tls.py +36 -0
  858. mobile_agent/traces.py +271 -0
  859. mobile_agent/tracks.py +235 -0
  860. mobile_agent/transport.py +271 -0
  861. mobile_agent/triggers/__init__.py +1 -0
  862. mobile_agent/triggers/actions.py +204 -0
  863. mobile_agent/triggers/model.py +146 -0
  864. mobile_agent/triggers/register.py +29 -0
  865. mobile_agent/triggers/routes.py +101 -0
  866. mobile_agent/triggers/service.py +387 -0
  867. mobile_agent/triggers/store.py +142 -0
  868. mobile_agent/tui/__init__.py +89 -0
  869. mobile_agent/tui/app.py +582 -0
  870. mobile_agent/tui/chrome.py +321 -0
  871. mobile_agent/tui/commands.py +375 -0
  872. mobile_agent/tui/demo_phone.py +369 -0
  873. mobile_agent/tui/images.py +29 -0
  874. mobile_agent/tui/keys.py +64 -0
  875. mobile_agent/tui/prompt.py +195 -0
  876. mobile_agent/tui/render.py +395 -0
  877. mobile_agent/tui/screens.py +180 -0
  878. mobile_agent/tui/session.py +308 -0
  879. mobile_agent/tui/tasks.py +287 -0
  880. mobile_agent/tui/theme.py +118 -0
  881. mobile_agent/tui/widgets.py +272 -0
  882. mobile_agent/update_check.py +213 -0
  883. mobile_agent/usage.py +184 -0
  884. mobile_agent/verify/__init__.py +0 -0
  885. mobile_agent/verify/__main__.py +41 -0
  886. mobile_agent/verify/a11y.py +189 -0
  887. mobile_agent/verify/actions.py +290 -0
  888. mobile_agent/verify/assertions.py +570 -0
  889. mobile_agent/verify/audit.py +312 -0
  890. mobile_agent/verify/business.py +221 -0
  891. mobile_agent/verify/business_run.py +131 -0
  892. mobile_agent/verify/business_state.py +168 -0
  893. mobile_agent/verify/check_schema.py +398 -0
  894. mobile_agent/verify/checks.py +614 -0
  895. mobile_agent/verify/cli.py +423 -0
  896. mobile_agent/verify/conditions.py +483 -0
  897. mobile_agent/verify/crashes.py +321 -0
  898. mobile_agent/verify/device_audit.py +246 -0
  899. mobile_agent/verify/dialogs.py +287 -0
  900. mobile_agent/verify/evidence.py +705 -0
  901. mobile_agent/verify/fixtures.py +305 -0
  902. mobile_agent/verify/flow.py +213 -0
  903. mobile_agent/verify/l10n.py +141 -0
  904. mobile_agent/verify/netcerts.py +67 -0
  905. mobile_agent/verify/netproxy.py +356 -0
  906. mobile_agent/verify/netrun.py +81 -0
  907. mobile_agent/verify/netshim.m +28 -0
  908. mobile_agent/verify/netshim.py +48 -0
  909. mobile_agent/verify/netstubs.py +132 -0
  910. mobile_agent/verify/overlay.py +174 -0
  911. mobile_agent/verify/perf.py +239 -0
  912. mobile_agent/verify/proof.py +192 -0
  913. mobile_agent/verify/replay_admission.py +48 -0
  914. mobile_agent/verify/report.py +952 -0
  915. mobile_agent/verify/run_cleanup.py +67 -0
  916. mobile_agent/verify/run_links.py +48 -0
  917. mobile_agent/verify/run_perf.py +44 -0
  918. mobile_agent/verify/run_secrets.py +39 -0
  919. mobile_agent/verify/runner.py +976 -0
  920. mobile_agent/verify/runs.py +57 -0
  921. mobile_agent/verify/screen_coverage.py +181 -0
  922. mobile_agent/verify/smart.py +106 -0
  923. mobile_agent/verify/snapshot_run.py +114 -0
  924. mobile_agent/verify/snapshots.py +306 -0
  925. mobile_agent/verify/sound.py +335 -0
  926. mobile_agent/verify/source_observation.py +130 -0
  927. mobile_agent/verify/system_surfaces/__init__.py +7 -0
  928. mobile_agent/verify/system_surfaces/play.py +106 -0
  929. mobile_agent/verify/system_surfaces/spec.py +139 -0
  930. mobile_agent/verify/system_surfaces/stage.py +138 -0
  931. mobile_agent/verify/system_surfaces/surfaces.py +121 -0
  932. mobile_agent/verify/tree.py +223 -0
  933. mobile_agent/verify/verdict.py +377 -0
  934. mobile_agent/verify/wire.py +392 -0
  935. mobile_agent/verify/wirestore.py +176 -0
  936. mobile_agent/waiting/__init__.py +1 -0
  937. mobile_agent/waiting/contacts.py +73 -0
  938. mobile_agent/waiting/drafts.py +136 -0
  939. mobile_agent/waiting/job.py +145 -0
  940. mobile_agent/waiting/messages.py +174 -0
  941. mobile_agent/waiting/rank.py +115 -0
  942. mobile_agent/waiting/register.py +26 -0
  943. mobile_agent/watch.py +502 -0
  944. mobile_agent/wda/__init__.py +2 -0
  945. mobile_agent/wda/frame_clock.py +646 -0
  946. mobile_agent/wda/frame_source.py +325 -0
  947. mobile_agent/wda/frame_store.py +115 -0
  948. mobile_agent/wda/gate.py +163 -0
  949. mobile_agent/wda/gestures.py +291 -0
  950. mobile_agent/wda/guards.py +94 -0
  951. mobile_agent/wda/identity.py +55 -0
  952. mobile_agent/wda/observe.py +884 -0
  953. mobile_agent/wda/patches.py +856 -0
  954. mobile_agent/wda/point_gestures.py +150 -0
  955. mobile_agent/wda/source.py +32 -0
  956. mobile_agent/wda/system_dialogs.py +571 -0
  957. mobile_agent/wda/text.py +694 -0
  958. mobile_agent/wda/timeouts.py +77 -0
  959. mobile_agent/wda/video.py +505 -0
  960. mobile_agent/wda/watchdog.py +243 -0
  961. mobile_agent/wireless/__init__.py +15 -0
  962. mobile_agent/wireless/api.py +354 -0
  963. mobile_agent/wireless/cli.py +287 -0
  964. mobile_agent/wireless/devicectl.py +229 -0
  965. mobile_agent/wireless/exposure.py +33 -0
  966. mobile_agent/wireless/mobster-wifi-pair.c +122 -0
  967. mobile_agent/wireless/monitor.py +332 -0
  968. mobile_agent/wireless/network.py +334 -0
  969. mobile_agent/wireless/onboarding.py +293 -0
  970. mobile_agent/wireless/pair.py +124 -0
  971. mobile_agent/wireless/probe.py +322 -0
  972. mobile_agent/wireless/register.py +8 -0
  973. mobile_agent/wireless/relay.py +179 -0
  974. mobile_agent/wireless/result.py +87 -0
  975. mobile_agent/wireless/store.py +85 -0
  976. mobile_agent/wireless/switch.py +77 -0
  977. mobile_agent/wireless/transport.py +118 -0
  978. mobile_agent/wireless/words.py +81 -0
  979. mobile_agent/wireless/xctestrun.py +83 -0
  980. mobile_agent/workflow_tools.py +59 -0
  981. mobile_agent/workflows/__init__.py +2 -0
  982. mobile_agent/workflows/brief.py +201 -0
  983. mobile_agent/workflows/cron.py +110 -0
  984. mobile_agent/workflows/health.py +257 -0
  985. mobile_agent/workflows/history.py +126 -0
  986. mobile_agent/workflows/records.py +442 -0
  987. mobile_agent/workflows/runs.py +1000 -0
  988. mobile_agent/workflows/scheduler.py +134 -0
  989. mobile_agent/workflows/service.py +973 -0
  990. mobile_agent/workflows/starters.py +285 -0
  991. mobile_agent/workflows/triggers.py +248 -0
  992. mobile_agent/xray/__init__.py +1 -0
  993. mobile_agent/xray/app_cli.py +116 -0
  994. mobile_agent/xray/cli.py +21 -0
  995. mobile_agent/xray/crawl.py +754 -0
  996. mobile_agent/xray/diff.py +171 -0
  997. mobile_agent/xray/diff_cli.py +43 -0
  998. mobile_agent/xray/job.py +184 -0
  999. mobile_agent/xray/paywall.py +188 -0
  1000. mobile_agent/xray/policy.py +305 -0
  1001. mobile_agent/xray/register.py +43 -0
  1002. mobile_agent/xray/report.py +283 -0
  1003. mobile_agent/xray/screens.py +117 -0
  1004. mobster_cli-0.4.3.dist-info/METADATA +93 -0
  1005. mobster_cli-0.4.3.dist-info/RECORD +1009 -0
  1006. mobster_cli-0.4.3.dist-info/WHEEL +5 -0
  1007. mobster_cli-0.4.3.dist-info/entry_points.txt +3 -0
  1008. mobster_cli-0.4.3.dist-info/licenses/LICENSE +21 -0
  1009. mobster_cli-0.4.3.dist-info/top_level.txt +1 -0
@@ -0,0 +1,410 @@
1
+ # MobsterBench-iOS
2
+
3
+ A pre-registered benchmark of Mobster's iPhone agent on a real phone: frozen tasks, budgets, a safety monitor and
4
+ graders that never read the agent's own claims. Nothing here runs by itself: every command below is explicit.
5
+
6
+ ## Decision rule (pre-registered, hashed with the suite)
7
+
8
+ For each baseline, per-task success rates are paired: mean(Mobster − baseline) with a 95% bootstrap
9
+ CI over tasks. The result is **better** if the lower bound is above 0, **not worse** if it is above
10
+ −5 pp, and **worse** otherwise. Speed is compared only on tasks both agents solved at least once:
11
+ the median ratio of per-task p50 agent time (Mobster/baseline), with a bootstrap CI. It is
12
+ **faster** if the upper bound is below 1. **State of the art** means better or not-worse accuracy,
13
+ faster, and zero unsafe attempts, against *every* baseline that ran. No baseline is in this tree, so the report
14
+ makes no comparison; the rule stays because it is hashed with the suite.
15
+
16
+ ## The suite
17
+
18
+ `suite.py` defines 68 tasks. They are frozen in `manifest.json` (SHA-256 of tasks, checks, budgets,
19
+ fixture labels and image digests, and the decision rule). `run` refuses a suite whose hash differs.
20
+ To change a task, bump `SUITE_VERSION` and run `freeze --force`, which shows up in the diff.
21
+
22
+ | category | n | mirrors | budget |
23
+ | --- | ---: | --- | --- |
24
+ | navigation | 10 | AndroidLab operation tasks, iOSWorld Settings navigation, MobileAgentBench | 15 steps / 90 s |
25
+ | retrieval (incl. 2 abstention) | 10 | AndroidLab query + infeasible tasks, SPA-Bench single-app | 20 / 120 s |
26
+ | settings_state | 9 | AndroidWorld System* state tasks (read-only variant) | 20 / 120 s |
27
+ | text_entry (search, URL, keypad) | 8 | AndroidWorld typing sub-goals, MobileAgentBench search | 20 / 150 s |
28
+ | multi_app | 6 | SPA-Bench cross-app, AndroidWorld information transfer | 35 / 300 s |
29
+ | web (incl. 1 abstention) | 10 | WebArena/Mind2Web-style information seeking in mobile Safari | 25 / 180 s |
30
+ | scroll (off-screen targets) | 7 | AndroidLens long-horizon scrolling, iOSWorld scroll-to-target | 25 / 180 s |
31
+ | visual (dry run) | 8 | VisualWebArena visual predicates, AndroidWorld batch tasks | 80 / 480 s |
32
+
33
+ Every task has:
34
+
35
+ - a start state that the harness resets to (relaunch, then pop to root, or open a start URL);
36
+ - an **independent oracle**, from one of two sources:
37
+ - the harness's own probe reads the device over its own WDA connection (foreground app,
38
+ navigation title, on-screen text);
39
+ - the answer is compared with ground truth fixed before the run;
40
+ - a **safety class**, one of:
41
+ - `read_only`;
42
+ - `read_only_history`: Safari or Maps history only;
43
+ - `reversible_reset`: a search field or the Calculator display, cleared by relaunch;
44
+ - step and time budgets.
45
+
46
+ No task sends, buys, posts, deletes, likes or calls anything, and none changes account, security
47
+ or connectivity settings. `test_suite.py` checks every goal for this.
48
+
49
+ The oracles never read an agent's evidence or citations. Only Mobster produces citations, so
50
+ grading them would bias the comparison.
51
+
52
+ ### Ground truth
53
+
54
+ There are four kinds of ground truth:
55
+
56
+ - `Literal`: stable public facts written in the task.
57
+ - `Captured`: Bluetooth, Wi-Fi and Airplane Mode state, read from the Settings root screen during
58
+ each attempt's reset. They may change between days.
59
+ - `Fixture`: records and labelled images that you install.
60
+ - `Truth`: per-device values in `truth/<device>.json`.
61
+
62
+ `Truth` values start from seeds. Some were read on the phone on 2026-09-22 (iOS version, model
63
+ number, model name, capacity). Others are public facts. iOS 26 screen titles are marked
64
+ **assumed** until `capture-truth` confirms them. `capture-truth` is the harness's read-only
65
+ navigator: it relaunches an app, taps rows by their exact accessibility label, and never taps a
66
+ switch. `dry-plan` lists every missing or assumed key. A task whose truth is missing is
67
+ **ungraded**, never passed.
68
+
69
+ ## Fixtures (set up once, by hand)
70
+
71
+ ```
72
+ mobile_agent/.venv/bin/python -m mobile_agent.bench fixtures --out ~/Desktop/mobsterbench-fixtures
73
+ ```
74
+
75
+ This writes three things:
76
+
77
+ - `copy-to-phone/MobsterBench/{dogs12,receipts12,sunglasses12,eyes8}`: 44 CC0 or public-domain
78
+ images from `evals/vision`, renamed so that a filename never reveals its label.
79
+ - `SETUP.txt`: the setup instructions.
80
+ - `labels-do-not-copy.json`: the answer key. It stays on the Mac.
81
+
82
+ To set up the phone:
83
+
84
+ 1. Copy `MobsterBench` into Files › On My iPhone, by AirDrop or through Finder.
85
+ 2. In Photos, create the album **MobsterBench Dogs** from the dogs12 images, and the album
86
+ **MobsterBench Receipts** from the receipts12 images.
87
+ 3. Create these records by hand. All of the content is fictional:
88
+ - **Notes:** a note whose lines are `MobsterBench Note`, `Locker code: 4817`, and
89
+ `https://en.m.wikipedia.org/wiki/Alan_Turing`.
90
+ - **Contacts:** Bench Tester, company *Mobster Bench Labs*, mobile `(555) 010-4477`, city Cupertino.
91
+ - **Reminders:** a list named *MobsterBench* with three incomplete reminders: *Water the plants*,
92
+ *Return library books*, and *Pick up dry cleaning*.
93
+ - **Calendar:** an event *MobsterBench Review* on 15 Oct 2026, 14:00–15:00, location *Room 42*.
94
+ 4. Verify the setup with `dry-plan --probe --verify-fixtures`, which is read-only. With
95
+ `run --verify-fixtures`, any task whose fixture is missing is **skipped** rather than failed.
96
+
97
+ The visual tasks are dry runs. The agent judges images and must not act on them. The graders are:
98
+
99
+ - **Exact file sets**, with item precision and recall reported (dogs, receipts, sunglasses).
100
+ - **Per-item labels**, where `unsure` is the correct answer for 4 of the 8 eye images.
101
+ - **Album counts.**
102
+ - **One single-image abstention:** the eyes cannot be seen, so the correct answer is "cannot tell".
103
+
104
+ ## Agents under test
105
+
106
+ Every agent runs with the same controls:
107
+
108
+ - **Inputs:** the goal text, and the answer field names as Mobster's `output_schema`.
109
+ - **Budgets:** the task's step and time budgets, which are hard. A late answer counts as a timeout.
110
+ - **Safety:** the safety monitor (`safety.py`) checks every action *before* dispatch. Refused actions are never
111
+ sent, the run stops, and the attempt fails with the event recorded.
112
+ - **Timing:** agent time excludes harness-only safety reads (`monitor_ms`). Resets and grading are never timed.
113
+
114
+ | agent | what it is |
115
+ | --- | --- |
116
+ | `mobster-smart` | Mobster's agent (`frontier.FrontierAgent`), in process, composed by `engines.build_frontier` as the app composes it: device lease, WDA session from `/status`, FrameClock attached in `on` mode, the task's apps, and its answer fields as `output_schema`. The verdict is about this arm. Its other models are under "Smart, the held-out tranche and A/Bs" below. |
117
+
118
+ **Known gap:** Mobster can fail the Calculator tasks because the display is drawn and not in the AX tree. These
119
+ tasks are tagged `known_gap_mobster_ax_drawn_display`.
120
+
121
+ ## Metrics (`report.py`)
122
+
123
+ - **Success rate:**
124
+ - A Wilson 95% CI over attempts.
125
+ - A task-level bootstrap CI, because repeats of a task are not independent.
126
+ - pass^1 and pass^3 (as in tau-bench).
127
+ - Flaky tasks: tasks whose repeats disagree.
128
+ - The rate per category.
129
+ - **Time:**
130
+ - Wall-clock agent time, p50 and p90 per task.
131
+ - Per step: agent time divided by decision steps.
132
+ - Time to first action.
133
+ - **Model calls and cost:**
134
+ - Model calls per task.
135
+ - Dollars per task and in total, from Mobster's own telemetry.
136
+ - Unpriced calls are counted and never treated as zero.
137
+ - **Safety:** unsafe or risky attempts that were blocked, and unintended actions (both must be 0).
138
+ - **Abstention:** whether abstentions were correct.
139
+ - **Visual items:** TP, FP and FN, with precision and recall, and correct "unsure" answers.
140
+ - **Accounting:** skipped, infra and ungraded attempts are counted separately and never enter the
141
+ rates.
142
+
143
+ ## Runner hygiene and device rules (`runner.py`, `phone.py`)
144
+
145
+ Before each attempt, the runner does four things:
146
+
147
+ - **Health check** (GET only): WDA `/status` must have a session, and `/wda/locked` must be false.
148
+ A locked phone halts the run, and so do 2 consecutive infrastructure failures.
149
+ - **Yield:** it waits while the Mobster app on :8765 has a queued or running task. It only sends
150
+ GET requests there and never POSTs to :8765.
151
+ - **Lease:** it takes the same exclusive device lease `serve` uses for resets and grading.
152
+ - **Reset:** it resets and verifies the start app.
153
+
154
+ These rules apply throughout:
155
+
156
+ - **Timeouts:** short everywhere (health 3 s, AX read 6–8 s), because WDA serves one
157
+ request at a time.
158
+ - **Session:** the WDA session always comes from `/status`, never a new one, and the WDA runner is
159
+ never restarted.
160
+ - **Order:** tasks are shuffled per repeat, and agents per task, from a seed stored in `plan.json`.
161
+ - **Records:** everything goes to `records.jsonl`, one fsynced line per attempt. `--resume DIR`
162
+ continues and retries infrastructure failures. No GUI window is ever opened.
163
+
164
+ ## Commands
165
+
166
+ ```
167
+ PY=mobile_agent/.venv/bin/python
168
+
169
+ # Offline checks: suite hash, truth coverage, fixtures, agents, runtime/cost estimate
170
+ $PY -m mobile_agent.bench dry-plan
171
+
172
+ # Once, with the phone free and unlocked (read-only navigation by the harness)
173
+ $PY -m mobile_agent.bench capture-truth --wda-url http://127.0.0.1:8100
174
+ $PY -m mobile_agent.bench dry-plan --probe --verify-fixtures
175
+
176
+ # Smoke (2 read-only tasks x each agent, 1 repeat)
177
+ $PY -m mobile_agent.bench run --only web.heading,nav.accessibility --repeats 1 \
178
+ --out research/bench-runs/smoke-$(date +%F)
179
+
180
+ # The full benchmark (all agents, 3 repeats), then the report
181
+ $PY -m mobile_agent.bench run --repeats 3 --verify-fixtures --out research/bench-runs/full-$(date +%F)
182
+ $PY -m mobile_agent.bench run --resume research/bench-runs/full-YYYY-MM-DD # after any halt
183
+ $PY -m mobile_agent.bench report --run research/bench-runs/full-YYYY-MM-DD # -> research/bench-<date>.md
184
+ ```
185
+
186
+ ## Smart, the held-out tranche and A/Bs (October 2026)
187
+
188
+ Smart runs on the bench as `mobster-smart` (Sonnet 5.5 on the API), `mobster-smart-haiku`, `mobster-smart-luna`
189
+ (gpt-6-luna), `mobster-smart-sol` (gpt-6.1-sol), `mobster-smart-codex` (gpt-6.1-sol through the Codex CLI's ChatGPT
190
+ sign-in, no per-call cost) and `mobster-smart-cc` (`claude -p`; seconds of process start per call, so not for
191
+ timing). Every way Smart reaches the phone passes the safety monitor first, including point taps, long presses and
192
+ text writes.
193
+
194
+ | Suite (`--suite`) | What |
195
+ |---|---|
196
+ | `heldout` | H1: 16 tasks (6 short, 4 retrieval, 4 multi-app, 2 text entry), frozen 2026-10-09 in `heldout-manifest.json` and never tuned on |
197
+ | `training` | H1's siblings (same apps and shapes, other values), for anything that learns |
198
+ | `combo` | 7 varied tasks for reading engine combinations by hand |
199
+ | `hard` | 7 long tasks (four apps chained, web lookups, library counts) |
200
+
201
+ ```
202
+ $PY -m mobile_agent.bench run --suite heldout --agents mobster-smart,mobster-smart-haiku --order abba \
203
+ --repeats 2 --no-yield --secrets-env ~/mobster-work/secrets/bench.env --env-file mobile_agent/.env --out DIR
204
+ $PY -m mobile_agent.bench.ab DIR # the paired verdict: success CI, short-task time ratio, safety
205
+ $PY -m mobile_agent.bench.trace_view DIR # every step of every attempt, with latency and cost
206
+ ```
207
+
208
+ `--order abba` runs each task A B B A (the leading arm alternates by task). `--secrets-env` loads a file first, into
209
+ the bench process only. A reset clears Calculator, which keeps its last result across a relaunch.
210
+
211
+ Offline gates on recorded Smart turns: `decide_gate.py` (decision models choosing a mark), `llm_units.py` (each LLM
212
+ re-asked a recorded turn: agreement, latency, $).
213
+
214
+ ## MobsterBench Real: the requests customers make (`real/`)
215
+
216
+ 48 tasks paying users ask, on the owner's iPhone, in real apps (Messages, Mail, Calendar, Reminders, Notes, Photos,
217
+ Maps, Safari, Settings, Instagram, App Store, Wallet, Weather, Clock, Health), started on the Home Screen. The
218
+ pre-registration, with the metrics, the ABBA protocol and the outside-agent comparison, is
219
+ [`docs/realbench.md`](../docs/realbench.md); the hash is in `real-manifest.json`.
220
+
221
+ - **Nothing leaves the phone.** A send, reply, like, follow, comment, call, delete or install ends at Mobster's approval
222
+ card, which the bench records and declines. `real/policy.py` refuses every commit control, money app and setting the
223
+ task doesn't name before it reaches the phone.
224
+ - **Writes go into bench containers** that the harness restores after each attempt (`real/harness.py`): the "Mobster
225
+ Bench Scratchpad" note, the "Mobster Bench Errands" list, a timer, Dark Mode and Low Power Mode.
226
+ - **Keys that change are read by the harness** at the attempt's start or right after it (`real/reads.py`): the latest
227
+ text, the temperature, the battery, the note's text. Code grades every task (`real/checks.py`).
228
+
229
+ ```
230
+ PY=mobile_agent/.venv/bin/python
231
+ export MOBSTER_BENCH_UDID=<UDID> # the bench iPhone, the only device read
232
+ $PY -m mobile_agent.bench.real list -v # the tasks, counts and grader coverage
233
+ $PY -m mobile_agent.bench.real survey --out ~/mobster-work/realbench/survey # read-only: screens and keys
234
+ $PY -m mobile_agent.bench.real containers [--restore] # check or set the bench containers
235
+ $PY -m mobile_agent.bench.real run --secrets-env ~/mobster-work/secrets/bench.env \
236
+ --out ~/mobster-work/realbench/runs/NAME # each task once, $5 spend cap
237
+ $PY -m mobile_agent.bench.real run --agents mobster-smart,mobster-smart-haiku --order abba --repeats 2 --out DIR
238
+ $PY -m mobile_agent.bench.real report --run DIR
239
+ ```
240
+
241
+ `survey` and `run` read the phone's apps from the iPhone `--udid` or `MOBSTER_BENCH_UDID` names, and from no
242
+ other: they never list the attached devices. Without a UDID they stop before the phone's apps are read, unless the
243
+ output folder already holds `inventory.json`.
244
+
245
+ Runs, surveys and captured keys hold what the phone showed: keep them under `~/mobster-work/realbench`, never in git.
246
+
247
+ ## The tuning loop on iOSWorld (`tuning.py`, `tuning_analysis.py`)
248
+
249
+ Every engine change goes through one loop: a hypothesis from measured failures, an offline check, a paired A/B on
250
+ the iOSWorld simulators, then a promotion or a recorded loss. iOSWorld's 133 tasks are split once into dev (every
251
+ task an earlier build ran), val (never run; promotes a change) and test (never run, never looked at; opened only
252
+ for a public claim). The splits file carries its own SHA-256, and `run` refuses a file that no longer matches it
253
+ and refuses test tasks outside `--split test`.
254
+
255
+ ```
256
+ $PY -m mobile_agent.bench.tuning run --batch DIR --arm A=WORKTREE_MAIN --arm B=WORKTREE_CHANGE --repo ../iOSWorld \
257
+ --sims UDID:8200:9200,UDID:8201:9201,... --splits splits.json --split dev_core --runs 2 \
258
+ --env-file bench.env --model claude-sonnet-5-5 --xctestrun WDA.xctestrun --shutdown --ledger ledger.jsonl
259
+ $PY -m mobile_agent.bench.tuning judge --batch DIR --repo ../iOSWorld --env-file bench.env --ledger ledger.jsonl
260
+ $PY -m mobile_agent.bench.tuning trace --batch DIR # trace.jsonl per task: one line per model turn
261
+ $PY -m mobile_agent.bench.tuning label --batch DIR --env-file bench.env # root cause of each failed run
262
+ $PY -m mobile_agent.bench.tuning scoreboard --batch DIR --labels DIR/labels.jsonl --ledger ledger.jsonl
263
+ $PY -m mobile_agent.bench.tuning counterfactual --runs DIR --variant pkg.mod:fn --n 40 --out OUT
264
+ ```
265
+
266
+ - **Runs.** Each task runs A B B A, and its attempts are dealt to the simulators with a rotation, so every
267
+ simulator runs every arm equally often. A batch holds one run folder per arm and run (`A1 B1 B2 A2`), so
268
+ `iosworld compare --a DIR/A* --b DIR/B*` reads it unchanged. An A/A is the same worktree as both arms.
269
+ - **No driver outlives its run.** Each task is a child in its own session with a hard timeout (1,200 s; the agent
270
+ stops itself at 900 s). A reaper in its own session watches the runner; when the runner ends, however it ends, the
271
+ reaper kills any child left, stops the batch's WDA runners and, with `--shutdown`, shuts the simulators down.
272
+ - **WDA session.** Each task starts a new session the way the app does (no quiescence wait), so the bench measures
273
+ the session users run. `MOBSTER_BENCH_SESSION=legacy` brings back the plain session every run before 10 Oct had.
274
+ - **Reset.** `MOBSTER_BENCH_RESET=restore` (with `MOBSTER_BENCH_CHECKPOINTS=DIR`) makes each task's clean slate by
275
+ restoring a checkpoint of the freshly seeded apps (`bench/evals/checkpoint.py`, about 4.5 s, checked by digest)
276
+ instead of iOSWorld's wipe-and-reseed (43-66 s). Each simulator's seed is made once, from iOSWorld's own reset; a
277
+ restore whose digest differs falls back to iOSWorld's reset. The default stays iOSWorld's reset until an A/A shows
278
+ the two equivalent.
279
+ - **Per-turn timing.** With `MOBSTER_BENCH_TTFT=on` (the runner's default), `bench/stream_timing.py` sends each Claude
280
+ call's identical request streamed and rebuilds the same reply, so each turn records its time to first token
281
+ beside its tokens. It is a measurement for the benchmark; the app keeps the unstreamed call. Both arms run it alike.
282
+ - **The trace** has per turn: the screen's and the screenshot's hashes, the app, the model and route, input, output
283
+ and cached tokens, call latency, time to first token and generation time, the actions with refresh, exec and settle
284
+ times, refusals, chunk stops and the contract items' states. Per task: the official pass, the rubric and each
285
+ criterion, status, answer, $, calls and the time buckets.
286
+ - **The labeller** reads each failed trace and returns one root cause from a fixed taxonomy (perception or grounding,
287
+ wrong plan, lost cross-app state, premature DONE, step budget, loop or stall, gave up, infra, judge miss), the first
288
+ wrong step and a one-line counterfactual. Spot-check its labels by hand before trusting the map.
289
+ - **Counterfactuals** re-ask recorded turns with a variant (`fn(messages, schema, turn) -> (messages, schema)`) and
290
+ report agreement with the recorded first action (also on passing runs only), output tokens, latency and time to
291
+ first token. Kill an idea here when it is cheap to kill.
292
+ - **The scoreboard** shows per arm the official pass (and reweighted to the 133-task mix), rubric, s/task p50 and
293
+ p90, calls, output tokens per turn, turn latency, time to first token, $/task, false DONEs and WDA crashes; the
294
+ same by category; the paired difference with bootstrap CIs and their half-widths per category; the failure map;
295
+ and the trend across builds from the ledger.
296
+
297
+ ## Cheap evals (`evals/`)
298
+
299
+ Most engine ideas should live or die before a paired A/B, which costs about $20 and an hour. `evals/` holds the
300
+ cheaper levels, each run on recorded data. None of them touches a device.
301
+
302
+ L0 is trace analytics, $0 and under a minute over every recorded run:
303
+
304
+ ```
305
+ $PY -m mobile_agent.bench.evals.l0 --runs ~/mobster-work/tuning/batches research/iosworld-runs \
306
+ --suite iosworld --app-groups groups.json --labels labels.jsonl --out DIR
307
+ ```
308
+
309
+ It writes `DIR/l0.md` and `DIR/l0.json`:
310
+
311
+ - the mechanisms ranked by seconds: round trips, repeated actions, unchanged actions, refusals, DONE deferrals,
312
+ DONE-only last turns, re-read screens, typing and settle time, and turns beyond the shortest passing run of the
313
+ same task;
314
+ - where the seconds go, without overlap;
315
+ - time sinks by step type and by app group;
316
+ - where each failing run first leaves the passing path.
317
+
318
+ The divergence is the first milestone the failing run never reached. A milestone is an action every passing run of
319
+ the task took; scrolls and dismissals don't count. `groups.json` maps app names to groups and stays outside the
320
+ repository, with the runs.
321
+
322
+ The same table now carries a time-to-first-token breakdown when the runs have streamed timing:
323
+ - how often the cache hit;
324
+ - how TTFT scales with uncached tokens;
325
+ - the turns whose output tokens show hidden thinking.
326
+
327
+ L1 is component and turn evals on frozen sets, cents a run. A set is built once from recorded runs and frozen as
328
+ `<root>/<name>/<version>/`: `items.jsonl`, the screenshots it uses, and a `MANIFEST.json` whose sha256 covers both. The
329
+ loader refuses a set whose files no longer match it. Tasks are split into a tune half and a report half by one
330
+ seeded map shared by every set. A task in val or test never enters a set. The sets hold task text and screens, so
331
+ they stay outside the repository.
332
+
333
+ ```
334
+ $PY -m mobile_agent.bench.evals.build done --runs BATCHES --batches aa1,ac1 --splits splits.json \
335
+ --labels labels.jsonl --root SETS --version v2
336
+ $PY -m mobile_agent.bench.evals.l1 SETS/done/v2 --system llm:claude-haiku-5-5 --half report \
337
+ --keys bench.env --ledger spend.jsonl --cap 15 --out DIR
338
+ ```
339
+
340
+ | Set | Item | Label |
341
+ |---|---|---|
342
+ | `done` | a run's ending at its DONE: contract, notes, answer, each step's new rows, list reads and effects | the judge's verdict, the unsatisfied criteria, the verdict with labelled judge misses corrected |
343
+ | `value` | a screen's rows and screenshot, and a REPORT question | the value the agent found on that screen in a passing run, or none for another screen |
344
+ | `golden` | a recorded prompt and screenshot | the next action, plus other passing runs' actions on that screen; at a failing run's divergence, also its wrong action |
345
+ | `contract` | a request and its apps | the judge's rubric criteria, each with how often judged runs failed it |
346
+ | `commit` | a commit-class control the guard decided on (refused, tapped, on a read screen), with the contracts compiled for its task | whether the request asks for that act (`commit_requested`), and whether a run failed because the guard refused it |
347
+ | `grounding` | a screen's rows and screenshot, and an intent made from the tree (a label, the third row of a list, the button beside a label, a long label's first words) or the planner's own words for a tap | the element |
348
+
349
+ The systems `l1` runs:
350
+
351
+ - `done`: `accept_all` (the engine as it is), `file:` (an offline gate's results), `llm:<model>` (a reference completion check), and `completion_check:<model>`.
352
+ - `value`: `llm:<model>` and `jev`.
353
+ - `golden`: `llm:<model>` with one observation arm:
354
+ - `+noimage`: rows only;
355
+ - no suffix: rows and the screenshot;
356
+ - `+marks`: rows and the screenshot with each row's box and id drawn;
357
+ - `+marksonly`: the marked screenshot alone.
358
+
359
+ Add `+nothink` for any arm. `decide:jev` and `decide:openai` pick the next tap with a decision model.
360
+ - `contract`: `recorded`, and `compile:<model>` with `+itemize` or `+selfcheck`. A matcher model maps the items onto the criteria.
361
+ - `grounding`: `llm:<model>` (rows only, `+image`, `+marks`, `+marksonly`), `decide:jev`, and `decide:openai` with the same arms.
362
+ - `commit`: `family:current` (this checkout's guard rule) and `family:old` (the rule before #224), with no model call.
363
+
364
+ Each run prints accuracy, latency p50 and p90, and $. It writes its rows, and `--rescore ROWS` scores old rows
365
+ against a set again with no calls. The ledger refuses a call once the spend recorded in it reaches `--cap`.
366
+
367
+ The pairwise step judge (`evals/pairwise.py`) turns a golden run into a preference win rate. It keeps only the
368
+ turns where the candidate's first action differs from every acceptable recorded action. On each one, a judge sees the
369
+ request, the progress and the screen, and is asked twice with the actions swapped. A verdict counts only when both
370
+ orders agree; otherwise it's a tie. `--calibrate synthetic` asks the judge about pairs whose answer is
371
+ known: the recorded action against a tap on a random other element, or against DONE mid-task.
372
+
373
+ ```
374
+ $PY -m mobile_agent.bench.evals.pairwise SETS/golden/v2 --rows DIR/golden-v2-report-llm_claude-haiku-5-5.jsonl \
375
+ --judge claude-sonnet-5-5 --keys bench.env --ledger spend.jsonl --cap 15 --out DIR
376
+ ```
377
+
378
+ L2 starts offline with `evals/irt.py`, a 2PL item response model fitted over every judged iOSWorld run. Each engine
379
+ configuration is a respondent and each task an item. It ranks tasks by Fisher information at the tuned engine's
380
+ ability, and the top k are the informative subset for a fast directional A/B. `--pairs` backtests the subset on
381
+ past paired experiments: for each one it refits without that experiment, then compares the subset's delta with the
382
+ full delta, and random subsets give the baseline.
383
+
384
+ ```
385
+ $PY -m mobile_agent.bench.evals.irt --runs BATCHES research/iosworld-runs --anchor ac1:A --tasks DEV_CORE \
386
+ --pairs pairs.json --fraction 0.5 --out DIR
387
+ ```
388
+
389
+ The finishing-turn set (`finish`) re-asks each DONE ending's final turn. It scores a model or effort level by how
390
+ often it finishes when the run was done and when it wasn't.
391
+
392
+ `evals/proxy.py` checks whether the cheap evals predict the expensive one. Keep one JSONL line per hypothesis that
393
+ reached a paired A/B or was stopped before one: its deltas on each proxy, and its L3 result. With four or more
394
+ L3 results, it prints Spearman's rank correlation between each proxy and the outcome, and how often their signs
395
+ agree.
396
+
397
+ ```
398
+ $PY -m mobile_agent.bench.evals.proxy validity.jsonl --outcome pass_delta
399
+ ```
400
+
401
+ L2 checkpoints (`evals/checkpoint.py`) snapshot the iOSWorld apps' data on a simulator. A snapshot covers each app's
402
+ data-container folders, the ones iOSWorld's reset wipes, and the shared app-group containers. Copies are APFS
403
+ clones (`cp -c`), and a digest of the persistent folders checks every restore against its save. Restoring the
404
+ freshly seeded checkpoint is a reset. Restoring one taken just before a task's hard part starts a run at the crux.
405
+ It refuses any simulator whose name doesn't start with "Eval Lab", so the tuning loop's simulators are never touched.
406
+
407
+ ```
408
+ $PY -m mobile_agent.bench.evals.checkpoint save --udid UDID --repo BOOTSTRAP_DIR --name seed
409
+ $PY -m mobile_agent.bench.evals.checkpoint restore --udid UDID --repo BOOTSTRAP_DIR --name seed
410
+ ```
File without changes