swipium 1.4.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (541) hide show
  1. package/CHANGELOG.md +313 -0
  2. package/README.md +175 -219
  3. package/THREAT_MODEL.md +223 -47
  4. package/dist/appMap/automationLink.js +39 -26
  5. package/dist/appMap/automationLink.js.map +1 -1
  6. package/dist/appMap/build.js +68 -20
  7. package/dist/appMap/build.js.map +1 -1
  8. package/dist/appMap/codeIndex.js +31 -5
  9. package/dist/appMap/codeIndex.js.map +1 -1
  10. package/dist/appMap/featureIndex.js +23 -5
  11. package/dist/appMap/featureIndex.js.map +1 -1
  12. package/dist/appMap/featureModel.js +44 -8
  13. package/dist/appMap/featureModel.js.map +1 -1
  14. package/dist/appMap/firstRunApply.js +24 -6
  15. package/dist/appMap/firstRunApply.js.map +1 -1
  16. package/dist/appMap/fsWalk.js +19 -2
  17. package/dist/appMap/fsWalk.js.map +1 -1
  18. package/dist/appMap/issues.js +10 -30
  19. package/dist/appMap/issues.js.map +1 -1
  20. package/dist/appMap/migrations.js +6 -6
  21. package/dist/appMap/migrations.js.map +1 -1
  22. package/dist/appMap/prelaunch.js +2 -2
  23. package/dist/appMap/prelaunch.js.map +1 -1
  24. package/dist/appMap/projectRegistry.js +83 -11
  25. package/dist/appMap/projectRegistry.js.map +1 -1
  26. package/dist/appMap/provenance.js +2 -2
  27. package/dist/appMap/provenance.js.map +1 -1
  28. package/dist/appMap/query.js +21 -5
  29. package/dist/appMap/query.js.map +1 -1
  30. package/dist/appMap/runtimeMerge.js +12 -5
  31. package/dist/appMap/runtimeMerge.js.map +1 -1
  32. package/dist/appMap/schema.js +1 -1
  33. package/dist/appMap/schema.js.map +1 -1
  34. package/dist/appMap/screenMatch.js +6 -2
  35. package/dist/appMap/screenMatch.js.map +1 -1
  36. package/dist/appMap/staticScan.js +151 -39
  37. package/dist/appMap/staticScan.js.map +1 -1
  38. package/dist/appMap/store.js +58 -85
  39. package/dist/appMap/store.js.map +1 -1
  40. package/dist/appMap/tsAstScan.js +34 -12
  41. package/dist/appMap/tsAstScan.js.map +1 -1
  42. package/dist/artifacts/bundletool.js +49 -12
  43. package/dist/artifacts/bundletool.js.map +1 -1
  44. package/dist/artifacts/resolve.js +41 -14
  45. package/dist/artifacts/resolve.js.map +1 -1
  46. package/dist/automation/capabilities.js +112 -30
  47. package/dist/automation/capabilities.js.map +1 -1
  48. package/dist/automation/gestures.js +6 -2
  49. package/dist/automation/gestures.js.map +1 -1
  50. package/dist/automation/plan.js +71 -23
  51. package/dist/automation/plan.js.map +1 -1
  52. package/dist/automation/report.js +15 -5
  53. package/dist/automation/report.js.map +1 -1
  54. package/dist/automation/selectors.js +22 -28
  55. package/dist/automation/selectors.js.map +1 -1
  56. package/dist/automation/types.js +1 -1
  57. package/dist/automation/types.js.map +1 -1
  58. package/dist/automation/waits.js +14 -8
  59. package/dist/automation/waits.js.map +1 -1
  60. package/dist/automation/webview.js +9 -3
  61. package/dist/automation/webview.js.map +1 -1
  62. package/dist/automationGen/appiumModel.js +16 -8
  63. package/dist/automationGen/appiumModel.js.map +1 -1
  64. package/dist/automationGen/ciEmitter.js +6 -6
  65. package/dist/automationGen/ciEmitter.js.map +1 -1
  66. package/dist/automationGen/identifiers.js +224 -0
  67. package/dist/automationGen/identifiers.js.map +1 -0
  68. package/dist/automationGen/jsEmitter.js +288 -121
  69. package/dist/automationGen/jsEmitter.js.map +1 -1
  70. package/dist/automationGen/packagePatch.js +2 -2
  71. package/dist/automationGen/packagePatch.js.map +1 -1
  72. package/dist/automationGen/platformResolve.js +36 -0
  73. package/dist/automationGen/platformResolve.js.map +1 -0
  74. package/dist/automationGen/projectProfile.js +76 -27
  75. package/dist/automationGen/projectProfile.js.map +1 -1
  76. package/dist/automationGen/pythonEmitter.js +278 -107
  77. package/dist/automationGen/pythonEmitter.js.map +1 -1
  78. package/dist/automationGen/readmeEmitter.js +7 -6
  79. package/dist/automationGen/readmeEmitter.js.map +1 -1
  80. package/dist/automationGen/run.js +388 -0
  81. package/dist/automationGen/run.js.map +1 -0
  82. package/dist/automationGen/suitePlan.js +17 -10
  83. package/dist/automationGen/suitePlan.js.map +1 -1
  84. package/dist/automationGen/validation.js +52 -12
  85. package/dist/automationGen/validation.js.map +1 -1
  86. package/dist/build/parseBuildLog.js +235 -31
  87. package/dist/build/parseBuildLog.js.map +1 -1
  88. package/dist/build/plan.js +39 -18
  89. package/dist/build/plan.js.map +1 -1
  90. package/dist/ci/preflight.js +13 -4
  91. package/dist/ci/preflight.js.map +1 -1
  92. package/dist/cli/gc.js +74 -0
  93. package/dist/cli/gc.js.map +1 -0
  94. package/dist/cli/init.js +217 -26
  95. package/dist/cli/init.js.map +1 -1
  96. package/dist/cli/main.js +50 -0
  97. package/dist/cli/main.js.map +1 -0
  98. package/dist/cli/report.js +218 -0
  99. package/dist/cli/report.js.map +1 -0
  100. package/dist/cli/scan.js +36 -15
  101. package/dist/cli/scan.js.map +1 -1
  102. package/dist/cli/suite.js +7 -7
  103. package/dist/cli/suite.js.map +1 -1
  104. package/dist/cli/verify.js +7 -7
  105. package/dist/cli/verify.js.map +1 -1
  106. package/dist/consent/consent.js +162 -5
  107. package/dist/consent/consent.js.map +1 -1
  108. package/dist/context/detect.js +55 -18
  109. package/dist/context/detect.js.map +1 -1
  110. package/dist/context/findApps.js +22 -8
  111. package/dist/context/findApps.js.map +1 -1
  112. package/dist/context/projectRoot.js +174 -19
  113. package/dist/context/projectRoot.js.map +1 -1
  114. package/dist/context/scan.js +1 -1
  115. package/dist/context/scan.js.map +1 -1
  116. package/dist/core/capabilityGroups.js +90 -0
  117. package/dist/core/capabilityGroups.js.map +1 -0
  118. package/dist/core/target.js +10 -8
  119. package/dist/core/target.js.map +1 -1
  120. package/dist/core/targetPlan.js +160 -39
  121. package/dist/core/targetPlan.js.map +1 -1
  122. package/dist/drivers/DirectDriver.js +317 -43
  123. package/dist/drivers/DirectDriver.js.map +1 -1
  124. package/dist/drivers/SimctlDriver.js +124 -8
  125. package/dist/drivers/SimctlDriver.js.map +1 -1
  126. package/dist/drivers/WdaDriver.js +365 -55
  127. package/dist/drivers/WdaDriver.js.map +1 -1
  128. package/dist/explore/candidates.js +7 -3
  129. package/dist/explore/candidates.js.map +1 -1
  130. package/dist/explore/graph.js +15 -6
  131. package/dist/explore/graph.js.map +1 -1
  132. package/dist/explore/memory.js +4 -1
  133. package/dist/explore/memory.js.map +1 -1
  134. package/dist/explore/planner.js +54 -9
  135. package/dist/explore/planner.js.map +1 -1
  136. package/dist/explore/policy.js +11 -6
  137. package/dist/explore/policy.js.map +1 -1
  138. package/dist/explore/runner.js +363 -190
  139. package/dist/explore/runner.js.map +1 -1
  140. package/dist/explore/signatures.js +4 -2
  141. package/dist/explore/signatures.js.map +1 -1
  142. package/dist/explore/suite.js +3 -1
  143. package/dist/explore/suite.js.map +1 -1
  144. package/dist/featureTesting/executionBootstrap.js +137 -29
  145. package/dist/featureTesting/executionBootstrap.js.map +1 -1
  146. package/dist/featureTesting/featureMap.js +6 -3
  147. package/dist/featureTesting/featureMap.js.map +1 -1
  148. package/dist/featureTesting/featureScope.js +101 -20
  149. package/dist/featureTesting/featureScope.js.map +1 -1
  150. package/dist/featureTesting/mapFeatureScope.js +44 -15
  151. package/dist/featureTesting/mapFeatureScope.js.map +1 -1
  152. package/dist/featureTesting/objectiveModel.js +15 -11
  153. package/dist/featureTesting/objectiveModel.js.map +1 -1
  154. package/dist/featureTesting/resultMerge.js +16 -8
  155. package/dist/featureTesting/resultMerge.js.map +1 -1
  156. package/dist/featureTesting/sources.js +8 -5
  157. package/dist/featureTesting/sources.js.map +1 -1
  158. package/dist/featureTesting/suiteBridge.js +8 -2
  159. package/dist/featureTesting/suiteBridge.js.map +1 -1
  160. package/dist/featureTesting/synonyms.js +32 -4
  161. package/dist/featureTesting/synonyms.js.map +1 -1
  162. package/dist/featureTesting/testCaseFactory.js +27 -15
  163. package/dist/featureTesting/testCaseFactory.js.map +1 -1
  164. package/dist/featureTesting/testPlan.js +34 -12
  165. package/dist/featureTesting/testPlan.js.map +1 -1
  166. package/dist/firstRun/authStateMachine.js +1 -1
  167. package/dist/firstRun/authStateMachine.js.map +1 -1
  168. package/dist/firstRun/classifyScreen.js +9 -6
  169. package/dist/firstRun/classifyScreen.js.map +1 -1
  170. package/dist/firstRun/firstRunPlanner.js +16 -13
  171. package/dist/firstRun/firstRunPlanner.js.map +1 -1
  172. package/dist/firstRun/firstRunRunner.js +92 -31
  173. package/dist/firstRun/firstRunRunner.js.map +1 -1
  174. package/dist/firstRun/generatedDataPolicy.js +25 -15
  175. package/dist/firstRun/generatedDataPolicy.js.map +1 -1
  176. package/dist/firstRun/inputPlanner.js +45 -11
  177. package/dist/firstRun/inputPlanner.js.map +1 -1
  178. package/dist/firstRun/onboardingStateMachine.js +1 -1
  179. package/dist/firstRun/onboardingStateMachine.js.map +1 -1
  180. package/dist/firstRun/paywallPolicy.js +3 -3
  181. package/dist/firstRun/paywallPolicy.js.map +1 -1
  182. package/dist/firstRun/types.js +1 -1
  183. package/dist/firstRun/types.js.map +1 -1
  184. package/dist/fixtures/catalog.js +72 -9
  185. package/dist/fixtures/catalog.js.map +1 -1
  186. package/dist/fixtures/load.js +50 -0
  187. package/dist/fixtures/load.js.map +1 -0
  188. package/dist/flows/discover.js +2 -2
  189. package/dist/flows/discover.js.map +1 -1
  190. package/dist/flows/generate.js +68 -17
  191. package/dist/flows/generate.js.map +1 -1
  192. package/dist/flows/lint.js +88 -14
  193. package/dist/flows/lint.js.map +1 -1
  194. package/dist/flows/pack.js +21 -5
  195. package/dist/flows/pack.js.map +1 -1
  196. package/dist/flows/paths.js +57 -0
  197. package/dist/flows/paths.js.map +1 -0
  198. package/dist/flows/repair.js +176 -37
  199. package/dist/flows/repair.js.map +1 -1
  200. package/dist/flows/run.js +308 -99
  201. package/dist/flows/run.js.map +1 -1
  202. package/dist/flows/schema.js +107 -25
  203. package/dist/flows/schema.js.map +1 -1
  204. package/dist/flows/seedExec.js +8 -4
  205. package/dist/flows/seedExec.js.map +1 -1
  206. package/dist/flows/templates.js +5 -5
  207. package/dist/index.js +50 -8
  208. package/dist/index.js.map +1 -1
  209. package/dist/ios/signing.js +32 -3
  210. package/dist/ios/signing.js.map +1 -1
  211. package/dist/issues/classify.js +28 -20
  212. package/dist/issues/classify.js.map +1 -1
  213. package/dist/issues/fingerprint.js +35 -9
  214. package/dist/issues/fingerprint.js.map +1 -1
  215. package/dist/issues/index.js +93 -46
  216. package/dist/issues/index.js.map +1 -1
  217. package/dist/issues/metrics.js +6 -5
  218. package/dist/issues/metrics.js.map +1 -1
  219. package/dist/issues/recurrence.js +35 -8
  220. package/dist/issues/recurrence.js.map +1 -1
  221. package/dist/issues/report.js +12 -8
  222. package/dist/issues/report.js.map +1 -1
  223. package/dist/issues/reportBridge.js +40 -9
  224. package/dist/issues/reportBridge.js.map +1 -1
  225. package/dist/issues/schema.js +2 -2
  226. package/dist/issues/schema.js.map +1 -1
  227. package/dist/issues/sourceRevision.js +2 -2
  228. package/dist/issues/sourceRevision.js.map +1 -1
  229. package/dist/issues/store.js +110 -32
  230. package/dist/issues/store.js.map +1 -1
  231. package/dist/lib/abortScope.js +48 -0
  232. package/dist/lib/abortScope.js.map +1 -0
  233. package/dist/lib/android.js +84 -8
  234. package/dist/lib/android.js.map +1 -1
  235. package/dist/lib/coordSpace.js +1 -1
  236. package/dist/lib/coordSpace.js.map +1 -1
  237. package/dist/lib/device.js +53 -12
  238. package/dist/lib/device.js.map +1 -1
  239. package/dist/lib/gestures.js +141 -0
  240. package/dist/lib/gestures.js.map +1 -0
  241. package/dist/lib/gitignore.js +4 -3
  242. package/dist/lib/gitignore.js.map +1 -1
  243. package/dist/lib/image.js +12 -3
  244. package/dist/lib/image.js.map +1 -1
  245. package/dist/lib/lockfile.js +399 -0
  246. package/dist/lib/lockfile.js.map +1 -0
  247. package/dist/lib/needsInput.js +9 -6
  248. package/dist/lib/needsInput.js.map +1 -1
  249. package/dist/lib/png.js +4 -3
  250. package/dist/lib/png.js.map +1 -1
  251. package/dist/lib/redact.js +170 -9
  252. package/dist/lib/redact.js.map +1 -1
  253. package/dist/lib/result.js +94 -10
  254. package/dist/lib/result.js.map +1 -1
  255. package/dist/lib/schemaHash.js +7 -5
  256. package/dist/lib/schemaHash.js.map +1 -1
  257. package/dist/lib/sensitive.js +6 -3
  258. package/dist/lib/sensitive.js.map +1 -1
  259. package/dist/lib/simctl.js +3 -3
  260. package/dist/lib/simctl.js.map +1 -1
  261. package/dist/lib/spawn.js +78 -17
  262. package/dist/lib/spawn.js.map +1 -1
  263. package/dist/lib/toolAnnotations.js +114 -0
  264. package/dist/lib/toolAnnotations.js.map +1 -0
  265. package/dist/lib/wda.js +321 -25
  266. package/dist/lib/wda.js.map +1 -1
  267. package/dist/lib/wdaConfig.js +12 -5
  268. package/dist/lib/wdaConfig.js.map +1 -1
  269. package/dist/lib/wdaTune.js +52 -23
  270. package/dist/lib/wdaTune.js.map +1 -1
  271. package/dist/mobileAudit/checks.js +150 -28
  272. package/dist/mobileAudit/checks.js.map +1 -1
  273. package/dist/mobileAudit/evidence.js +4 -4
  274. package/dist/mobileAudit/evidence.js.map +1 -1
  275. package/dist/mobileAudit/profiles.js +121 -20
  276. package/dist/mobileAudit/profiles.js.map +1 -1
  277. package/dist/mobileAudit/results.js +9 -4
  278. package/dist/mobileAudit/results.js.map +1 -1
  279. package/dist/mobileAudit/runner.js +214 -35
  280. package/dist/mobileAudit/runner.js.map +1 -1
  281. package/dist/oracle/auth.js +1 -1
  282. package/dist/oracle/auth.js.map +1 -1
  283. package/dist/oracle/failures.js +1085 -145
  284. package/dist/oracle/failures.js.map +1 -1
  285. package/dist/oracle/health.js +148 -26
  286. package/dist/oracle/health.js.map +1 -1
  287. package/dist/oracle/locator.js +148 -19
  288. package/dist/oracle/locator.js.map +1 -1
  289. package/dist/oracle/record.js +3 -3
  290. package/dist/oracle/record.js.map +1 -1
  291. package/dist/orchestration/envelope.js +2 -2
  292. package/dist/orchestration/envelope.js.map +1 -1
  293. package/dist/orchestration/goal.js +7 -13
  294. package/dist/orchestration/goal.js.map +1 -1
  295. package/dist/orchestration/testThis/execute.js +167 -0
  296. package/dist/orchestration/testThis/execute.js.map +1 -0
  297. package/dist/orchestration/testThis/pipeline.js +413 -0
  298. package/dist/orchestration/testThis/pipeline.js.map +1 -0
  299. package/dist/orchestration/testThis/plan.js +519 -0
  300. package/dist/orchestration/testThis/plan.js.map +1 -0
  301. package/dist/orchestration/testThis/sessionIntent.js +72 -0
  302. package/dist/orchestration/testThis/sessionIntent.js.map +1 -0
  303. package/dist/orchestration/testThis/terminal.js +136 -0
  304. package/dist/orchestration/testThis/terminal.js.map +1 -0
  305. package/dist/orchestration/testThis/types.js +12 -0
  306. package/dist/orchestration/testThis/types.js.map +1 -0
  307. package/dist/plan/plan.js +9 -9
  308. package/dist/plan/plan.js.map +1 -1
  309. package/dist/prompts/index.js +24 -24
  310. package/dist/prompts/index.js.map +1 -1
  311. package/dist/report/coverage.js +0 -1
  312. package/dist/report/coverage.js.map +1 -1
  313. package/dist/report/evidence.js.map +1 -1
  314. package/dist/report/export.js +449 -72
  315. package/dist/report/export.js.map +1 -1
  316. package/dist/report/findingsDedupe.js +41 -0
  317. package/dist/report/findingsDedupe.js.map +1 -0
  318. package/dist/report/flake.js +13 -14
  319. package/dist/report/flake.js.map +1 -1
  320. package/dist/report/history.js +72 -38
  321. package/dist/report/history.js.map +1 -1
  322. package/dist/report/policy.js +18 -7
  323. package/dist/report/policy.js.map +1 -1
  324. package/dist/report/qaLevel.js +10 -16
  325. package/dist/report/qaLevel.js.map +1 -1
  326. package/dist/report/readiness.js +42 -12
  327. package/dist/report/readiness.js.map +1 -1
  328. package/dist/report/sarifSources.js +160 -0
  329. package/dist/report/sarifSources.js.map +1 -0
  330. package/dist/report/summary.js +2 -2
  331. package/dist/report/summary.js.map +1 -1
  332. package/dist/report/testCatalog.js +4 -4
  333. package/dist/report/testCatalog.js.map +1 -1
  334. package/dist/report/timing.js +23 -23
  335. package/dist/report/timing.js.map +1 -1
  336. package/dist/report/toolHealth.js +124 -0
  337. package/dist/report/toolHealth.js.map +1 -0
  338. package/dist/server.js +501 -69
  339. package/dist/server.js.map +1 -1
  340. package/dist/services/automationGenerate.js +8 -2
  341. package/dist/services/automationGenerate.js.map +1 -1
  342. package/dist/services/build.js +10 -4
  343. package/dist/services/build.js.map +1 -1
  344. package/dist/services/flowGenerate.js +75 -0
  345. package/dist/services/flowGenerate.js.map +1 -0
  346. package/dist/services/preflight.js +40 -8
  347. package/dist/services/preflight.js.map +1 -1
  348. package/dist/services/prepareAndroid.js +92 -18
  349. package/dist/services/prepareAndroid.js.map +1 -1
  350. package/dist/services/prepareIos.js +94 -17
  351. package/dist/services/prepareIos.js.map +1 -1
  352. package/dist/services/report.js +271 -80
  353. package/dist/services/report.js.map +1 -1
  354. package/dist/services/smoke.js +68 -22
  355. package/dist/services/smoke.js.map +1 -1
  356. package/dist/services/suiteGenerate.js +43 -6
  357. package/dist/services/suiteGenerate.js.map +1 -1
  358. package/dist/services/testSuiteKnowledge.js +78 -33
  359. package/dist/services/testSuiteKnowledge.js.map +1 -1
  360. package/dist/session/attach.js +284 -4
  361. package/dist/session/attach.js.map +1 -1
  362. package/dist/session/processRegistry.js +433 -0
  363. package/dist/session/processRegistry.js.map +1 -0
  364. package/dist/session/progress.js +1 -1
  365. package/dist/session/progress.js.map +1 -1
  366. package/dist/session/retention.js +201 -0
  367. package/dist/session/retention.js.map +1 -0
  368. package/dist/session/store.js +459 -59
  369. package/dist/session/store.js.map +1 -1
  370. package/dist/snapshot/overlays.js +60 -10
  371. package/dist/snapshot/overlays.js.map +1 -1
  372. package/dist/snapshot/parse.js +30 -12
  373. package/dist/snapshot/parse.js.map +1 -1
  374. package/dist/snapshot/present.js +36 -6
  375. package/dist/snapshot/present.js.map +1 -1
  376. package/dist/snapshot/settle.js +39 -9
  377. package/dist/snapshot/settle.js.map +1 -1
  378. package/dist/state/consent.js +99 -0
  379. package/dist/state/consent.js.map +1 -0
  380. package/dist/state/profile.js +82 -11
  381. package/dist/state/profile.js.map +1 -1
  382. package/dist/suite/compile.js +15 -6
  383. package/dist/suite/compile.js.map +1 -1
  384. package/dist/suite/lint.js +22 -4
  385. package/dist/suite/lint.js.map +1 -1
  386. package/dist/suite/pom.js +75 -44
  387. package/dist/suite/pom.js.map +1 -1
  388. package/dist/suite/secretGuard.js +266 -0
  389. package/dist/suite/secretGuard.js.map +1 -0
  390. package/dist/suite/testcase.js +15 -11
  391. package/dist/suite/testcase.js.map +1 -1
  392. package/dist/testSuite/exporter.js +7 -3
  393. package/dist/testSuite/exporter.js.map +1 -1
  394. package/dist/testSuite/generator.js +43 -14
  395. package/dist/testSuite/generator.js.map +1 -1
  396. package/dist/testSuite/history.js +1 -1
  397. package/dist/testSuite/history.js.map +1 -1
  398. package/dist/testSuite/issueLinks.js +3 -3
  399. package/dist/testSuite/issueLinks.js.map +1 -1
  400. package/dist/testSuite/lint.js +4 -4
  401. package/dist/testSuite/lint.js.map +1 -1
  402. package/dist/testSuite/merge.js +13 -7
  403. package/dist/testSuite/merge.js.map +1 -1
  404. package/dist/testSuite/schema.js +21 -16
  405. package/dist/testSuite/schema.js.map +1 -1
  406. package/dist/testSuite/store.js +12 -4
  407. package/dist/testSuite/store.js.map +1 -1
  408. package/dist/testSuite/traceability.js +2 -2
  409. package/dist/testSuite/traceability.js.map +1 -1
  410. package/dist/tools/act.js +868 -174
  411. package/dist/tools/act.js.map +1 -1
  412. package/dist/tools/agent.js +521 -112
  413. package/dist/tools/agent.js.map +1 -1
  414. package/dist/tools/appControl.js +82 -19
  415. package/dist/tools/appControl.js.map +1 -1
  416. package/dist/tools/appMap.js +393 -189
  417. package/dist/tools/appMap.js.map +1 -1
  418. package/dist/tools/build.js +92 -51
  419. package/dist/tools/build.js.map +1 -1
  420. package/dist/tools/bundletool.js +141 -40
  421. package/dist/tools/bundletool.js.map +1 -1
  422. package/dist/tools/clearOverlay.js +98 -18
  423. package/dist/tools/clearOverlay.js.map +1 -1
  424. package/dist/tools/device.js +108 -19
  425. package/dist/tools/device.js.map +1 -1
  426. package/dist/tools/doctor.js +98 -35
  427. package/dist/tools/doctor.js.map +1 -1
  428. package/dist/tools/explore.js +110 -42
  429. package/dist/tools/explore.js.map +1 -1
  430. package/dist/tools/featureTesting.js +152 -130
  431. package/dist/tools/featureTesting.js.map +1 -1
  432. package/dist/tools/firstRun.js +94 -66
  433. package/dist/tools/firstRun.js.map +1 -1
  434. package/dist/tools/flow.js +347 -132
  435. package/dist/tools/flow.js.map +1 -1
  436. package/dist/tools/flowRepair.js +42 -10
  437. package/dist/tools/flowRepair.js.map +1 -1
  438. package/dist/tools/generate.js +199 -0
  439. package/dist/tools/generate.js.map +1 -0
  440. package/dist/tools/getArtifact.js +37 -8
  441. package/dist/tools/getArtifact.js.map +1 -1
  442. package/dist/tools/health.js +17 -12
  443. package/dist/tools/health.js.map +1 -1
  444. package/dist/tools/ios.js +148 -194
  445. package/dist/tools/ios.js.map +1 -1
  446. package/dist/tools/issues.js +256 -171
  447. package/dist/tools/issues.js.map +1 -1
  448. package/dist/tools/jobs.js +55 -11
  449. package/dist/tools/jobs.js.map +1 -1
  450. package/dist/tools/metro.js +84 -38
  451. package/dist/tools/metro.js.map +1 -1
  452. package/dist/tools/mobileAudit.js +83 -26
  453. package/dist/tools/mobileAudit.js.map +1 -1
  454. package/dist/tools/network.js +36 -14
  455. package/dist/tools/network.js.map +1 -1
  456. package/dist/tools/note.js +31 -17
  457. package/dist/tools/note.js.map +1 -1
  458. package/dist/tools/prepareIosTarget.js +31 -14
  459. package/dist/tools/prepareIosTarget.js.map +1 -1
  460. package/dist/tools/prepareTarget.js +193 -47
  461. package/dist/tools/prepareTarget.js.map +1 -1
  462. package/dist/tools/report.js +16 -8
  463. package/dist/tools/report.js.map +1 -1
  464. package/dist/tools/resolveArtifact.js +12 -12
  465. package/dist/tools/resolveArtifact.js.map +1 -1
  466. package/dist/tools/resolveTarget.js +81 -18
  467. package/dist/tools/resolveTarget.js.map +1 -1
  468. package/dist/tools/screenRecord.js +85 -20
  469. package/dist/tools/screenRecord.js.map +1 -1
  470. package/dist/tools/screenshot.js +42 -18
  471. package/dist/tools/screenshot.js.map +1 -1
  472. package/dist/tools/smoke.js +29 -12
  473. package/dist/tools/smoke.js.map +1 -1
  474. package/dist/tools/snapshot.js +157 -107
  475. package/dist/tools/snapshot.js.map +1 -1
  476. package/dist/tools/startSession.js +117 -84
  477. package/dist/tools/startSession.js.map +1 -1
  478. package/dist/tools/suite.js +391 -310
  479. package/dist/tools/suite.js.map +1 -1
  480. package/dist/tools/testSuite.js +112 -36
  481. package/dist/tools/testSuite.js.map +1 -1
  482. package/dist/tools/testThis.js +35 -802
  483. package/dist/tools/testThis.js.map +1 -1
  484. package/dist/tools/visual.js +698 -116
  485. package/dist/tools/visual.js.map +1 -1
  486. package/dist/tools/wait.js +9 -23
  487. package/dist/tools/wait.js.map +1 -1
  488. package/dist/tools/wda.js +312 -54
  489. package/dist/tools/wda.js.map +1 -1
  490. package/dist/version.js +37 -64
  491. package/dist/version.js.map +1 -1
  492. package/dist/visual/ocr.js +65 -8
  493. package/dist/visual/ocr.js.map +1 -1
  494. package/dist/visual/provider.js +87 -15
  495. package/dist/visual/provider.js.map +1 -1
  496. package/docs/README.md +24 -10
  497. package/docs/ci-reports.md +328 -0
  498. package/docs/concepts.md +227 -0
  499. package/docs/flows.md +153 -0
  500. package/docs/mcp-server.md +210 -104
  501. package/docs/physical-devices.md +84 -0
  502. package/docs/tools.md +808 -217
  503. package/package.json +16 -6
  504. package/dist/appMap/diff.js +0 -60
  505. package/dist/appMap/diff.js.map +0 -1
  506. package/dist/automation/maestroIr.js +0 -282
  507. package/dist/automation/maestroIr.js.map +0 -1
  508. package/dist/interop/maestro.js +0 -151
  509. package/dist/interop/maestro.js.map +0 -1
  510. package/dist/tools/assertVisual.js +0 -74
  511. package/dist/tools/assertVisual.js.map +0 -1
  512. package/dist/tools/automationGenerate.js +0 -394
  513. package/dist/tools/automationGenerate.js.map +0 -1
  514. package/dist/tools/capabilities.js +0 -209
  515. package/dist/tools/capabilities.js.map +0 -1
  516. package/dist/tools/detectContext.js +0 -41
  517. package/dist/tools/detectContext.js.map +0 -1
  518. package/dist/tools/flowGenerate.js +0 -55
  519. package/dist/tools/flowGenerate.js.map +0 -1
  520. package/dist/tools/history.js +0 -56
  521. package/dist/tools/history.js.map +0 -1
  522. package/dist/tools/idling.js +0 -104
  523. package/dist/tools/idling.js.map +0 -1
  524. package/dist/tools/inputCapabilities.js +0 -30
  525. package/dist/tools/inputCapabilities.js.map +0 -1
  526. package/dist/tools/locator.js +0 -57
  527. package/dist/tools/locator.js.map +0 -1
  528. package/dist/tools/maestro.js +0 -78
  529. package/dist/tools/maestro.js.map +0 -1
  530. package/dist/tools/permissions.js +0 -149
  531. package/dist/tools/permissions.js.map +0 -1
  532. package/dist/tools/plan.js +0 -49
  533. package/dist/tools/plan.js.map +0 -1
  534. package/dist/tools/screenInfo.js +0 -70
  535. package/dist/tools/screenInfo.js.map +0 -1
  536. package/dist/tools/seed.js +0 -101
  537. package/dist/tools/seed.js.map +0 -1
  538. package/dist/tools/state.js +0 -170
  539. package/dist/tools/state.js.map +0 -1
  540. package/dist/tools/visualText.js +0 -61
  541. package/dist/tools/visualText.js.map +0 -1
