swipium 1.5.0 → 2.0.1

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 (498) hide show
  1. package/CHANGELOG.md +183 -0
  2. package/README.md +173 -280
  3. package/THREAT_MODEL.md +223 -47
  4. package/dist/appMap/automationLink.js +30 -27
  5. package/dist/appMap/automationLink.js.map +1 -1
  6. package/dist/appMap/build.js +47 -21
  7. package/dist/appMap/build.js.map +1 -1
  8. package/dist/appMap/codeIndex.js +2 -2
  9. package/dist/appMap/codeIndex.js.map +1 -1
  10. package/dist/appMap/featureIndex.js +3 -3
  11. package/dist/appMap/featureIndex.js.map +1 -1
  12. package/dist/appMap/featureModel.js +2 -2
  13. package/dist/appMap/featureModel.js.map +1 -1
  14. package/dist/appMap/firstRunApply.js +2 -2
  15. package/dist/appMap/firstRunApply.js.map +1 -1
  16. package/dist/appMap/issues.js +10 -10
  17. package/dist/appMap/issues.js.map +1 -1
  18. package/dist/appMap/migrations.js +5 -5
  19. package/dist/appMap/migrations.js.map +1 -1
  20. package/dist/appMap/prelaunch.js +2 -2
  21. package/dist/appMap/prelaunch.js.map +1 -1
  22. package/dist/appMap/projectRegistry.js +77 -11
  23. package/dist/appMap/projectRegistry.js.map +1 -1
  24. package/dist/appMap/provenance.js +2 -2
  25. package/dist/appMap/provenance.js.map +1 -1
  26. package/dist/appMap/query.js +2 -2
  27. package/dist/appMap/query.js.map +1 -1
  28. package/dist/appMap/runtimeMerge.js +3 -3
  29. package/dist/appMap/runtimeMerge.js.map +1 -1
  30. package/dist/appMap/schema.js +1 -1
  31. package/dist/appMap/schema.js.map +1 -1
  32. package/dist/appMap/screenMatch.js +1 -1
  33. package/dist/appMap/screenMatch.js.map +1 -1
  34. package/dist/appMap/staticScan.js +17 -17
  35. package/dist/appMap/staticScan.js.map +1 -1
  36. package/dist/appMap/store.js +55 -7
  37. package/dist/appMap/store.js.map +1 -1
  38. package/dist/appMap/tsAstScan.js +3 -3
  39. package/dist/appMap/tsAstScan.js.map +1 -1
  40. package/dist/artifacts/bundletool.js +5 -5
  41. package/dist/artifacts/bundletool.js.map +1 -1
  42. package/dist/artifacts/resolve.js +10 -10
  43. package/dist/artifacts/resolve.js.map +1 -1
  44. package/dist/automation/capabilities.js +3 -3
  45. package/dist/automation/capabilities.js.map +1 -1
  46. package/dist/automation/gestures.js +1 -1
  47. package/dist/automation/gestures.js.map +1 -1
  48. package/dist/automation/plan.js +7 -7
  49. package/dist/automation/plan.js.map +1 -1
  50. package/dist/automation/report.js +3 -3
  51. package/dist/automation/report.js.map +1 -1
  52. package/dist/automation/selectors.js +14 -25
  53. package/dist/automation/selectors.js.map +1 -1
  54. package/dist/automation/types.js +1 -1
  55. package/dist/automation/types.js.map +1 -1
  56. package/dist/automation/waits.js +5 -5
  57. package/dist/automation/waits.js.map +1 -1
  58. package/dist/automation/webview.js +2 -2
  59. package/dist/automation/webview.js.map +1 -1
  60. package/dist/automationGen/appiumModel.js +13 -7
  61. package/dist/automationGen/appiumModel.js.map +1 -1
  62. package/dist/automationGen/ciEmitter.js +5 -5
  63. package/dist/automationGen/ciEmitter.js.map +1 -1
  64. package/dist/automationGen/identifiers.js +224 -0
  65. package/dist/automationGen/identifiers.js.map +1 -0
  66. package/dist/automationGen/jsEmitter.js +265 -106
  67. package/dist/automationGen/jsEmitter.js.map +1 -1
  68. package/dist/automationGen/packagePatch.js +2 -2
  69. package/dist/automationGen/packagePatch.js.map +1 -1
  70. package/dist/automationGen/platformResolve.js +36 -0
  71. package/dist/automationGen/platformResolve.js.map +1 -0
  72. package/dist/automationGen/projectProfile.js +71 -26
  73. package/dist/automationGen/projectProfile.js.map +1 -1
  74. package/dist/automationGen/pythonEmitter.js +276 -105
  75. package/dist/automationGen/pythonEmitter.js.map +1 -1
  76. package/dist/automationGen/readmeEmitter.js +7 -6
  77. package/dist/automationGen/readmeEmitter.js.map +1 -1
  78. package/dist/{tools/automationGenerate.js → automationGen/run.js} +72 -113
  79. package/dist/automationGen/run.js.map +1 -0
  80. package/dist/automationGen/suitePlan.js +6 -4
  81. package/dist/automationGen/suitePlan.js.map +1 -1
  82. package/dist/automationGen/validation.js +20 -8
  83. package/dist/automationGen/validation.js.map +1 -1
  84. package/dist/build/parseBuildLog.js +2 -2
  85. package/dist/build/parseBuildLog.js.map +1 -1
  86. package/dist/build/plan.js +7 -7
  87. package/dist/build/plan.js.map +1 -1
  88. package/dist/ci/preflight.js +13 -4
  89. package/dist/ci/preflight.js.map +1 -1
  90. package/dist/cli/gc.js +74 -0
  91. package/dist/cli/gc.js.map +1 -0
  92. package/dist/cli/init.js +217 -26
  93. package/dist/cli/init.js.map +1 -1
  94. package/dist/cli/main.js +50 -0
  95. package/dist/cli/main.js.map +1 -0
  96. package/dist/cli/report.js +218 -0
  97. package/dist/cli/report.js.map +1 -0
  98. package/dist/cli/scan.js +35 -14
  99. package/dist/cli/scan.js.map +1 -1
  100. package/dist/cli/suite.js +6 -6
  101. package/dist/cli/suite.js.map +1 -1
  102. package/dist/cli/verify.js +7 -7
  103. package/dist/cli/verify.js.map +1 -1
  104. package/dist/consent/consent.js +162 -5
  105. package/dist/consent/consent.js.map +1 -1
  106. package/dist/context/detect.js +45 -14
  107. package/dist/context/detect.js.map +1 -1
  108. package/dist/context/findApps.js +6 -6
  109. package/dist/context/findApps.js.map +1 -1
  110. package/dist/context/projectRoot.js +174 -19
  111. package/dist/context/projectRoot.js.map +1 -1
  112. package/dist/context/scan.js +1 -1
  113. package/dist/context/scan.js.map +1 -1
  114. package/dist/core/capabilityGroups.js +90 -0
  115. package/dist/core/capabilityGroups.js.map +1 -0
  116. package/dist/core/target.js +3 -3
  117. package/dist/core/target.js.map +1 -1
  118. package/dist/core/targetPlan.js +65 -62
  119. package/dist/core/targetPlan.js.map +1 -1
  120. package/dist/drivers/DirectDriver.js +300 -36
  121. package/dist/drivers/DirectDriver.js.map +1 -1
  122. package/dist/drivers/SimctlDriver.js +120 -7
  123. package/dist/drivers/SimctlDriver.js.map +1 -1
  124. package/dist/drivers/WdaDriver.js +350 -50
  125. package/dist/drivers/WdaDriver.js.map +1 -1
  126. package/dist/explore/candidates.js +2 -2
  127. package/dist/explore/candidates.js.map +1 -1
  128. package/dist/explore/graph.js +5 -5
  129. package/dist/explore/graph.js.map +1 -1
  130. package/dist/explore/policy.js +5 -5
  131. package/dist/explore/policy.js.map +1 -1
  132. package/dist/explore/runner.js +301 -284
  133. package/dist/explore/runner.js.map +1 -1
  134. package/dist/explore/signatures.js +1 -1
  135. package/dist/featureTesting/executionBootstrap.js +29 -30
  136. package/dist/featureTesting/executionBootstrap.js.map +1 -1
  137. package/dist/featureTesting/featureMap.js +2 -2
  138. package/dist/featureTesting/featureMap.js.map +1 -1
  139. package/dist/featureTesting/featureScope.js +12 -12
  140. package/dist/featureTesting/featureScope.js.map +1 -1
  141. package/dist/featureTesting/mapFeatureScope.js +7 -7
  142. package/dist/featureTesting/mapFeatureScope.js.map +1 -1
  143. package/dist/featureTesting/objectiveModel.js +10 -10
  144. package/dist/featureTesting/objectiveModel.js.map +1 -1
  145. package/dist/featureTesting/resultMerge.js +6 -6
  146. package/dist/featureTesting/resultMerge.js.map +1 -1
  147. package/dist/featureTesting/sources.js +4 -4
  148. package/dist/featureTesting/sources.js.map +1 -1
  149. package/dist/featureTesting/suiteBridge.js +1 -1
  150. package/dist/featureTesting/suiteBridge.js.map +1 -1
  151. package/dist/featureTesting/synonyms.js +1 -1
  152. package/dist/featureTesting/synonyms.js.map +1 -1
  153. package/dist/featureTesting/testCaseFactory.js +11 -11
  154. package/dist/featureTesting/testCaseFactory.js.map +1 -1
  155. package/dist/featureTesting/testPlan.js +3 -3
  156. package/dist/featureTesting/testPlan.js.map +1 -1
  157. package/dist/firstRun/authStateMachine.js +1 -1
  158. package/dist/firstRun/authStateMachine.js.map +1 -1
  159. package/dist/firstRun/classifyScreen.js +5 -5
  160. package/dist/firstRun/classifyScreen.js.map +1 -1
  161. package/dist/firstRun/firstRunPlanner.js +11 -11
  162. package/dist/firstRun/firstRunPlanner.js.map +1 -1
  163. package/dist/firstRun/firstRunRunner.js +8 -8
  164. package/dist/firstRun/firstRunRunner.js.map +1 -1
  165. package/dist/firstRun/generatedDataPolicy.js +9 -9
  166. package/dist/firstRun/generatedDataPolicy.js.map +1 -1
  167. package/dist/firstRun/inputPlanner.js +5 -5
  168. package/dist/firstRun/inputPlanner.js.map +1 -1
  169. package/dist/firstRun/onboardingStateMachine.js +1 -1
  170. package/dist/firstRun/onboardingStateMachine.js.map +1 -1
  171. package/dist/firstRun/paywallPolicy.js +3 -3
  172. package/dist/firstRun/paywallPolicy.js.map +1 -1
  173. package/dist/firstRun/types.js +1 -1
  174. package/dist/firstRun/types.js.map +1 -1
  175. package/dist/fixtures/catalog.js +33 -3
  176. package/dist/fixtures/catalog.js.map +1 -1
  177. package/dist/fixtures/load.js +50 -0
  178. package/dist/fixtures/load.js.map +1 -0
  179. package/dist/flows/discover.js +2 -2
  180. package/dist/flows/discover.js.map +1 -1
  181. package/dist/flows/generate.js +20 -10
  182. package/dist/flows/generate.js.map +1 -1
  183. package/dist/flows/pack.js +3 -3
  184. package/dist/flows/pack.js.map +1 -1
  185. package/dist/flows/paths.js +57 -0
  186. package/dist/flows/paths.js.map +1 -0
  187. package/dist/flows/repair.js +111 -23
  188. package/dist/flows/repair.js.map +1 -1
  189. package/dist/flows/run.js +153 -57
  190. package/dist/flows/run.js.map +1 -1
  191. package/dist/flows/schema.js +50 -5
  192. package/dist/flows/schema.js.map +1 -1
  193. package/dist/flows/seedExec.js +4 -4
  194. package/dist/flows/seedExec.js.map +1 -1
  195. package/dist/flows/templates.js +5 -5
  196. package/dist/index.js +50 -8
  197. package/dist/index.js.map +1 -1
  198. package/dist/issues/classify.js +16 -16
  199. package/dist/issues/classify.js.map +1 -1
  200. package/dist/issues/fingerprint.js +24 -4
  201. package/dist/issues/fingerprint.js.map +1 -1
  202. package/dist/issues/index.js +94 -31
  203. package/dist/issues/index.js.map +1 -1
  204. package/dist/issues/metrics.js +4 -4
  205. package/dist/issues/metrics.js.map +1 -1
  206. package/dist/issues/recurrence.js +35 -8
  207. package/dist/issues/recurrence.js.map +1 -1
  208. package/dist/issues/report.js +4 -4
  209. package/dist/issues/report.js.map +1 -1
  210. package/dist/issues/reportBridge.js +4 -4
  211. package/dist/issues/reportBridge.js.map +1 -1
  212. package/dist/issues/schema.js +2 -2
  213. package/dist/issues/schema.js.map +1 -1
  214. package/dist/issues/sourceRevision.js +2 -2
  215. package/dist/issues/sourceRevision.js.map +1 -1
  216. package/dist/issues/store.js +110 -32
  217. package/dist/issues/store.js.map +1 -1
  218. package/dist/lib/abortScope.js +48 -0
  219. package/dist/lib/abortScope.js.map +1 -0
  220. package/dist/lib/android.js +75 -7
  221. package/dist/lib/android.js.map +1 -1
  222. package/dist/lib/coordSpace.js +1 -1
  223. package/dist/lib/coordSpace.js.map +1 -1
  224. package/dist/lib/device.js +32 -7
  225. package/dist/lib/device.js.map +1 -1
  226. package/dist/lib/gestures.js +141 -0
  227. package/dist/lib/gestures.js.map +1 -0
  228. package/dist/lib/gitignore.js +4 -3
  229. package/dist/lib/gitignore.js.map +1 -1
  230. package/dist/lib/image.js +1 -1
  231. package/dist/lib/image.js.map +1 -1
  232. package/dist/lib/lockfile.js +370 -31
  233. package/dist/lib/lockfile.js.map +1 -1
  234. package/dist/lib/needsInput.js +3 -3
  235. package/dist/lib/needsInput.js.map +1 -1
  236. package/dist/lib/png.js +2 -2
  237. package/dist/lib/png.js.map +1 -1
  238. package/dist/lib/redact.js +170 -9
  239. package/dist/lib/redact.js.map +1 -1
  240. package/dist/lib/result.js +79 -10
  241. package/dist/lib/result.js.map +1 -1
  242. package/dist/lib/schemaHash.js +3 -3
  243. package/dist/lib/schemaHash.js.map +1 -1
  244. package/dist/lib/sensitive.js +3 -2
  245. package/dist/lib/sensitive.js.map +1 -1
  246. package/dist/lib/simctl.js +3 -3
  247. package/dist/lib/simctl.js.map +1 -1
  248. package/dist/lib/spawn.js +52 -10
  249. package/dist/lib/spawn.js.map +1 -1
  250. package/dist/lib/toolAnnotations.js +114 -0
  251. package/dist/lib/toolAnnotations.js.map +1 -0
  252. package/dist/lib/wda.js +294 -15
  253. package/dist/lib/wda.js.map +1 -1
  254. package/dist/mobileAudit/checks.js +12 -12
  255. package/dist/mobileAudit/checks.js.map +1 -1
  256. package/dist/mobileAudit/evidence.js +4 -4
  257. package/dist/mobileAudit/evidence.js.map +1 -1
  258. package/dist/mobileAudit/profiles.js +1 -1
  259. package/dist/mobileAudit/profiles.js.map +1 -1
  260. package/dist/mobileAudit/results.js +3 -3
  261. package/dist/mobileAudit/results.js.map +1 -1
  262. package/dist/mobileAudit/runner.js +72 -18
  263. package/dist/mobileAudit/runner.js.map +1 -1
  264. package/dist/oracle/auth.js +1 -1
  265. package/dist/oracle/auth.js.map +1 -1
  266. package/dist/oracle/failures.js +219 -36
  267. package/dist/oracle/failures.js.map +1 -1
  268. package/dist/oracle/health.js +63 -17
  269. package/dist/oracle/health.js.map +1 -1
  270. package/dist/oracle/locator.js +13 -13
  271. package/dist/oracle/locator.js.map +1 -1
  272. package/dist/oracle/record.js +3 -3
  273. package/dist/oracle/record.js.map +1 -1
  274. package/dist/orchestration/envelope.js +2 -2
  275. package/dist/orchestration/envelope.js.map +1 -1
  276. package/dist/orchestration/goal.js +4 -4
  277. package/dist/orchestration/goal.js.map +1 -1
  278. package/dist/orchestration/testThis/execute.js +62 -21
  279. package/dist/orchestration/testThis/execute.js.map +1 -1
  280. package/dist/orchestration/testThis/pipeline.js +119 -30
  281. package/dist/orchestration/testThis/pipeline.js.map +1 -1
  282. package/dist/orchestration/testThis/plan.js +162 -73
  283. package/dist/orchestration/testThis/plan.js.map +1 -1
  284. package/dist/orchestration/testThis/sessionIntent.js +72 -0
  285. package/dist/orchestration/testThis/sessionIntent.js.map +1 -0
  286. package/dist/orchestration/testThis/terminal.js +34 -16
  287. package/dist/orchestration/testThis/terminal.js.map +1 -1
  288. package/dist/orchestration/testThis/types.js +1 -1
  289. package/dist/orchestration/testThis/types.js.map +1 -1
  290. package/dist/plan/plan.js +9 -9
  291. package/dist/plan/plan.js.map +1 -1
  292. package/dist/prompts/index.js +22 -22
  293. package/dist/prompts/index.js.map +1 -1
  294. package/dist/report/export.js +392 -37
  295. package/dist/report/export.js.map +1 -1
  296. package/dist/report/findingsDedupe.js +41 -0
  297. package/dist/report/findingsDedupe.js.map +1 -0
  298. package/dist/report/policy.js +7 -4
  299. package/dist/report/policy.js.map +1 -1
  300. package/dist/report/qaLevel.js +8 -8
  301. package/dist/report/qaLevel.js.map +1 -1
  302. package/dist/report/sarifSources.js +160 -0
  303. package/dist/report/sarifSources.js.map +1 -0
  304. package/dist/report/summary.js +2 -2
  305. package/dist/report/summary.js.map +1 -1
  306. package/dist/report/testCatalog.js +4 -4
  307. package/dist/report/testCatalog.js.map +1 -1
  308. package/dist/report/toolHealth.js +124 -0
  309. package/dist/report/toolHealth.js.map +1 -0
  310. package/dist/server.js +472 -45
  311. package/dist/server.js.map +1 -1
  312. package/dist/services/automationGenerate.js +8 -2
  313. package/dist/services/automationGenerate.js.map +1 -1
  314. package/dist/services/build.js +2 -2
  315. package/dist/services/build.js.map +1 -1
  316. package/dist/{tools → services}/flowGenerate.js +29 -13
  317. package/dist/services/flowGenerate.js.map +1 -0
  318. package/dist/services/preflight.js +4 -4
  319. package/dist/services/preflight.js.map +1 -1
  320. package/dist/services/prepareAndroid.js +46 -8
  321. package/dist/services/prepareAndroid.js.map +1 -1
  322. package/dist/services/prepareIos.js +24 -9
  323. package/dist/services/prepareIos.js.map +1 -1
  324. package/dist/services/report.js +100 -45
  325. package/dist/services/report.js.map +1 -1
  326. package/dist/services/smoke.js +32 -16
  327. package/dist/services/smoke.js.map +1 -1
  328. package/dist/services/suiteGenerate.js +28 -3
  329. package/dist/services/suiteGenerate.js.map +1 -1
  330. package/dist/services/testSuiteKnowledge.js +40 -27
  331. package/dist/services/testSuiteKnowledge.js.map +1 -1
  332. package/dist/session/attach.js +270 -6
  333. package/dist/session/attach.js.map +1 -1
  334. package/dist/session/processRegistry.js +317 -48
  335. package/dist/session/processRegistry.js.map +1 -1
  336. package/dist/session/progress.js +1 -1
  337. package/dist/session/retention.js +201 -0
  338. package/dist/session/retention.js.map +1 -0
  339. package/dist/session/store.js +275 -48
  340. package/dist/session/store.js.map +1 -1
  341. package/dist/snapshot/overlays.js +53 -8
  342. package/dist/snapshot/overlays.js.map +1 -1
  343. package/dist/snapshot/parse.js +28 -4
  344. package/dist/snapshot/parse.js.map +1 -1
  345. package/dist/snapshot/present.js +11 -5
  346. package/dist/snapshot/present.js.map +1 -1
  347. package/dist/snapshot/settle.js +39 -9
  348. package/dist/snapshot/settle.js.map +1 -1
  349. package/dist/state/consent.js +99 -0
  350. package/dist/state/consent.js.map +1 -0
  351. package/dist/state/profile.js +46 -2
  352. package/dist/state/profile.js.map +1 -1
  353. package/dist/suite/compile.js +9 -5
  354. package/dist/suite/compile.js.map +1 -1
  355. package/dist/suite/lint.js +4 -4
  356. package/dist/suite/lint.js.map +1 -1
  357. package/dist/suite/pom.js +50 -41
  358. package/dist/suite/pom.js.map +1 -1
  359. package/dist/suite/secretGuard.js +266 -0
  360. package/dist/suite/secretGuard.js.map +1 -0
  361. package/dist/suite/testcase.js +9 -7
  362. package/dist/suite/testcase.js.map +1 -1
  363. package/dist/testSuite/exporter.js +4 -4
  364. package/dist/testSuite/exporter.js.map +1 -1
  365. package/dist/testSuite/generator.js +13 -9
  366. package/dist/testSuite/generator.js.map +1 -1
  367. package/dist/testSuite/history.js +1 -1
  368. package/dist/testSuite/history.js.map +1 -1
  369. package/dist/testSuite/issueLinks.js +3 -3
  370. package/dist/testSuite/issueLinks.js.map +1 -1
  371. package/dist/testSuite/lint.js +4 -4
  372. package/dist/testSuite/lint.js.map +1 -1
  373. package/dist/testSuite/merge.js +5 -5
  374. package/dist/testSuite/merge.js.map +1 -1
  375. package/dist/testSuite/schema.js +5 -5
  376. package/dist/testSuite/schema.js.map +1 -1
  377. package/dist/testSuite/store.js +3 -3
  378. package/dist/testSuite/store.js.map +1 -1
  379. package/dist/testSuite/traceability.js +2 -2
  380. package/dist/testSuite/traceability.js.map +1 -1
  381. package/dist/tools/act.js +794 -164
  382. package/dist/tools/act.js.map +1 -1
  383. package/dist/tools/agent.js +451 -128
  384. package/dist/tools/agent.js.map +1 -1
  385. package/dist/tools/appControl.js +69 -19
  386. package/dist/tools/appControl.js.map +1 -1
  387. package/dist/tools/appMap.js +188 -130
  388. package/dist/tools/appMap.js.map +1 -1
  389. package/dist/tools/build.js +32 -42
  390. package/dist/tools/build.js.map +1 -1
  391. package/dist/tools/bundletool.js +21 -31
  392. package/dist/tools/bundletool.js.map +1 -1
  393. package/dist/tools/clearOverlay.js +55 -12
  394. package/dist/tools/clearOverlay.js.map +1 -1
  395. package/dist/tools/device.js +76 -24
  396. package/dist/tools/device.js.map +1 -1
  397. package/dist/tools/doctor.js +68 -28
  398. package/dist/tools/doctor.js.map +1 -1
  399. package/dist/tools/explore.js +41 -47
  400. package/dist/tools/explore.js.map +1 -1
  401. package/dist/tools/featureTesting.js +31 -48
  402. package/dist/tools/featureTesting.js.map +1 -1
  403. package/dist/tools/firstRun.js +34 -41
  404. package/dist/tools/firstRun.js.map +1 -1
  405. package/dist/tools/flow.js +183 -103
  406. package/dist/tools/flow.js.map +1 -1
  407. package/dist/tools/flowRepair.js +25 -13
  408. package/dist/tools/flowRepair.js.map +1 -1
  409. package/dist/tools/generate.js +52 -89
  410. package/dist/tools/generate.js.map +1 -1
  411. package/dist/tools/getArtifact.js +16 -5
  412. package/dist/tools/getArtifact.js.map +1 -1
  413. package/dist/tools/health.js +15 -12
  414. package/dist/tools/health.js.map +1 -1
  415. package/dist/tools/ios.js +45 -223
  416. package/dist/tools/ios.js.map +1 -1
  417. package/dist/tools/issues.js +251 -35
  418. package/dist/tools/issues.js.map +1 -1
  419. package/dist/tools/jobs.js +41 -16
  420. package/dist/tools/jobs.js.map +1 -1
  421. package/dist/tools/metro.js +36 -35
  422. package/dist/tools/metro.js.map +1 -1
  423. package/dist/tools/mobileAudit.js +50 -45
  424. package/dist/tools/mobileAudit.js.map +1 -1
  425. package/dist/tools/network.js +31 -14
  426. package/dist/tools/network.js.map +1 -1
  427. package/dist/tools/note.js +26 -26
  428. package/dist/tools/note.js.map +1 -1
  429. package/dist/tools/prepareIosTarget.js +10 -16
  430. package/dist/tools/prepareIosTarget.js.map +1 -1
  431. package/dist/tools/prepareTarget.js +117 -50
  432. package/dist/tools/prepareTarget.js.map +1 -1
  433. package/dist/tools/report.js +11 -22
  434. package/dist/tools/report.js.map +1 -1
  435. package/dist/tools/resolveArtifact.js +11 -15
  436. package/dist/tools/resolveArtifact.js.map +1 -1
  437. package/dist/tools/resolveTarget.js +78 -24
  438. package/dist/tools/resolveTarget.js.map +1 -1
  439. package/dist/tools/screenRecord.js +23 -21
  440. package/dist/tools/screenRecord.js.map +1 -1
  441. package/dist/tools/screenshot.js +23 -16
  442. package/dist/tools/screenshot.js.map +1 -1
  443. package/dist/tools/smoke.js +20 -16
  444. package/dist/tools/smoke.js.map +1 -1
  445. package/dist/tools/snapshot.js +155 -118
  446. package/dist/tools/snapshot.js.map +1 -1
  447. package/dist/tools/startSession.js +104 -116
  448. package/dist/tools/startSession.js.map +1 -1
  449. package/dist/tools/suite.js +72 -43
  450. package/dist/tools/suite.js.map +1 -1
  451. package/dist/tools/testSuite.js +30 -20
  452. package/dist/tools/testSuite.js.map +1 -1
  453. package/dist/tools/testThis.js +24 -28
  454. package/dist/tools/testThis.js.map +1 -1
  455. package/dist/tools/visual.js +686 -210
  456. package/dist/tools/visual.js.map +1 -1
  457. package/dist/tools/wait.js +9 -38
  458. package/dist/tools/wait.js.map +1 -1
  459. package/dist/tools/wda.js +187 -57
  460. package/dist/tools/wda.js.map +1 -1
  461. package/dist/version.js +31 -22
  462. package/dist/version.js.map +1 -1
  463. package/dist/visual/ocr.js +53 -6
  464. package/dist/visual/ocr.js.map +1 -1
  465. package/dist/visual/provider.js +80 -12
  466. package/dist/visual/provider.js.map +1 -1
  467. package/docs/README.md +24 -10
  468. package/docs/ci-reports.md +328 -0
  469. package/docs/concepts.md +227 -0
  470. package/docs/flows.md +153 -0
  471. package/docs/mcp-server.md +194 -128
  472. package/docs/physical-devices.md +84 -0
  473. package/docs/tools.md +812 -152
  474. package/package.json +3 -2
  475. package/dist/tools/assertVisual.js +0 -84
  476. package/dist/tools/assertVisual.js.map +0 -1
  477. package/dist/tools/automationGenerate.js.map +0 -1
  478. package/dist/tools/capabilities.js +0 -179
  479. package/dist/tools/capabilities.js.map +0 -1
  480. package/dist/tools/detectContext.js +0 -41
  481. package/dist/tools/detectContext.js.map +0 -1
  482. package/dist/tools/flowGenerate.js.map +0 -1
  483. package/dist/tools/history.js +0 -86
  484. package/dist/tools/history.js.map +0 -1
  485. package/dist/tools/locator.js +0 -85
  486. package/dist/tools/locator.js.map +0 -1
  487. package/dist/tools/permissions.js +0 -174
  488. package/dist/tools/permissions.js.map +0 -1
  489. package/dist/tools/plan.js +0 -52
  490. package/dist/tools/plan.js.map +0 -1
  491. package/dist/tools/screenInfo.js +0 -76
  492. package/dist/tools/screenInfo.js.map +0 -1
  493. package/dist/tools/seed.js +0 -133
  494. package/dist/tools/seed.js.map +0 -1
  495. package/dist/tools/state.js +0 -217
  496. package/dist/tools/state.js.map +0 -1
  497. package/dist/tools/visualText.js +0 -106
  498. package/dist/tools/visualText.js.map +0 -1
package/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # Swipium
6
6
 
7
- MCP server for simulator-based mobile QA agents.
7
+ An MCP server that lets coding agents QA mobile apps on Android Emulators and iOS Simulators.
8
8
 
9
9
  [![npm version](https://img.shields.io/npm/v/swipium.svg)](https://www.npmjs.com/package/swipium)
10
10
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
@@ -12,311 +12,142 @@ MCP server for simulator-based mobile QA agents.
12
12
  [![MCP](https://img.shields.io/badge/MCP-server-black.svg)](https://modelcontextprotocol.io)
13
13
  [![Platform](https://img.shields.io/badge/platform-Android%20Emulator%20%2B%20iOS%20Simulator-blue.svg)](https://swipium.com)
14
14
 
15
- Swipium lets an AI agent run practical mobile QA from a local MCP client: launch an app in an Android Emulator or iOS Simulator, inspect screens, act on the UI, run smoke checks, collect evidence, build an app knowledge map, generate reports, and create reusable test assets.
15
+ Swipium gives an AI coding agent (Claude Code, Codex, Gemini CLI, Cursor, VS Code, and other MCP clients) the tools a QA engineer uses: find or build the app, boot a simulator, install and launch it, read the screen, tap and type through real user flows, and write a report backed by screenshots, logs, and UI dumps. A run can be turned into a repeatable flow, a test suite, or Appium code.
16
16
 
17
- Website: [swipium.com](https://swipium.com)
17
+ It is for mobile developers who want their agent to catch the broken login screen before a TestFlight or Play Console build. It runs locally (stdio, no network listener), drives devices through `adb`, `simctl`, and WebDriverAgent rather than Appium, and asks your consent before anything with side effects. [swipium.com](https://swipium.com)
18
18
 
19
- ## About
20
-
21
- The goal of the MCP is to give your agent a ready-to-use suite of tools so it can test your application using an emulator and real user flows, not directly against the code, with the experience of a QA. Avoid reaching TestFlight or production only to find an error that could have been caught before making the build.
22
-
23
- Focused on mobile applications, for now.
24
-
25
- ## What is Swipium?
26
-
27
- Swipium is not a replacement for a test runner. It is an agent-facing QA harness.
28
-
29
- It helps an agent answer requests like:
30
-
31
- - "Test it."
32
- - "Test this e2e flow."
33
- - "Create test automation for this app."
34
- - "Smoke test this app."
35
- - "Explore the login flow."
36
- - "Generate a report with evidence."
37
- - "Turn this run into a reusable flow."
38
- - "Create an automation suite from what you observed."
39
-
40
- The MCP server keeps the workflow deterministic where possible and explicit where risk exists. Heavy steps such as booting simulators, installing apps, writing files, or generating automation are exposed as tools with structured outputs, blockers, artifacts, and consent prompts.
41
-
42
- Swipium does not run on Appium. It drives devices directly via `adb`, `simctl`, and WebDriverAgent; Appium is one of the export formats for generated tests (`qa_generate` with `target:"appium"`), not the execution engine.
43
-
44
- ## QuickStart
45
-
46
- Run this from the mobile app repository:
47
-
48
- ```bash
49
- npx -y swipium verify
50
- ```
51
-
52
- Add Swipium to your agent:
53
-
54
- ```bash
55
- npm install -g swipium
56
- swipium init claude --apply --scope project
57
- ```
58
-
59
- Then ask the agent:
19
+ ### A session, abbreviated
60
20
 
61
21
  ```text
62
- Test this app with Swipium. Start with qa_test_this. Use Android Emulator or iOS Simulator only. Generate a report with evidence.
22
+ You: Smoke test this app on Android with Swipium.
23
+ Agent > qa_test_this { goal: "smoke" } (mode defaults to "plan": nothing runs)
24
+ plan for ~/code/shop-app (framework=react-native, session 3f9c2a1b)
25
+ target: android (will boot Pixel_8_API_35)
26
+ artifact: APK android/app/build/outputs/apk/release/app-release.apk
27
+ 1. [ ] qa_prepare_target: Install + launch 2. [ ] qa_smoke 3. [ ] qa_report
28
+ Agent > qa_test_this { sessionId: "3f9c2a1b", mode: "execute", goal: "smoke" }
29
+ 🔐 Consent required (low): • boot_emulator: emulator -avd Pixel_8_API_35 -no-window
30
+ • install_apk: adb install -r -g android/app/.../app-release.apk
31
+ You: Approve (one prompt covers boot + install)
32
+ state: "running", jobId: "a41c09e2"
33
+ Agent > qa_job_status { sessionId: "3f9c2a1b", jobId: "a41c09e2", waitMs: 60000 }
34
+ status: "done", result.state: "completed"
35
+ reportSummary: "PASS app · COVERED coverage · PASS tool. Read swipium://session/3f9c2a1b/report/…"
36
+ Agent: The app launched and passed the smoke checks with no crashes or error screens.
63
37
  ```
64
38
 
65
- For a direct MCP configuration without a global install:
66
-
67
- ```jsonc
68
- {
69
- "mcpServers": {
70
- "swipium": {
71
- "command": "npx",
72
- "args": ["-y", "swipium"],
73
- "cwd": "/absolute/path/to/your/mobile-app",
74
- "timeout": 600000
75
- }
76
- }
77
- }
78
- ```
39
+ The report behind that summary, rendered with `npx swipium report --latest --format markdown`, includes:
79
40
 
80
- ## Installation
41
+ ```markdown
42
+ **Release risk: 🟢 SHIP**
81
43
 
82
- Run without installing:
83
-
84
- ```bash
85
- npx -y swipium verify
44
+ **App status:** PASS - No high-severity app/native finding observed in this run.
45
+ **Coverage status:** COVERED - Structured smoke/workflow evidence was collected.
46
+ **Tool status:** PASS - No Swipium/MCP limitations or tool errors recorded in this run.
86
47
  ```
87
48
 
88
- Install globally:
49
+ ## Contents
89
50
 
90
- ```bash
91
- npm install -g swipium
92
- swipium verify
93
- ```
94
-
95
- Install in a project:
96
-
97
- ```bash
98
- npm install --save-dev swipium
99
- npx swipium verify
100
- ```
101
-
102
- ### Prerequisites
103
-
104
- All platforms:
105
-
106
- - Node.js 20 or newer.
107
-
108
- Android:
51
+ [Requirements](#requirements) · [Quickstart](#quickstart) · [Starter prompts](#starter-prompts) · [How it works](#how-it-works) · [Tools](#tools) · [Where results go](#where-results-go) · [Configuration](#configuration--environment-variables) · [CLI](#cli-reference) · [CI](#ci) · [Upgrading from 1.5](#upgrading-from-15) · [Troubleshooting](#troubleshooting) · [Security](#security)
109
52
 
110
- - Android platform-tools with `adb` on your PATH (`ANDROID_HOME/platform-tools`), typically installed via Android Studio.
111
- - The Android Emulator package and at least one AVD, or an emulator that is already online.
112
- - An APK or buildable Android project. Java is only needed for build-from-source native Android builds.
113
-
114
- iOS:
115
-
116
- - Xcode with an iOS Simulator runtime and at least one simulator created.
117
- - A simulator-ready app artifact, such as a simulator `.app`.
118
- - For UI interaction (taps, typing, `qa_snapshot`): a WebDriverAgent build. Install `appium-webdriveragent`, or configure `ios.wda.derivedDataPath` / `wdaProjectPath`, then let `qa_wda` build and start it. `qa_doctor` with `platform:"ios"` checks for this.
119
-
120
- #### iOS runs in two modes
121
-
122
- - **Visual-only mode** (no WebDriverAgent): install, launch, deep links, screenshots, logs, and visual assertions work via `simctl`. UI-tree snapshots, taps, typing, and swipes are rejected with a clear error pointing to `qa_wda`.
123
- - **Full-interaction mode** (WebDriverAgent built and running): structured snapshots and input work like on Android. Use `qa_wda` (doctor, build, start) or attach an external WDA URL.
124
-
125
- Android has full interaction out of the box through `adb`; no extra agent is required.
126
-
127
- ## Usage
128
-
129
- Start with the autopilot tool:
130
-
131
- ```text
132
- qa_test_this {
133
- "projectRoot": "/absolute/path/to/app",
134
- "mode": "execute",
135
- "goal": "smoke"
136
- }
137
- ```
53
+ ## Requirements
138
54
 
139
- Common workflow:
55
+ **Node.js 20 or newer.** Swipium works with emulators and simulators only; physical devices are refused with `PHYSICAL_DEVICE_UNSUPPORTED` ([why](docs/physical-devices.md)).
140
56
 
141
- 1. `qa_doctor` checks local toolchain readiness. Use `platform:"android"`, `platform:"ios"`, or `platform:"both"`.
142
- 2. `qa_test_this` resolves the project, artifact, and simulator target.
143
- 3. `qa_job_status` polls long-running work.
144
- 4. `qa_smoke` or `qa_explore` runs the app.
145
- 5. `qa_report` produces the evidence report, including separate app and coverage verdicts.
146
- 6. `qa_app_map_read` or `qa_app_map_query` reads the durable app map.
147
- 7. `qa_generate` creates reusable QA assets from the run (`target`: flow, page objects, POM suite, test cases, or Appium code).
57
+ | Host | Android Emulator | iOS Simulator |
58
+ | --- | --- | --- |
59
+ | macOS | Supported | Supported (Xcode with a Simulator runtime) |
60
+ | Linux | Supported | Not available |
61
+ | Windows | Experimental and untested; some process-cleanup helpers rely on `ps` | Not available |
148
62
 
149
- CLI helpers:
150
-
151
- ```bash
152
- swipium verify # starts the server and checks tool injection
153
- swipium init claude # preview Claude Code registration
154
- swipium init gemini # preview Gemini registration
155
- swipium init codex # preview Codex config
156
- swipium init flows # create starter flow templates
157
- swipium scan # scan project context
158
- swipium suite # local suite helper
159
- ```
160
-
161
- Note: `swipium verify` only reports pass/fail for server start and tool injection. Actionable fix hints — install steps for platform-tools, Xcode, WebDriverAgent, `brew install` suggestions — come from the `qa_doctor` tool output inside your MCP client, not from `swipium verify`.
162
-
163
- ## MCP Server
164
-
165
- Swipium runs as a stdio MCP server. MCP clients launch it as a local process and communicate through JSON-RPC over stdin and stdout.
166
-
167
- Manual MCP configuration:
168
-
169
- ```jsonc
170
- {
171
- "mcpServers": {
172
- "swipium": {
173
- "command": "npx",
174
- "args": ["-y", "swipium"],
175
- "cwd": "/absolute/path/to/your/mobile-app",
176
- "timeout": 600000
177
- }
178
- }
179
- }
180
- ```
181
-
182
- Installed binary configuration:
183
-
184
- ```jsonc
185
- {
186
- "mcpServers": {
187
- "swipium": {
188
- "command": "swipium",
189
- "args": [],
190
- "cwd": "/absolute/path/to/your/mobile-app",
191
- "timeout": 600000
192
- }
193
- }
194
- }
195
- ```
196
-
197
- `npx -y swipium` is the canonical setup for npm users. If you run from a source checkout instead, build first with `npm run build` and use `node /absolute/path/to/swipium/dist/index.js` as the command.
198
-
199
- Important:
200
-
201
- - Set `cwd` to the mobile app repository.
202
- - Restart the MCP client after installing or upgrading.
203
- - Run `qa_doctor` if tools are missing or stale.
204
- - Use `qa_get_artifact` for report, screenshot, dump, and log artifacts.
205
-
206
- More detail: [docs/mcp-server.md](docs/mcp-server.md)
207
-
208
- ## Agent Integration
209
-
210
- ### Claude Code
63
+ | Your app | What Swipium needs |
64
+ | --- | --- |
65
+ | React Native / Expo, debug build | Metro serving the JS bundle. `qa_metro` can start it (consent-gated); otherwise the run stops with `METRO_REQUIRED`. |
66
+ | React Native / Expo release, or native Android / iOS | An installable artifact (APK or `.aab` for Android, a simulator `.app` for iOS; a device `.ipa` is refused) or a project Swipium can build. |
67
+ | Expo managed (no `android/` or `ios/`) | Run `npx expo prebuild` first. Without native directories the build fails with `EXPO_PREBUILD_REQUIRED`. |
68
+ | Flutter | A buildable Flutter project, or a built APK / `.app`. |
211
69
 
212
- Global install:
70
+ - **Android:** platform-tools, the Emulator, and at least one AVD (usually via Android Studio). `adb` on your `PATH` is used if present, else the SDK copy from `$ANDROID_HOME`, `$ANDROID_SDK_ROOT`, or the default SDK location (`~/Library/Android/sdk`, `~/Android/Sdk`, `%LOCALAPPDATA%\Android\Sdk`). The `emulator` binary that boots AVDs and `aapt2` come from the SDK first. `.aab` files need bundletool.
71
+ - **iOS (macOS only):** Xcode and a simulator. Taps, typing, and UI-tree snapshots need **WebDriverAgent** (WDA, the on-simulator automation server Appium uses); without it iOS is visual-only ([iOS modes](docs/concepts.md#ios-modes)).
213
72
 
214
- ```bash
215
- npm install -g swipium
216
- swipium init claude --apply --scope project
217
- ```
73
+ ## Quickstart
218
74
 
219
- No global install:
75
+ **1. Register Swipium with your client.** From your app repository, for Claude Code:
220
76
 
221
77
  ```bash
222
- claude mcp add swipium --scope project -- npx -y swipium
78
+ npx -y swipium init claude --scope project # preview; changes nothing
79
+ npx -y swipium init claude --scope project --apply # writes .mcp.json, then runs `swipium verify`
223
80
  ```
224
81
 
225
- ### Gemini CLI
82
+ The same command handles `codex`, `gemini`, `cursor`, and `vscode` (`swipium init <client> --apply`). Claude Desktop, Windsurf, manual configs, and per-client details are in **[docs/mcp-server.md](docs/mcp-server.md)**.
226
83
 
227
- Global install:
84
+ **2. Restart the client** and check that it lists `qa_test_this`, `qa_doctor`, and `qa_report`.
228
85
 
229
- ```bash
230
- npm install -g swipium
231
- swipium init gemini --apply
232
- ```
233
-
234
- No global install:
86
+ **3. Ask the agent to test the app:**
235
87
 
236
- ```bash
237
- gemini mcp add swipium npx -y swipium
88
+ ```text
89
+ Use Swipium to smoke test this app. Run qa_doctor, then qa_test_this with
90
+ mode "execute" and goal "smoke", poll qa_job_status until the job finishes,
91
+ and summarize the report.
238
92
  ```
239
93
 
240
- ### Codex
94
+ `mode:"execute"` matters: the default `mode:"plan"` has no side effects and only returns what would happen. `goal:"smoke"` is the fastest path. With no `goal`, `qa_test_this` runs the smoke check and then tries to generate a test suite.
241
95
 
242
- Global install:
96
+ If a tool returns `PROJECT_ROOT_UNRESOLVED`, name the absolute project path in your prompt or set `SWIPIUM_PROJECT_ROOT` in the server config ([Project root](docs/concepts.md#project-root)).
243
97
 
244
- ```bash
245
- npm install -g swipium
246
- swipium init codex --apply
247
- ```
98
+ ### What you'll see
248
99
 
249
- Manual Codex config:
100
+ - **One approval prompt** listing the exact build, boot, and install commands. Clients with MCP elicitation show a real prompt; others return `requiresConsent`, which the agent must relay to you.
101
+ - **The first build can take minutes.** The run is a background job the agent polls with `qa_job_status`.
102
+ - **Two states.** The job `status` is `running`, `done`, `failed`, or `cancelled`. The run's `result.state` is `completed` or `needs_input` (job `done`), or `blocked` or `unsafe` (job `failed`). `needs_input` means one question for you, such as login credentials.
103
+ - **A report** with separate verdicts for the app, coverage, and Swipium itself. Read it with `npx swipium report --latest --format markdown`.
250
104
 
251
- ```toml
252
- [mcp_servers.swipium]
253
- command = "npx"
254
- args = ["-y", "swipium"]
255
- cwd = "/absolute/path/to/your/mobile-app"
256
- ```
105
+ ## Starter prompts
257
106
 
258
- Known caveat: Codex builds after ~0.120.0 have an open tool-injection regression (openai/codex#19425). Set `cwd` explicitly, and if `qa_*` tools do not appear after setup, switch `command` to an absolute path (the installed `swipium` binary, or `node <abs>/dist/index.js` from a source checkout) and restart Codex.
259
-
260
- ### Claude Desktop
107
+ | Goal | Prompt |
108
+ | --- | --- |
109
+ | Smoke test | "Use Swipium to smoke test this app: qa_test_this mode execute, goal smoke, then summarize the report." |
110
+ | Test login | "Use Swipium to test login with goal test_login. Don't ask me for the password: type `${SWIPIUM_TEST_EMAIL}` and `${SWIPIUM_TEST_PASSWORD}` with qa_act." (set both in the server `env`; placeholders expand server-side and secret values are redacted) |
111
+ | Reproduce a bug | "Use Swipium to reproduce this bug with goal reproduce_bug and goalText: 'checkout button does nothing after adding a coupon'. Attach the evidence." |
112
+ | Save a flow | "Turn the last Swipium run into a flow named login-smoke with qa_generate and save it." |
113
+ | Release gate | "Run Swipium with goal release_gate and tell me whether the release gate passes." |
261
114
 
262
- Add to `claude_desktop_config.json` (macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`), then restart Claude Desktop:
115
+ Clients that support MCP prompts can use the built-in ones instead: `swipium_setup_check`, `swipium_guardrail_validation`, `swipium_full_smoke`, `swipium_bug_repro`, and `swipium_convert_run_to_flow`.
263
116
 
264
- ```jsonc
265
- {
266
- "mcpServers": {
267
- "swipium": {
268
- "command": "npx",
269
- "args": ["-y", "swipium"],
270
- "cwd": "/absolute/path/to/your/mobile-app",
271
- "timeout": 600000
272
- }
273
- }
274
- }
275
- ```
117
+ ## How it works
276
118
 
277
- ### Cursor
278
-
279
- Add to `.cursor/mcp.json` in the mobile app repository (or `~/.cursor/mcp.json` for all projects):
280
-
281
- ```jsonc
282
- {
283
- "mcpServers": {
284
- "swipium": {
285
- "command": "npx",
286
- "args": ["-y", "swipium"],
287
- "cwd": "/absolute/path/to/your/mobile-app",
288
- "timeout": 600000
289
- }
290
- }
291
- }
119
+ ```text
120
+ qa_test_this {mode:"plan"} > qa_test_this {mode:"execute"} > consent > job
121
+ │
122
+ qa_job_status {waitMs} ◄──────────────────────────────┘
123
+ ├─ completed / blocked / unsafe > report (qa_get_artifact reportUri)
124
+ └─ needs_input > ask you one question > qa_continue_from_blocker
292
125
  ```
293
126
 
294
- After setup, verify that the client lists `qa_test_this`, `qa_capabilities`, and `qa_report`.
295
-
296
- ## Tool Docs
127
+ `qa_test_this` finds or builds the app, boots a simulator, installs and launches the app, runs a smoke check (plus exploration or suite generation, per `goal`), and always writes a report. Failures carry a `failureCode` that `qa_explain_blocker` explains. For hands-on work the agent opens a session (`qa_start_session`), reads the screen with `qa_snapshot`, and acts on element refs such as `@e3`.
297
128
 
298
- Swipium exposes 60 public MCP tools. Start with `qa_test_this` for low-context requests.
129
+ Concepts, explained in **[docs/concepts.md](docs/concepts.md)**:
299
130
 
300
- Full reference: [docs/tools.md](docs/tools.md)
131
+ - **[Project root](docs/concepts.md#project-root):** the repository under test, from the `projectRoot` argument, MCP roots, `SWIPIUM_PROJECT_ROOT`, `CLAUDE_PROJECT_DIR`, or the server's working directory.
132
+ - **[Consent](docs/concepts.md#consent):** builds, boots, installs, data wipes, network changes, and repo-supplied commands need your single-use approval.
133
+ - **[Sessions and jobs](docs/concepts.md#sessions-and-jobs):** a session holds one run's device, app, and evidence; long work is a job you poll.
134
+ - **[Secrets and redaction](docs/concepts.md#secrets-and-redaction):** credentials are redacted from text output; screenshots are not.
135
+ - **[iOS modes](docs/concepts.md#ios-modes):** visual-only through `simctl`, or full interaction with WDA.
136
+ - The **app map** is Swipium's durable memory of your app's screens; a **flow** is a replayable YAML script ([docs/flows.md](docs/flows.md)); a **POM suite** is a generated page-object test suite. See the [glossary](docs/concepts.md#glossary).
301
137
 
302
- New in 1.5.0 — production consolidation:
138
+ ## Tools
303
139
 
304
- - **60 public tools** — the MCP surface is smaller and clearer, with lower-level helpers merged into canonical workflows or deferred out of the public contract.
305
- - **`qa_generate`** — one entry point for flow YAML, page objects, per-run suites, test-case docs, and Appium code.
306
- - **`qa_first_run`** — one safe first-run tool for login, signup, onboarding, permissions, OTP, paywall, and home-screen transitions.
307
- - **Release hardening** — clean builds, lint/format/test/audit/pack release checks, structured `failureCode` errors, and safer local file locking.
308
-
309
- Earlier releases added device-parity, local-first visual, seeded-state, report-history (1.1.0); durable issue memory, persistent test suite, flow plan/repair, agent helpers (1.2.0); feature-focused testing plus local build/artifact resolution (1.3.0); and app-map/agent helper refinements (1.4.0). The 1.5.0 release consolidates those capabilities into the production public surface — see the CHANGELOG for migration notes.
140
+ Grouped by capability (`qa_status` without arguments returns the same groups). Every tool's parameters and behavior are in **[docs/tools.md](docs/tools.md)**; `swipium verify` lists what your installed version exposes.
310
141
 
311
142
  | Group | Tools |
312
143
  | --- | --- |
313
- | Start | `qa_agent_brief`, `qa_capabilities`, `qa_test_this`, `qa_job_status`, `qa_job_cancel`, `qa_status`, `qa_explain_blocker`, `qa_continue_from_blocker`, `qa_next_best_action`, `qa_get_artifact` |
314
- | Setup | `qa_doctor`, `qa_start_session`, `qa_detect_context`, `qa_plan`, `qa_prepare_target`, `qa_prepare_ios_target`, `qa_ios`, `qa_wda` |
144
+ | Start | `qa_test_this`, `qa_status`, `qa_job_status`, `qa_job_cancel`, `qa_explain_blocker`, `qa_continue_from_blocker`, `qa_get_artifact` |
145
+ | Setup | `qa_doctor`, `qa_start_session`, `qa_prepare_target`, `qa_prepare_ios_target`, `qa_ios`, `qa_wda` |
315
146
  | Build | `qa_resolve_target`, `qa_resolve_artifact`, `qa_build`, `qa_bundletool` |
316
147
  | Device | `qa_device_info`, `qa_orientation`, `qa_geolocation`, `qa_network`, `qa_metro`, `qa_app_control`, `qa_screen_record` |
317
- | Drive | `qa_snapshot`, `qa_inspect`, `qa_act`, `qa_clear_overlay`, `qa_check_health`, `qa_screenshot`, `qa_note`, `qa_assert_visual`, `qa_wait` |
148
+ | Drive | `qa_snapshot`, `qa_inspect`, `qa_act`, `qa_clear_overlay`, `qa_check_health`, `qa_screenshot`, `qa_note`, `qa_visual`, `qa_wait` |
318
149
  | Run | `qa_smoke`, `qa_explore`, `qa_report` |
319
- | App map | `qa_app_map_build`, `qa_app_map_read`, `qa_app_map_query`, `qa_app_map_update`, `qa_app_map_feature_scope` |
150
+ | App map | `qa_app_map_build`, `qa_app_map_read`, `qa_app_map_query`, `qa_app_map_feature_scope`, `qa_app_map_update` |
320
151
  | Feature | `qa_test_feature` |
321
152
  | Flows | `qa_flow_check`, `qa_flow_run`, `qa_flow_compile`, `qa_flow_repair` |
322
153
  | Generate | `qa_generate` |
@@ -324,31 +155,93 @@ Earlier releases added device-parity, local-first visual, seeded-state, report-h
324
155
  | Issues | `qa_issue_log`, `qa_mobile_audit` |
325
156
  | First run | `qa_first_run` |
326
157
 
327
- ## Why Swipium?
158
+ Every tool carries MCP annotations: read-only tools declare `readOnlyHint:true` and `openWorldHint:false` (so clients can auto-approve them); the rest also declare `destructiveHint` and `idempotentHint`.
328
159
 
329
- - Agent-native: exposes QA work as MCP tools with structured outputs.
330
- - Simulator-first: focuses on Android Emulator and iOS Simulator reliability.
331
- - Evidence-first: screenshots, logs, reports, dumps, and artifacts are stored and linked.
332
- - App memory: the app map preserves screens, features, test cases, flows, and coverage context.
333
- - Practical consent: mutating actions are gated instead of hidden behind agent text.
334
- - Reusable output: exploratory runs can become flows, test cases, suites, and generated automation.
335
- - Local by default: the server runs on the developer machine and uses local simulators.
160
+ ## Where results go
336
161
 
337
- ## Security
162
+ - **`<your repo>/.swipium/`:** app map, flows, test suite, issue ledger, visual baselines, generated files, and your configuration (`config.json`, `fixtures.json`, `policy.json`). The first time Swipium writes the app map or issue ledger in a Git repository, it adds `.swipium/` to `.gitignore`. Never pruned automatically.
163
+ - **`~/.swipium/runs/`:** per-session state and evidence (screenshots, logs, UI dumps, reports), returned as `swipium://` URIs. When a server process first loads its session registry, it prunes in the background session directories older than `SWIPIUM_RETENTION_DAYS`, keeping registered sessions and the newest `SWIPIUM_RETENTION_KEEP` per project. `swipium gc` cleans up on demand.
338
164
 
339
- Swipium runs locally as a stdio process: no network listener, no remote service. Destructive actions are consent-gated server-side, and known secret shapes are redacted from snapshots, artifacts, and reports. Trust boundaries, threats, and controls are documented in the [Threat Model](THREAT_MODEL.md). Report vulnerabilities per the [Security Policy](SECURITY.md).
165
+ ## Configuration & environment variables
340
166
 
341
- ## Docs
167
+ Set these in the MCP server's `env` block (or your shell, for CLI commands). This is the complete list.
168
+
169
+ | Variable | Purpose |
170
+ | --- | --- |
171
+ | `SWIPIUM_PROJECT_ROOT` | Absolute path of the app repository when the client provides no MCP roots. |
172
+ | `CLAUDE_PROJECT_DIR` | Set by Claude Code; used as the project root after `SWIPIUM_PROJECT_ROOT`. |
173
+ | `ANDROID_HOME`, `ANDROID_SDK_ROOT` | Android SDK location, searched for `adb`, `emulator`, and `aapt2` (see [Requirements](#requirements)). |
174
+ | `BUNDLETOOL_JAR` | Path to `bundletool.jar` for converting `.aab` files. A `bundletool` launcher on `PATH` also works. |
175
+ | `DEVELOPMENT_TEAM`, `XCODE_DEVELOPMENT_TEAM` | Apple team ID for signing WDA (`ios.wda.developmentTeam` in `.swipium/config.json` takes precedence). |
176
+ | `APPIUM_HOME` | Extra location searched for an Appium-installed WDA (besides `~/.appium` and global npm). |
177
+ | `WDA_PROJECT_PATH`, `WEBDRIVERAGENT_PROJECT` | Extra `WebDriverAgent.xcodeproj` candidates reported by `qa_doctor` and `qa_wda` status (to build one, pass `wdaProjectPath`). |
178
+ | `SWIPIUM_ALLOW_REMOTE_WDA` | Comma-separated exact non-loopback WDA base URLs you pre-approve. Set it in your client config, never in the repository. |
179
+ | `SWIPIUM_TEST_*` | Test-account values: `_EMAIL`, `_USERNAME`, `_PASSWORD`, `_OTP`, `_TOKEN`, `_PIN`. Flows and `qa_act` use `${SWIPIUM_TEST_EMAIL}`; `fixtures.json` uses `"var": "SWIPIUM_TEST_EMAIL"`. |
180
+ | Other `SWIPIUM_*` | Flows and fixtures read **only** `SWIPIUM_*` names from the environment (never `${HOME}` or `${AWS_SECRET_ACCESS_KEY}`). Names containing `pass`, `secret`, `token`, `otp`, `pin`, `cvv`, `key`, or `code` are secrets and redacted. |
181
+ | `SWIPIUM_OCR_CMD` | OCR command for `qa_visual` `find_text` (none bundled; consent-gated). `{image}` becomes a PNG path; it prints `[{"text","confidence","bbox"}]` JSON. `ocrCommand` in `config.json` wins. |
182
+ | `SWIPIUM_VISUAL_MASK_CMD` | Masks screenshots before OCR and visual providers see them (`visualMaskCommand` in config wins). |
183
+ | `SWIPIUM_REQUIRE_ELICITATION=1` | Refuse every consent-gated action (`CONSENT_REFUSED`) when the client can't show a real consent prompt. |
184
+ | `SWIPIUM_RETENTION_DAYS` | Age limit in days for `~/.swipium/runs` session directories (default 30). `0` or `off` disables the automatic prune; `swipium gc` still works. |
185
+ | `SWIPIUM_RETENTION_KEEP` | Number of newest sessions per project always kept (default 20). |
186
+ | `CI` | When set, reports label the run environment as CI. |
187
+ | `SWIPIUM_DISABLE_DEVICE_DISCOVERY` | Test-suite isolation only: disables device auto-discovery. Not for normal use. |
188
+
189
+ Generated flows, suites, and code never contain credential values; they reference `SWIPIUM_TEST_*`, `SWIPIUM_SECRET_N`, or `SWIPIUM_GEN_<FIELD>`, which you set when replaying. Generated Appium projects read their own variables (`SWIPIUM_PLATFORM`, `APPIUM_HOST`, `ANDROID_*`, `IOS_*`, …), documented in their README.
190
+
191
+ ## CLI reference
192
+
193
+ With no subcommand, `swipium` runs the stdio MCP server (what clients launch). `swipium --help` prints this list.
194
+
195
+ | Command | What it does |
196
+ | --- | --- |
197
+ | `swipium` (alias `swipium serve`) | Start the stdio MCP server. Unrecognized flags alone (such as `--stdio`) are ignored with a warning; an unknown subcommand prints usage and exits 2. |
198
+ | `swipium init <client> [--apply] [--scope local\|user\|project] [--cwd <dir>]` | Preview (default) or apply the registration for `claude`, `codex`, `gemini`, `cursor`, or `vscode`. See [docs/mcp-server.md](docs/mcp-server.md). |
199
+ | `swipium init flows [--root <dir>] [--force]` | Write starter flow templates into `.swipium/flows/` (existing files kept unless `--force`). |
200
+ | `swipium verify` | Start the server over stdio, check that every tool is listed, and run `qa_doctor`. |
201
+ | `swipium scan [path] [--check \| --dry-run \| --no-write]` | Print a readiness report. Creates `.swipium/` unless the result is `BLOCKED` or a no-write flag is set. |
202
+ | `swipium suite <lint\|compile\|init> [projectRoot] [--suite <file>]` | `lint` flags brittle page-object locators, `compile` turns a POM suite into flows under `.swipium/flows/`, `init` explains suites. |
203
+ | `swipium report --format junit\|sarif\|github-summary\|markdown\|json` | Render a saved report (`--latest` default, `--session`, `--report`, `--root`, `--out`, `--fail-on-gate`). Exits 1 when the gate blocks with `--fail-on-gate`, 2 on usage error or no report. |
204
+ | `swipium gc [--dry-run] [--days N] [--keep N]` | Delete old `~/.swipium/runs` session directories and stale `~/.swipium/projects.json` entries. |
205
+ | `swipium --help` / `-h`, `--version` / `-v` | Print usage or the version. |
206
+
207
+ ## CI
208
+
209
+ `swipium report` renders a finished run as JUnit, SARIF, a GitHub job summary, Markdown, or JSON; `--fail-on-gate` fails the job when the `.swipium/policy.json` release gate blocks. The CLI does not drive devices: CI still needs an agent (such as headless Claude Code) calling the MCP tools, including `qa_flow_run` to replay saved flows. Nobody can approve consent in CI, so install the app before the agent step. Recipe: **[docs/ci-reports.md](docs/ci-reports.md)**.
210
+
211
+ ## Upgrading from 1.5
212
+
213
+ 2.0.0 removes and renames tools and tightens defaults. Work through this list:
214
+
215
+ 1. **Restart your MCP client.** A client still running the old server gets `STALE_CLIENT` for removed tools and old call shapes.
216
+ 2. **Rename environment variables your flows and fixtures read** so they start with `SWIPIUM_` (for example `${TEST_PASSWORD}` becomes `${SWIPIUM_TEST_PASSWORD}`). Other names are no longer read from the environment.
217
+ 3. **CI: every app install now asks for consent**, including an APK inside the project. Install the app yourself before the agent step ([docs/ci-reports.md](docs/ci-reports.md)).
218
+ 4. **Saved prompts and scripts:** replace removed tools using the [migration table](CHANGELOG.md#migrating-from-150) (also in [docs/tools.md](docs/tools.md#migrating-from-150)), and drop arguments a tool doesn't declare; they now fail with `INVALID_ARGUMENT` instead of being ignored.
219
+ 5. **Remote WDA:** `ios.wda.allowNonLoopbackUrls` in `.swipium/config.json` no longer pre-approves a URL. Pass `allowNonLoopback:true` and approve the consent, or list the URL in `SWIPIUM_ALLOW_REMOTE_WDA` in your client config.
220
+ 6. **Scripts calling `swipium <unknown>`** now exit 2 instead of starting the server.
221
+ 7. **Metro and WDA processes started by 1.5.x** are not cleaned up automatically. Stop them yourself: the Metro process on port 8081 and any old WebDriverAgent `xcodebuild`.
222
+ 8. **Known issue:** the first time an iOS session from before the upgrade is rebound, the app may be relaunched once.
223
+
224
+ ## Troubleshooting
225
+
226
+ Every error has a `failureCode`, `nextSteps`, and `retrySafe`. `qa_explain_blocker` explains any code, `qa_doctor` checks the toolchain, and the full catalog is in [docs/tools.md](docs/tools.md#failure-codes).
227
+
228
+ | `failureCode` | Meaning | What to do |
229
+ | --- | --- | --- |
230
+ | `PROJECT_ROOT_UNRESOLVED` | Swipium can't tell which app to test. | Name the absolute path in the prompt or set `SWIPIUM_PROJECT_ROOT` ([project root](docs/concepts.md#project-root)). |
231
+ | `STALE_CLIENT` | The client runs a pre-upgrade server or uses a removed tool. | Restart the MCP client. |
232
+ | `ADB_NOT_FOUND` | Android platform-tools can't be found. | Install them via Android Studio; set `ANDROID_HOME` in the server `env` for GUI clients or non-default locations. |
233
+ | `NO_DEVICE` | No emulator is online and none can be booted. | Create an AVD or iOS Simulator; `qa_test_this` boots it for you. |
234
+ | `PHYSICAL_DEVICE_UNSUPPORTED` | Only a real phone is available. | Start an emulator, or unplug the phone. |
235
+ | `METRO_REQUIRED` | A debug RN/Expo build needs Metro serving. | Start Metro (`qa_metro {action:"start"}` or `npx react-native start` / `npx expo start`), then retry. |
236
+ | `EXPO_PREBUILD_REQUIRED` | The Expo project has no native directories. | Run `npx expo prebuild`, then retry. |
237
+ | `WDA_UNREACHABLE` | WebDriverAgent isn't running or answering. | `qa_wda {action:"status"}`, then `start` or `attach`. For a plain smoke check, use `goal:"smoke"`, which works visual-only. |
238
+ | `BACKEND_UNSUPPORTED` | The action needs WDA (iOS visual-only mode). | Attach WDA with `qa_wda`, or use `qa_visual` and `qa_screenshot`. |
239
+ | `CONSENT_DECLINED` / `CONSENT_CANCELLED` / `CONSENT_REFUSED` | Nothing ran: you declined, the prompt was dismissed or timed out, or `SWIPIUM_REQUIRE_ELICITATION=1` blocked it. | Re-call to get a fresh prompt if you want the action. |
240
+
241
+ ## Security
342
242
 
343
- - [MCP Server](docs/mcp-server.md)
344
- - [Tool Reference](docs/tools.md)
345
- - [Project Docs Index](docs/README.md)
346
- - [Threat Model](THREAT_MODEL.md)
347
- - [Security Policy](SECURITY.md)
348
- - [Contributing](CONTRIBUTING.md)
349
- - [Support](SUPPORT.md)
350
- - [Changelog](CHANGELOG.md)
243
+ Swipium is a local stdio process with no network listener. Actions with side effects need your [consent](docs/concepts.md#consent), known secret values are [redacted](docs/concepts.md#secrets-and-redaction) from snapshots, artifacts, and reports, and generated output is checked for leaked secrets. A cloned repository's `.swipium/` is treated as untrusted: repo-supplied commands are shown verbatim in the consent prompt, flows read only `SWIPIUM_*` variables, and Swipium never runs `git`. Screenshots are never redacted, so use `qa_start_session { sensitive: true }` to refuse all screen captures when that matters. Details: [Threat Model](THREAT_MODEL.md). Report vulnerabilities privately per the [Security Policy](SECURITY.md).
351
244
 
352
- ## License
245
+ ## Contributing and license
353
246
 
354
- MIT. See [LICENSE](LICENSE).
247
+ See [CONTRIBUTING.md](CONTRIBUTING.md), [SUPPORT.md](SUPPORT.md), the [docs index](docs/README.md), and the [CHANGELOG](CHANGELOG.md). MIT licensed; see [LICENSE](LICENSE).