package/docs/flows.md ADDED
@@ -0,0 +1,153 @@
1
+ # Flows
2
+
3
+ A flow is a replayable YAML script of steps under `.swipium/flows/`. Flows are the Flow V2 format: selector-bound input, visual steps, device-relative gestures, waits, setup and teardown, and a `structured`, `visual`, or `auto` mode. This page covers the file format, variables, starter templates, compiling and repairing, and the CI policy. The tools themselves (`qa_flow_check`, `qa_flow_run`, `qa_flow_compile`, `qa_flow_repair`, `qa_smoke`) are in the [Tool Reference](tools.md#flows).
4
+
5
+ **Contents**: [Example](#example) · [File format](#file-format) · [Step reference](#step-reference) · [Variables](#variables) · [Starter templates](#starter-templates) · [Compile and repair](#compile-and-repair) · [CI policy](#ci-policy)
6
+
7
+ ## Example
8
+
9
+ `.swipium/flows/login-smoke.yaml`:
10
+
11
+ ```yaml
12
+ name: login_smoke
13
+ mode: structured
14
+ fixtures:
15
+ - test_account
16
+ setup:
17
+ - prepareTarget
18
+ steps:
19
+ - waitForVisible: "Email"
20
+ - inputText:
21
+ into: "Email"
22
+ text: "${SWIPIUM_TEST_EMAIL}"
23
+ - inputText:
24
+ into: "Password"
25
+ text: "${SWIPIUM_TEST_PASSWORD}"
26
+ - tap: "Sign in"
27
+ - waitForVisible:
28
+ text: "Home"
29
+ timeoutMs: 12000
30
+ - assertVisible: "Home"
31
+ ```
32
+
33
+ Validate it with `qa_flow_check {flow:"login-smoke"}`, then run it on a prepared session with `qa_flow_run {sessionId, flow:"login-smoke"}`. The password is typed but treated as a secret, because its variable name contains `pass`.
34
+
35
+ ## File format
36
+
37
+ A flow is a YAML map with a non-empty `name` and a non-empty `steps` list.
38
+
39
+ | Key | Meaning |
40
+ | --- | --- |
41
+ | `name` | Required. |
42
+ | `steps` | Required, non-empty. Runs are fail-fast: the first failing step stops the flow. Mutating steps are never retried automatically. |
43
+ | `setup` | Steps that run before `steps`. |
44
+ | `teardown` | Steps that always run afterwards, even after a failure. |
45
+ | `mode` | `structured` (default: needs a UI tree), `visual` (screenshot-based), or `auto`. A structured flow on an iOS Simulator without WDA, or in a visual-fallback session, is refused with `BACKEND_UNSUPPORTED`. |
46
+ | `appId` | The app `prepareTarget` and `restartApp` act on (default: the session's app). |
47
+ | `fixtures` | Names of fixtures the flow needs (from `qa_start_session` or `.swipium/fixtures.json`). |
48
+ | `budgetProfile` | A budget profile label, such as `guardrail` or `full_smoke`. |
49
+
50
+ Each step is either a bare word (`prepareTarget`, `restartApp`, `waitForIdle`, `clearOverlay`, `networkOffline`, `networkOnline`) or a map with exactly one key. Variables are referenced inline as `${NAME}`; there is no top-level variables block.
51
+
52
+ **Selectors** (in `tap`, `inputText into`, `assertVisible`, `waitForVisible`, and similar steps):
53
+
54
+ - Plain text matches an element's text, content description, or id (case-insensitive substring).
55
+ - `id=<resource-id>` matches an Android resource id.
56
+ - `accessibility id=…`, `name=…`, `predicate string=…`, and `class chain=…` are native WDA selectors on iOS.
57
+
58
+ Prefer durable ids (`testID`, `accessibilityIdentifier`, resource ids) over visible text; `qa_flow_check` warns about platform-specific or brittle locators.
59
+
60
+ ## Step reference
61
+
62
+ | Step | Form | What it does |
63
+ | --- | --- | --- |
64
+ | `prepareTarget` | bare | Launches the flow's app and waits for the screen to settle. |
65
+ | `restartApp` | bare | Force-stops and relaunches the app. Mutating. |
66
+ | `tap` | `tap: "<selector>"` | Taps an element. |
67
+ | `tapAt` | `tapAt: [x, y]` | Taps a coordinate. Coordinate-only flows are flagged as brittle. |
68
+ | `tapImage` | `tapImage: <png>` or `{template, minScore}` | Template-matches a PNG and taps it. |
69
+ | `tapOcrText` | `tapOcrText: "<text>"` or `{text, minConfidence}` | Finds text by OCR and taps it. Needs an OCR provider. |
70
+ | `inputText` | `inputText: "<text>"` or `{into, text, secret}` | Types text; `into` focuses a field first. `secret` defaults to true when the text references a credential-like variable. |
71
+ | `assertVisible` | `assertVisible: "<selector>"` | Fails with `ASSERTION_FAILED` when not visible. |
72
+ | `assertNotVisible` | `assertNotVisible: "<selector>"` | Fails when visible. |
73
+ | `assertImage` | `assertImage: <png>` or `{template, minScore}` | Asserts a PNG template is on screen. |
74
+ | `assertOcrText` | `assertOcrText: "<text>"` or `{text, minConfidence}` | Asserts text by OCR. |
75
+ | `assertVisual` | `assertVisual: "<description>"` | Captures screenshot evidence and records a visual checkpoint for a human. It does not fail. |
76
+ | `assertDiff` | `assertDiff: <baseline>` or `{baseline, threshold}` | Compares the screen to a saved `qa_visual` baseline. |
77
+ | `swipe` | `swipe: up` or `{direction, area, distance}` | Device-relative swipe. `area` is `center`, `top`, `bottom`, `left`, or `right`; `distance` is a fraction of the screen (default 0.6). |
78
+ | `scrollTo` | `scrollTo: "<selector>"` | Swipes until the target is visible (up to 8 swipes). |
79
+ | `press` | `press: back`, `home`, or `enter` | Presses a key. |
80
+ | `openUrl` | `openUrl: "<url>"` | Opens a deep link or URL. Mutating when the URL contains a `${VAR}`. |
81
+ | `wait` | `wait: <ms>` or `{text}` / `{id}` | Waits a fixed time, or for an element. |
82
+ | `waitForIdle` | bare, or `waitForIdle: <timeoutMs>` | Waits for the UI to settle. |
83
+ | `waitForVisible` | `waitForVisible: "<selector>"` or `{text` / `id` / `"accessibility id", timeoutMs}` | Waits for an element to appear. |
84
+ | `clearOverlay` | bare | Clears a blocking overlay (see below). |
85
+ | `networkOffline`, `networkOnline` | bare | Turns airplane mode on or off (Android 11+). Mutating. |
86
+ | `seed` | `seed: <fixture>` | Runs the fixture's `seed` spec (deeplink, script, or API call). Mutating. |
87
+ | `note` | `note: "<reason>"` or `{outcome, reason}` | Records a workflow outcome (`pass` by default). |
88
+ | `screenshot` | `screenshot: "<reason>"` | Captures evidence. |
89
+
90
+ **`clearOverlay`** hides an open keyboard and does nothing else. Otherwise, on Android it presses BACK only when a BACK-dismissible overlay is actually open (a dialog, sheet, permission prompt, or RN LogBox or RedBox), never on a bare screen and never for a snackbar or banner; with nothing to clear it reports `nothingCleared:true`. On iOS it dismisses alerts and sheets with the native alert API. When the backend has no alert API or the overlay survives, the step reports `nothingCleared:false` with a note instead of claiming success.
91
+
92
+ **Mutating steps** are `networkOffline`, `networkOnline`, `seed`, `restartApp`, and `openUrl` with a `${VAR}` in its URL. They, and the OCR steps `tapOcrText` and `assertOcrText` (which send screenshots to an external provider), need the `flow_mutation_run` consent in `qa_flow_run` (risk high for script seeds, otherwise medium). `qa_smoke` never runs such a flow implicitly: it records it as `blocked` (category `destructive_refused`) with a pointer to `qa_flow_run`. OCR steps are refused in sensitive sessions (`UNSAFE_ACTION_REFUSED`).
93
+
94
+ **Paths**: `tapImage` and `assertImage` templates and `assertDiff` baselines must resolve (after symlinks) inside the project root, otherwise the step fails with `UNSAFE_ACTION_REFUSED`.
95
+
96
+ **Sensitive sessions**: `screenshot`, `assertVisual`, and failure evidence are not captured; the step detail says so, and an `assertVisual` checkpoint is recorded as `skipped`.
97
+
98
+ ## Variables
99
+
100
+ `${NAME}` resolves in this order:
101
+
102
+ 1. **Explicit variables**: `qa_flow_run {variables:{…}}` (or `qa_smoke {variables}`).
103
+ 2. **Stored session inputs**: values supplied through a needs-input answer (`qa_continue_from_blocker`) or first-run credentials. Values are never echoed; only their names are listed in `notes`.
104
+ 3. **The server environment, for `SWIPIUM_*` names only.** Any other environment variable is never read, because a flow file can come from an untrusted repository. The step fails with `MISSING_FIXTURE` and a message such as `Variables not available: HOME (flows only read SWIPIUM_* environment variables; pass it via qa_flow_run { variables } or rename it SWIPIUM_HOME)`.
105
+
106
+ A missing variable is not locator drift, so the failure does not point at `qa_flow_repair`.
107
+
108
+ **Secret names**: a variable whose name contains `pass`, `secret`, `token`, `otp`, `pin`, `cvv`, `key`, or `code` (case-insensitive) is a credential. Its resolved value joins the session's redaction set and is scrubbed everywhere, and `inputText` treats it as secret. So `SWIPIUM_TEST_PASSWORD` and `SWIPIUM_VERIFICATION_CODE` are secrets; `SWIPIUM_TEST_EMAIL` is not. See [Secrets and redaction](concepts.md#secrets-and-redaction).
109
+
110
+ Set `SWIPIUM_*` test data in the MCP server's `env` ([environment variables](../README.md#configuration--environment-variables)).
111
+
112
+ ## Starter templates
113
+
114
+ `swipium init flows [--root <dir>] [--force]` writes starter flows under `.swipium/flows/` (launch smoke, login smoke, iOS WDA smoke, offline, permission prompt, deep link, saved-item persistence, and a visual map or canvas smoke) plus a `smoke` pack in `.swipium/packs/smoke.yaml`. Existing files are kept unless you pass `--force`. Edit the selectors and variables, then validate each flow with `qa_flow_check` before running it.
115
+
116
+ ## Compile and repair
117
+
118
+ - **Record, then generate**: `qa_generate {target:"flow"}` turns a session's recorded actions into one flow; `qa_generate {target:"suite"}` writes a POM suite and compiles it into flows. Recorded secrets become `${SWIPIUM_*}` placeholders.
119
+ - **Compile a suite on disk**: `qa_flow_compile {suite}` (or `swipium suite compile` in CI) resolves page-object refs to selectors, carries variables, writes `.swipium/flows/<slug>.yaml` plus a copy under `.swipium/compiled/`, and validates each flow. It needs no session, which makes it the path for committed or hand-edited suites.
120
+ - **Repair a failed step**: when `qa_flow_run` fails on a locator, its `nextSteps` point at `qa_flow_repair {flow, failedStep}`. The repair proposes a stronger locator from the current screen, restricted to the failed target's role, and can patch the flow file (`apply:true`) at high or medium confidence. Details: [qa_flow_repair](tools.md#qa_flow_repair).
121
+
122
+ ## CI policy
123
+
124
+ `qa_flow_check {ci:true}`, the flow CI preflight, and the report release gate (`qa_report` CI exports and `swipium report --fail-on-gate`) read an optional `.swipium/policy.json`:
125
+
126
+ ```json
127
+ {
128
+ "ciAllowMutations": ["network", "seed", "restart"],
129
+ "blockOn": ["native_crash", "error_boundary", "anr"],
130
+ "warnOn": ["visual_diff", "missing_fixture"],
131
+ "ignoreKnown": ["REVENUECAT_BILLING_UNAVAILABLE_ON_EMULATOR"]
132
+ }
133
+ ```
134
+
135
+ ### Mutations in CI
136
+
137
+ `ciAllowMutations` lists the mutating steps a CI run may execute. Without a policy file, or with an empty list, every mutating step is flagged. Tokens are matched case-insensitively with punctuation ignored:
138
+
139
+ | Step | Accepted tokens |
140
+ | --- | --- |
141
+ | `networkOffline`, `networkOnline` | the step name, `network`, `network_toggle`, `connectivity` |
142
+ | `seed` | `seed`, `seeds`, `fixtures`, `fixture_seed` |
143
+ | `restartApp` | `restart_app`, `restart`, `lifecycle`, `app_control` |
144
+ | `openUrl` with a `${VAR}` | `open_url` |
145
+ | any | `all`, `*`, `mutating_steps` |
146
+
147
+ The CI variable preflight also reports every `${VAR}` that a CI run cannot resolve: names outside `SWIPIUM_*` always count as missing, because flows never read them from the environment.
148
+
149
+ ### Release gate
150
+
151
+ `blockOn`, `warnOn`, and `ignoreKnown` decide which failures block a release. Their rules (including that, without a policy file or with an empty `blockOn`, every failure blocks and `warnOn` is ignored) are in [ci-reports.md: Release-gate policy](ci-reports.md#release-gate-policy). Tokens name failure codes such as `native_crash` or `error_boundary`.
152
+
153
+ Codes are listed in the [failure-code catalog](tools.md#failure-codes). Export formats and CI recipes are in [ci-reports.md](ci-reports.md).
@@ -1,137 +1,243 @@
1
- # MCP Server
1
+ # MCP server reference
2
2
 
3
- Swipium runs as a local stdio MCP server. The MCP client starts the process and sends tool calls over stdin and stdout.
3
+ Swipium is a local stdio MCP server. Your MCP client starts it as a child process and talks
4
+ JSON-RPC over its stdin and stdout. Nothing listens on the network.
4
5
 
5
6
  ## Requirements
6
7
 
7
8
  - Node.js 20 or newer.
8
- - A mobile app repository as the MCP `cwd`.
9
- - Android Studio for Android Emulator workflows.
10
- - Xcode for iOS Simulator workflows.
9
+ - Host OS: macOS for the iOS Simulator and Android; Linux for Android. Android on Windows is
10
+ experimental and untested.
11
+ - Android: platform-tools (`adb`), the Android Emulator package, and at least one AVD, usually
12
+ installed through Android Studio. Build-tools (`aapt2`) are optional; Swipium uses them to read
13
+ an APK's package name and SDK level. See [How Android tools are found](#how-android-tools-are-found).
14
+ - iOS: Xcode with an iOS Simulator runtime and at least one simulator. WebDriverAgent is needed for
15
+ the structured UI tree, taps, typing and swipes. Visual-only checks work through `simctl` without
16
+ it: `qa_visual` baselines and diffs, OCR `find_text`, and template `find_image`.
17
+
18
+ ### How Android tools are found
19
+
20
+ Swipium looks for an Android SDK in `$ANDROID_HOME`, then `$ANDROID_SDK_ROOT`, then the default
21
+ directory (`~/Library/Android/sdk` on macOS, `~/Android/Sdk` on Linux,
22
+ `%LOCALAPPDATA%\Android\Sdk` on Windows).
23
+
24
+ - **`adb`**: the copy on `PATH` is used when there is one. Otherwise Swipium appends the SDK's
25
+ `platform-tools` to its own `PATH` at startup. It never shadows your `adb`, because a different
26
+ adb version would kill the adb server you are running.
27
+ - **`emulator`**: booting an AVD runs the SDK copy (`emulator/emulator`) first, and falls back to
28
+ `emulator` on `PATH` only when no SDK copy exists. Listing AVDs and the `qa_doctor` check follow
29
+ the `adb` rule (`PATH` first, then the SDK copy).
30
+ - **`aapt2`**: taken from the newest version under the SDK's `build-tools`. There is no `PATH`
31
+ fallback.
32
+
33
+ This matters for GUI-launched clients (Claude Desktop, Cursor started from the Dock), which don't
34
+ inherit your shell `PATH`. If Swipium still can't find the tools, set `ANDROID_HOME` in the server
35
+ `env`.
36
+
37
+ ## Server command
38
+
39
+ `npx -y swipium` is the portable command. After `npm install -g swipium` you can run `swipium`
40
+ instead. From a source checkout, run `npm run build` and use
41
+ `node /absolute/path/to/swipium/dist/index.js`.
42
+
43
+ | Invocation | Behavior |
44
+ | --- | --- |
45
+ | `swipium` or `swipium serve` | Runs the stdio MCP server. |
46
+ | `swipium --stdio` (flags only, no subcommand) | Runs the server and warns on stderr that the flags were ignored. |
47
+ | `swipium init`, `verify`, `scan`, `suite`, `report`, `gc` | CLI subcommands. See `swipium --help`. |
48
+ | `swipium <unknown word>` | Prints usage and exits with status 2 instead of starting a server. |
49
+
50
+ ## Project root
51
+
52
+ Every tool call works in one app repository. Swipium takes it from the `projectRoot` argument, then
53
+ the client's MCP roots, then `SWIPIUM_PROJECT_ROOT`, then `CLAUDE_PROJECT_DIR`, then the server's
54
+ working directory when that looks like an app. The full rules are in
55
+ [concepts.md](concepts.md#project-root). For client setup, the practical rule is: if your client
56
+ neither sends MCP roots nor lets you set a `cwd` (Claude Desktop, Windsurf), set
57
+ `SWIPIUM_PROJECT_ROOT` in the server `env`.
58
+
59
+ ## Client setup
60
+
61
+ `swipium init <client>` prints the exact registration and changes nothing. Add `--apply` to
62
+ perform it. After a successful apply it runs `swipium verify`. Options: `--scope local|user|project`
63
+ (default `local`) and `--cwd <app dir>` (default: the directory you run it from).
64
+
65
+ | Client | `swipium init` does | Where it lands |
66
+ | --- | --- | --- |
67
+ | Claude Code | Runs `claude mcp add swipium [--scope …] -- <command>` | `local` / `user`: `~/.claude.json`; `project`: `.mcp.json` |
68
+ | Codex | Appends a `[mcp_servers.swipium]` block with `cwd` and timeouts (refuses if `--cwd` doesn't exist; leaves an existing block alone) | `~/.codex/config.toml` |
69
+ | Gemini CLI | Runs `gemini mcp add --scope project\|user swipium …`; prints a manual block if that fails | `.gemini/settings.json` (project, the default), `~/.gemini/settings.json` (`--scope user`) |
70
+ | Cursor | Merges a `swipium` entry under `mcpServers` | `.cursor/mcp.json` (for all projects, add the same entry to `~/.cursor/mcp.json` yourself) |
71
+ | VS Code | Merges a `swipium` entry under `servers`; prints a `code --add-mcp …` line for the user profile | `.vscode/mcp.json` |
72
+ | Claude Desktop | Not supported by `init`; configure manually | `claude_desktop_config.json` |
73
+ | Windsurf | Not supported by `init`; configure manually | `mcp_config.json` (Cascade > MCP settings) |
74
+
75
+ Which command gets written:
76
+
77
+ - **Team-shared files** get the portable `npx -y swipium`. That covers Claude `--scope project`,
78
+ Gemini project scope, `.cursor/mcp.json` and `.vscode/mcp.json`.
79
+ - **Machine-local registrations** get this machine's `node` and the absolute path of the installed
80
+ `dist/index.js`. That covers Claude local and user scope, Gemini user scope, and Codex. The
81
+ exception is when Swipium itself runs from the npx cache; that path would disappear, so these
82
+ also get `npx -y swipium`.
83
+
84
+ For Cursor and VS Code, `init` refuses to edit a file that isn't plain JSON (for example JSONC with
85
+ comments), prints the entry to add by hand, and exits with status 2. An existing `swipium` entry
86
+ is left unchanged.
87
+
88
+ ### Manual configuration
89
+
90
+ Claude Code:
11
91
 
12
- ## Server Command
92
+ ```bash
93
+ claude mcp add swipium --scope project -- npx -y swipium
94
+ ```
95
+
96
+ Codex (`~/.codex/config.toml`). Codex's defaults of 10 s to start and 60 s per tool call are too
97
+ short for a first `npx` run and for builds and boots:
98
+
99
+ ```toml
100
+ [mcp_servers.swipium]
101
+ command = "npx"
102
+ args = ["-y", "swipium"]
103
+ cwd = "/absolute/path/to/your/mobile-app"
104
+ startup_timeout_sec = 30
105
+ tool_timeout_sec = 600
106
+ ```
107
+
108
+ Known caveat: in the Codex Desktop app, custom stdio MCP tools can show up in `/mcp` without being
109
+ available in threads ([openai/codex#19425](https://github.com/openai/codex/issues/19425)). If that
110
+ happens, use the Codex CLI.
111
+
112
+ Gemini CLI:
113
+
114
+ ```bash
115
+ gemini mcp add --scope project swipium npx -- -y swipium
116
+ ```
117
+
118
+ The `--` keeps Gemini from reading `-y` as its own flag. `init gemini` also suggests
119
+ `"timeout": 600000` in the settings entry.
13
120
 
14
- No global install:
121
+ Cursor (`.cursor/mcp.json`). For VS Code (`.vscode/mcp.json`), use the same entry under a top-level
122
+ `"servers"` key instead of `"mcpServers"`. This is the entry `swipium init cursor` and
123
+ `swipium init vscode` write:
15
124
 
16
- ```jsonc
17
- {s
125
+ ```json
126
+ {
18
127
  "mcpServers": {
19
128
  "swipium": {
129
+ "type": "stdio",
20
130
  "command": "npx",
21
131
  "args": ["-y", "swipium"],
22
- "cwd": "/absolute/path/to/your/mobile-app",
23
- "timeout": 600000
132
+ "env": { "SWIPIUM_PROJECT_ROOT": "${workspaceFolder}" }
24
133
  }
25
134
  }
26
135
  }
27
136
  ```
28
137
 
29
- Global install:
138
+ Why the entry sets `SWIPIUM_PROJECT_ROOT` even though these editors can send MCP roots: roots come
139
+ first in the resolution order, so when the editor sends them, Swipium uses them and ignores the
140
+ variable. The variable is a fallback for an editor version or window that sends no roots. The editor
141
+ replaces `${workspaceFolder}` with the open folder; if it is left unexpanded, the value is not an
142
+ absolute path and Swipium skips it.
143
+
144
+ Claude Desktop and Windsurf:
30
145
 
31
- ```jsonc
146
+ ```json
32
147
  {
33
148
  "mcpServers": {
34
149
  "swipium": {
35
- "command": "swipium",
36
- "args": [],
37
- "cwd": "/absolute/path/to/your/mobile-app",
38
- "timeout": 600000
150
+ "command": "npx",
151
+ "args": ["-y", "swipium"],
152
+ "env": { "SWIPIUM_PROJECT_ROOT": "/absolute/path/to/your/mobile-app" }
39
153
  }
40
154
  }
41
155
  }
42
156
  ```
43
157
 
44
- ## Claude Code
45
-
46
- ```bash
47
- npm install -g swipium
48
- swipium init claude --apply --scope project
49
- ```
50
-
51
- No global install:
52
-
53
- ```bash
54
- claude mcp add swipium --scope project -- npx -y swipium
55
- ```
56
-
57
- ## Gemini CLI
58
-
59
- ```bash
60
- npm install -g swipium
61
- swipium init gemini --apply
62
- ```
63
-
64
- No global install:
65
-
66
- ```bash
67
- gemini mcp add swipium npx -y swipium
68
- ```
69
-
70
- ## Codex
71
-
72
- ```bash
73
- npm install -g swipium
74
- swipium init codex --apply
75
- ```
76
-
77
- Manual config:
78
-
79
- ```toml
80
- [mcp_servers.swipium]
81
- command = "npx"
82
- args = ["-y", "swipium"]
83
- cwd = "/absolute/path/to/your/mobile-app"
84
- ```
158
+ Environment variables (test credentials, OCR provider, remote WDA allowlist, elicitation policy,
159
+ retention) are listed in the
160
+ [README's configuration section](../README.md#configuration--environment-variables).
161
+
162
+ ## What the server exposes
163
+
164
+ - **Tools**: listed in [tools.md](tools.md). Run `swipium verify` to see the exact list and count
165
+ your installed version serves. Every tool carries MCP annotations: read-only tools set
166
+ `readOnlyHint: true` and `openWorldHint: false`, and the others also set `destructiveHint` and
167
+ `idempotentHint`.
168
+ - **Server instructions**: sent on `initialize`. They give the first call
169
+ (`qa_test_this { mode: "execute" }`), the polling loop (`qa_job_status … waitMs`), how to relay
170
+ `needs_input`, blockers and consent, and the project-root order. `qa_status` without a
171
+ `sessionId` returns the same orientation plus the tool groups.
172
+ - **Prompts** (5): `swipium_setup_check`, `swipium_guardrail_validation`, `swipium_full_smoke`,
173
+ `swipium_bug_repro`, `swipium_convert_run_to_flow`.
174
+ - **Resources**:
175
+ - `swipium://session/{sessionId}/{kind}/{name}`: session artifacts (screenshots, dumps, reports,
176
+ logs).
177
+ - `swipium://project/{projectId}/app-map`: the full app map.
178
+ - `swipium://project/{projectId}/app-map/{kind}/{id}`: one feature, screen or test-suite section.
179
+
180
+ `resources/list` shows only the current client's project roots (its MCP roots plus roots of
181
+ sessions in this server process), never lists sensitive-mode sessions, and is capped at 100
182
+ entries per template, with the cap stated on the last entry. Anything not listed can still be
183
+ read by URI. Clients without resource support use `qa_get_artifact` and `qa_app_map_read`.
184
+
185
+ ## Server behavior
186
+
187
+ - **Response modes.** Pass `responseMode: "compact" | "normal" | "verbose"` on `qa_start_session`
188
+ or `qa_test_this`, and every later call in that session uses it. `compact` shortens only the
189
+ text channel to a summary plus URIs. `structuredContent` always carries the full payload.
190
+ - **Artifacts.** Evidence is stored under `~/.swipium/runs/` and returned as `swipium://` URIs.
191
+ `qa_get_artifact` returns metadata for images by default. Pass `mode: "inline"` only when you
192
+ need the pixels.
193
+ - **Unknown arguments are rejected.** A top-level argument a tool doesn't declare returns
194
+ `INVALID_ARGUMENT` with the accepted parameter list, and nothing runs. Swipium doesn't silently
195
+ drop it.
196
+ - **Stale clients.** A call to a tool removed in 2.0 (`qa_agent_brief`, `qa_capabilities`,
197
+ `qa_next_best_action`, `qa_detect_context`, `qa_plan`, `qa_assert_visual`), or a legacy call
198
+ shape (`qa_ios` `wda_*` or `screenshot` actions, `qa_wait for:"job_done"`), returns
199
+ `STALE_CLIENT` with the replacement call and a hint to restart the client. `qa_doctor` accepts
200
+ `expectedVersion`, `expectedToolCount` and `expectedSchemaHash` and reports a mismatch.
201
+ - **Consent.** Privileged actions (builds, boots, installs, data wipes and similar) return
202
+ `requiresConsent` with a `consentId` instead of running. On clients that support MCP elicitation,
203
+ Swipium asks the user directly. How consent works, and what each outcome returns, is in
204
+ [concepts.md](concepts.md#consent); the security reasoning is in
205
+ [THREAT_MODEL.md](../THREAT_MODEL.md).
206
+ - **Startup and shutdown.** The version and tool count are logged to stderr at startup, and
207
+ processes left behind by a crashed earlier server are reaped in the background. On shutdown or
208
+ client disconnect, Swipium restores changed network state and stops screen recorders and Metro.
209
+ Managed WebDriverAgent keeps running so the next server can reuse it; `qa_wda stop` stops it.
210
+
211
+ ## Scope
212
+
213
+ Swipium supports the Android Emulator and the iOS Simulator, with optional WebDriverAgent for
214
+ structured iOS automation. Swipium never acts on a physical device. See
215
+ [physical-devices.md](physical-devices.md).
85
216
 
86
217
  ## Verification
87
218
 
88
- Run:
89
-
90
219
  ```bash
91
220
  swipium verify
92
221
  ```
93
222
 
94
- Then, inside the MCP client, call:
95
-
96
- ```text
97
- qa_doctor
98
- qa_capabilities
99
- ```
100
-
101
- Use `qa_doctor` with `platform:"android"`, `platform:"ios"`, or `platform:"both"` when checking platform-specific readiness.
102
-
103
- Expected tool count: 95.
104
-
105
- If the client lists fewer tools, restart the MCP client. MCP clients often keep an old server process alive after package upgrades.
106
-
107
- ## Artifacts
108
-
109
- Swipium stores evidence as local artifacts and returns `swipium://` URIs. Use:
110
-
111
- - `qa_get_artifact` to read an artifact by URI.
112
- - `qa_report` to generate report artifacts.
113
- - `qa_screenshot` to capture screenshot artifacts.
114
- - `qa_app_map_read` to read app-map sections.
115
-
116
- Images default to metadata through `qa_get_artifact`. Request inline mode only when pixels are needed.
117
-
118
- ## Consent
119
-
120
- Swipium requests consent before high-impact local actions such as:
121
-
122
- - Booting a simulator when required by the plan.
123
- - Installing external app artifacts.
124
- - Writing generated automation into a project directory.
125
- - Running mutating flow steps.
126
-
127
- The consent result includes a `consentId`. Re-call the same tool with `approve: true` and that `consentId` to continue.
128
-
129
- ## Simulator Scope
130
-
131
- Public scope supports:
132
-
133
- - Android Emulator.
134
- - iOS Simulator.
135
- - Optional WebDriverAgent for structured iOS simulator automation.
136
-
137
- The public build does not support real-device execution.
223
+ This starts a Swipium server over stdio, checks that every tool and prompt this version declares is
224
+ listed, prints their names, count and schema hash, and calls `qa_doctor`. It exits with status 1 if a tool is missing
225
+ or `qa_doctor` errors. It starts the copy of Swipium you ran it with, not the command your client is
226
+ configured with.
227
+
228
+ Inside the client, call `qa_doctor`. It checks both platforms by default on macOS (ready if either
229
+ one is) and Android elsewhere. Pass `platform: "android" | "ios" | "both"` to be explicit.
230
+
231
+ ## Troubleshooting
232
+
233
+ | Symptom | Fix |
234
+ | --- | --- |
235
+ | The client lists fewer or different tools than `swipium verify`, or calls return `STALE_CLIENT` | The client is still running a server it started before the upgrade. Restart the client, or reload its MCP server list. |
236
+ | `PROJECT_ROOT_UNRESOLVED` | Pass an absolute `projectRoot`, or set `SWIPIUM_PROJECT_ROOT` in the server `env` (needed on Claude Desktop and Windsurf). |
237
+ | The server times out on first start (Codex, Gemini) | The first `npx` run downloads the package. Raise the startup timeout (Codex `startup_timeout_sec = 30`), or install globally and point the client at `swipium`. |
238
+ | Long tool calls time out | Raise the client's tool timeout (Codex `tool_timeout_sec = 600`, Gemini `timeout: 600000`). For builds and runs, prefer `qa_test_this { mode: "execute" }` plus `qa_job_status` polling. |
239
+ | `adb` or `emulator` not found from a GUI client | Set `ANDROID_HOME` in the server `env`, or install the SDK in its default location. See [How Android tools are found](#how-android-tools-are-found). |
240
+ | `INVALID_ARGUMENT` listing accepted parameters | Remove the undeclared argument. If the tool list looks outdated, restart the client. |
241
+ | Tools missing in Codex Desktop threads | Known Codex Desktop issue ([openai/codex#19425](https://github.com/openai/codex/issues/19425)). Use the Codex CLI. |
242
+ | `swipium init cursor --apply` or `init vscode --apply` exits with status 2 | The existing file isn't plain JSON. Add the printed entry by hand. |
243
+ | `PHYSICAL_DEVICE_UNSUPPORTED` | A phone was the only device, or was requested explicitly. Start an emulator or simulator. See [physical-devices.md](physical-devices.md). |
@@ -0,0 +1,84 @@
1
+ # Physical devices
2
+
3
+ Status: **not supported in Swipium 2.0.** Swipium runs only on Android Emulators and iOS
4
+ Simulators. A physical device is visible to Swipium, but Swipium never installs on it, launches on it
5
+ or drives it. The policy is server-side; a client cannot opt in by passing a flag. This page
6
+ describes the current behavior and what support would need.
7
+
8
+ ## The refusal rule
9
+
10
+ A connected phone does not stop a run by itself:
11
+
12
+ - **An emulator or simulator is viable** (one is online, or an AVD or simulator can be booted):
13
+ Swipium picks it, and the plan's `reason` mentions that the phone is visible but out of scope.
14
+ - **The phone is the only option, or it is requested** (its serial passed as `device`, or
15
+ `preferRealDevice: true` while a phone is visible): the call fails with
16
+ `PHYSICAL_DEVICE_UNSUPPORTED` (bucket `unsafe_refused`), so the agent can explain *why* instead
17
+ of reporting a bare "no device". A viable emulator or simulator, if any, is offered as the
18
+ alternative.
19
+
20
+ ## Current behavior
21
+
22
+ | Path | What happens with a physical device |
23
+ | --- | --- |
24
+ | `qa_resolve_target` | Lists it but never selects it. It follows the refusal rule above: an emulator is chosen when one is viable, and `PHYSICAL_DEVICE_UNSUPPORTED` is returned when the phone is the only candidate, is passed as `device`, or `preferRealDevice: true` is set while it is visible. |
25
+ | `qa_test_this` | Follows the same rule, and also refuses `preferRealDevice: true` whether or not a phone is visible, and iOS artifacts that only install on real hardware (device-only `.ipa` or `.app` builds). |
26
+ | `qa_prepare_target` | Refuses a physical serial passed as `device`, or a phone that is the only online device, before anything is installed or launched. With a phone and an emulator online and no `device`, it returns `MULTIPLE_DEVICES`. When it boots an emulator, it binds only a serial that was not online before the boot, so a phone that happens to be plugged in is never picked up. |
27
+ | Device auto-attach (any tool that needs a device) | Only a single online device is bound automatically, and Swipium probes it first. A physical device is refused, a still-booting emulator returns `DEVICE_NOT_READY`, and a device whose properties cannot be read (offline or unauthorized) is not bound. |
28
+ | iOS | Swipium enumerates simulators only, through `xcrun simctl`. Real iPhones and iPads are never listed or targeted. |
29
+
30
+ ## How Android emulators are recognized
31
+
32
+ adb lists emulators and phones side by side, so Swipium classifies each online serial
33
+ (`src/session/attach.ts`, `src/core/targetPlan.ts`):
34
+
35
+ 1. A serial of the form `emulator-<port>` is an emulator.
36
+ 2. Any other serial, for example `localhost:5555`, `127.0.0.1:<port>` or a Genymotion address, is
37
+ probed once with `adb -s <serial> shell getprop`. It is treated as an emulator when any of these
38
+ is true:
39
+ - `ro.kernel.qemu` or `ro.boot.qemu` is `1`;
40
+ - `ro.hardware` is `goldfish` or `ranchu`;
41
+ - `ro.genymotion.version` is set, or `ro.product.manufacturer` is `Genymotion`.
42
+ 3. Everything else whose properties could be read is physical and is refused.
43
+ 4. An emulator is used only once `sys.boot_completed` is `1`.
44
+
45
+ `qa_test_this`, `qa_resolve_target`, `qa_prepare_target` and device auto-attach all use this
46
+ property probe, so a network-attached emulator (`localhost:5555`, Genymotion) is accepted everywhere.
47
+
48
+ ## Why the line is drawn here
49
+
50
+ A developer's emulator or simulator is a disposable sandbox. A physical device usually is not:
51
+
52
+ 1. **Real user data.** Personal accounts, photos, messages, payment methods and 2FA apps live on
53
+ real hardware. Data wipes, fresh installs, permission resets and exploratory tapping have real
54
+ consequences there.
55
+ 2. **Changes that can't be undone.** Screen size and density overrides, airplane-mode toggles,
56
+ location spoofing and animation-scale changes do no harm on an emulator you can recreate. On a
57
+ person's phone they leave it feeling broken if a run dies before restoring them.
58
+ 3. **Identity and signing.** Real iOS devices need Apple code signing and device trust. Running
59
+ WebDriverAgent on hardware brings account and provisioning questions that the simulator path
60
+ avoids.
61
+ 4. **Fleet variance.** OEM skins, battery optimizers and vendor permission dialogs multiply the
62
+ overlays and interstitials that Swipium's oracle currently models for AOSP-like emulators.
63
+
64
+ ## Roadmap: what support would require
65
+
66
+ Physical-device support is not scheduled. It would keep the same tool surface, with an explicit
67
+ opt-in on target resolution, and it would need at least:
68
+
69
+ - **A threat-model extension** (per the out-of-scope clause in `THREAT_MODEL.md`): analysis of the
70
+ real-user-data adversary, stronger consent for every change to device state, and explicit
71
+ non-support for carrier, eSIM and payment surfaces.
72
+ - **A mutation policy:** no screen size or density overrides; no location spoofing without consent
73
+ for each action; data wipes and uninstalls limited to the app under test, never system or
74
+ third-party packages; and a mandatory check at session end that everything was restored.
75
+ - **A data-safety preflight:** refuse devices whose accounts or profiles suggest a personal phone
76
+ rather than a lab device, unless the user confirms it is a test device, with the heuristics
77
+ documented.
78
+ - **An iOS decision:** "bring your own signed WebDriverAgent" versus full signing automation,
79
+ before promising parity with iOS Simulator support.
80
+ - **Evidence hygiene:** screenshots and OCR on a personal device can capture other apps'
81
+ notifications, so sensitive mode would need stricter defaults on hardware.
82
+
83
+ Remote device farms, multi-tenant device brokering, and anything that sends device data off the
84
+ machine stay out of scope even then.