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.
- package/CHANGELOG.md +313 -0
- package/README.md +175 -219
- package/THREAT_MODEL.md +223 -47
- package/dist/appMap/automationLink.js +39 -26
- package/dist/appMap/automationLink.js.map +1 -1
- package/dist/appMap/build.js +68 -20
- package/dist/appMap/build.js.map +1 -1
- package/dist/appMap/codeIndex.js +31 -5
- package/dist/appMap/codeIndex.js.map +1 -1
- package/dist/appMap/featureIndex.js +23 -5
- package/dist/appMap/featureIndex.js.map +1 -1
- package/dist/appMap/featureModel.js +44 -8
- package/dist/appMap/featureModel.js.map +1 -1
- package/dist/appMap/firstRunApply.js +24 -6
- package/dist/appMap/firstRunApply.js.map +1 -1
- package/dist/appMap/fsWalk.js +19 -2
- package/dist/appMap/fsWalk.js.map +1 -1
- package/dist/appMap/issues.js +10 -30
- package/dist/appMap/issues.js.map +1 -1
- package/dist/appMap/migrations.js +6 -6
- package/dist/appMap/migrations.js.map +1 -1
- package/dist/appMap/prelaunch.js +2 -2
- package/dist/appMap/prelaunch.js.map +1 -1
- package/dist/appMap/projectRegistry.js +83 -11
- package/dist/appMap/projectRegistry.js.map +1 -1
- package/dist/appMap/provenance.js +2 -2
- package/dist/appMap/provenance.js.map +1 -1
- package/dist/appMap/query.js +21 -5
- package/dist/appMap/query.js.map +1 -1
- package/dist/appMap/runtimeMerge.js +12 -5
- package/dist/appMap/runtimeMerge.js.map +1 -1
- package/dist/appMap/schema.js +1 -1
- package/dist/appMap/schema.js.map +1 -1
- package/dist/appMap/screenMatch.js +6 -2
- package/dist/appMap/screenMatch.js.map +1 -1
- package/dist/appMap/staticScan.js +151 -39
- package/dist/appMap/staticScan.js.map +1 -1
- package/dist/appMap/store.js +58 -85
- package/dist/appMap/store.js.map +1 -1
- package/dist/appMap/tsAstScan.js +34 -12
- package/dist/appMap/tsAstScan.js.map +1 -1
- package/dist/artifacts/bundletool.js +49 -12
- package/dist/artifacts/bundletool.js.map +1 -1
- package/dist/artifacts/resolve.js +41 -14
- package/dist/artifacts/resolve.js.map +1 -1
- package/dist/automation/capabilities.js +112 -30
- package/dist/automation/capabilities.js.map +1 -1
- package/dist/automation/gestures.js +6 -2
- package/dist/automation/gestures.js.map +1 -1
- package/dist/automation/plan.js +71 -23
- package/dist/automation/plan.js.map +1 -1
- package/dist/automation/report.js +15 -5
- package/dist/automation/report.js.map +1 -1
- package/dist/automation/selectors.js +22 -28
- package/dist/automation/selectors.js.map +1 -1
- package/dist/automation/types.js +1 -1
- package/dist/automation/types.js.map +1 -1
- package/dist/automation/waits.js +14 -8
- package/dist/automation/waits.js.map +1 -1
- package/dist/automation/webview.js +9 -3
- package/dist/automation/webview.js.map +1 -1
- package/dist/automationGen/appiumModel.js +16 -8
- package/dist/automationGen/appiumModel.js.map +1 -1
- package/dist/automationGen/ciEmitter.js +6 -6
- package/dist/automationGen/ciEmitter.js.map +1 -1
- package/dist/automationGen/identifiers.js +224 -0
- package/dist/automationGen/identifiers.js.map +1 -0
- package/dist/automationGen/jsEmitter.js +288 -121
- package/dist/automationGen/jsEmitter.js.map +1 -1
- package/dist/automationGen/packagePatch.js +2 -2
- package/dist/automationGen/packagePatch.js.map +1 -1
- package/dist/automationGen/platformResolve.js +36 -0
- package/dist/automationGen/platformResolve.js.map +1 -0
- package/dist/automationGen/projectProfile.js +76 -27
- package/dist/automationGen/projectProfile.js.map +1 -1
- package/dist/automationGen/pythonEmitter.js +278 -107
- package/dist/automationGen/pythonEmitter.js.map +1 -1
- package/dist/automationGen/readmeEmitter.js +7 -6
- package/dist/automationGen/readmeEmitter.js.map +1 -1
- package/dist/automationGen/run.js +388 -0
- package/dist/automationGen/run.js.map +1 -0
- package/dist/automationGen/suitePlan.js +17 -10
- package/dist/automationGen/suitePlan.js.map +1 -1
- package/dist/automationGen/validation.js +52 -12
- package/dist/automationGen/validation.js.map +1 -1
- package/dist/build/parseBuildLog.js +235 -31
- package/dist/build/parseBuildLog.js.map +1 -1
- package/dist/build/plan.js +39 -18
- package/dist/build/plan.js.map +1 -1
- package/dist/ci/preflight.js +13 -4
- package/dist/ci/preflight.js.map +1 -1
- package/dist/cli/gc.js +74 -0
- package/dist/cli/gc.js.map +1 -0
- package/dist/cli/init.js +217 -26
- package/dist/cli/init.js.map +1 -1
- package/dist/cli/main.js +50 -0
- package/dist/cli/main.js.map +1 -0
- package/dist/cli/report.js +218 -0
- package/dist/cli/report.js.map +1 -0
- package/dist/cli/scan.js +36 -15
- package/dist/cli/scan.js.map +1 -1
- package/dist/cli/suite.js +7 -7
- package/dist/cli/suite.js.map +1 -1
- package/dist/cli/verify.js +7 -7
- package/dist/cli/verify.js.map +1 -1
- package/dist/consent/consent.js +162 -5
- package/dist/consent/consent.js.map +1 -1
- package/dist/context/detect.js +55 -18
- package/dist/context/detect.js.map +1 -1
- package/dist/context/findApps.js +22 -8
- package/dist/context/findApps.js.map +1 -1
- package/dist/context/projectRoot.js +174 -19
- package/dist/context/projectRoot.js.map +1 -1
- package/dist/context/scan.js +1 -1
- package/dist/context/scan.js.map +1 -1
- package/dist/core/capabilityGroups.js +90 -0
- package/dist/core/capabilityGroups.js.map +1 -0
- package/dist/core/target.js +10 -8
- package/dist/core/target.js.map +1 -1
- package/dist/core/targetPlan.js +160 -39
- package/dist/core/targetPlan.js.map +1 -1
- package/dist/drivers/DirectDriver.js +317 -43
- package/dist/drivers/DirectDriver.js.map +1 -1
- package/dist/drivers/SimctlDriver.js +124 -8
- package/dist/drivers/SimctlDriver.js.map +1 -1
- package/dist/drivers/WdaDriver.js +365 -55
- package/dist/drivers/WdaDriver.js.map +1 -1
- package/dist/explore/candidates.js +7 -3
- package/dist/explore/candidates.js.map +1 -1
- package/dist/explore/graph.js +15 -6
- package/dist/explore/graph.js.map +1 -1
- package/dist/explore/memory.js +4 -1
- package/dist/explore/memory.js.map +1 -1
- package/dist/explore/planner.js +54 -9
- package/dist/explore/planner.js.map +1 -1
- package/dist/explore/policy.js +11 -6
- package/dist/explore/policy.js.map +1 -1
- package/dist/explore/runner.js +363 -190
- package/dist/explore/runner.js.map +1 -1
- package/dist/explore/signatures.js +4 -2
- package/dist/explore/signatures.js.map +1 -1
- package/dist/explore/suite.js +3 -1
- package/dist/explore/suite.js.map +1 -1
- package/dist/featureTesting/executionBootstrap.js +137 -29
- package/dist/featureTesting/executionBootstrap.js.map +1 -1
- package/dist/featureTesting/featureMap.js +6 -3
- package/dist/featureTesting/featureMap.js.map +1 -1
- package/dist/featureTesting/featureScope.js +101 -20
- package/dist/featureTesting/featureScope.js.map +1 -1
- package/dist/featureTesting/mapFeatureScope.js +44 -15
- package/dist/featureTesting/mapFeatureScope.js.map +1 -1
- package/dist/featureTesting/objectiveModel.js +15 -11
- package/dist/featureTesting/objectiveModel.js.map +1 -1
- package/dist/featureTesting/resultMerge.js +16 -8
- package/dist/featureTesting/resultMerge.js.map +1 -1
- package/dist/featureTesting/sources.js +8 -5
- package/dist/featureTesting/sources.js.map +1 -1
- package/dist/featureTesting/suiteBridge.js +8 -2
- package/dist/featureTesting/suiteBridge.js.map +1 -1
- package/dist/featureTesting/synonyms.js +32 -4
- package/dist/featureTesting/synonyms.js.map +1 -1
- package/dist/featureTesting/testCaseFactory.js +27 -15
- package/dist/featureTesting/testCaseFactory.js.map +1 -1
- package/dist/featureTesting/testPlan.js +34 -12
- package/dist/featureTesting/testPlan.js.map +1 -1
- package/dist/firstRun/authStateMachine.js +1 -1
- package/dist/firstRun/authStateMachine.js.map +1 -1
- package/dist/firstRun/classifyScreen.js +9 -6
- package/dist/firstRun/classifyScreen.js.map +1 -1
- package/dist/firstRun/firstRunPlanner.js +16 -13
- package/dist/firstRun/firstRunPlanner.js.map +1 -1
- package/dist/firstRun/firstRunRunner.js +92 -31
- package/dist/firstRun/firstRunRunner.js.map +1 -1
- package/dist/firstRun/generatedDataPolicy.js +25 -15
- package/dist/firstRun/generatedDataPolicy.js.map +1 -1
- package/dist/firstRun/inputPlanner.js +45 -11
- package/dist/firstRun/inputPlanner.js.map +1 -1
- package/dist/firstRun/onboardingStateMachine.js +1 -1
- package/dist/firstRun/onboardingStateMachine.js.map +1 -1
- package/dist/firstRun/paywallPolicy.js +3 -3
- package/dist/firstRun/paywallPolicy.js.map +1 -1
- package/dist/firstRun/types.js +1 -1
- package/dist/firstRun/types.js.map +1 -1
- package/dist/fixtures/catalog.js +72 -9
- package/dist/fixtures/catalog.js.map +1 -1
- package/dist/fixtures/load.js +50 -0
- package/dist/fixtures/load.js.map +1 -0
- package/dist/flows/discover.js +2 -2
- package/dist/flows/discover.js.map +1 -1
- package/dist/flows/generate.js +68 -17
- package/dist/flows/generate.js.map +1 -1
- package/dist/flows/lint.js +88 -14
- package/dist/flows/lint.js.map +1 -1
- package/dist/flows/pack.js +21 -5
- package/dist/flows/pack.js.map +1 -1
- package/dist/flows/paths.js +57 -0
- package/dist/flows/paths.js.map +1 -0
- package/dist/flows/repair.js +176 -37
- package/dist/flows/repair.js.map +1 -1
- package/dist/flows/run.js +308 -99
- package/dist/flows/run.js.map +1 -1
- package/dist/flows/schema.js +107 -25
- package/dist/flows/schema.js.map +1 -1
- package/dist/flows/seedExec.js +8 -4
- package/dist/flows/seedExec.js.map +1 -1
- package/dist/flows/templates.js +5 -5
- package/dist/index.js +50 -8
- package/dist/index.js.map +1 -1
- package/dist/ios/signing.js +32 -3
- package/dist/ios/signing.js.map +1 -1
- package/dist/issues/classify.js +28 -20
- package/dist/issues/classify.js.map +1 -1
- package/dist/issues/fingerprint.js +35 -9
- package/dist/issues/fingerprint.js.map +1 -1
- package/dist/issues/index.js +93 -46
- package/dist/issues/index.js.map +1 -1
- package/dist/issues/metrics.js +6 -5
- package/dist/issues/metrics.js.map +1 -1
- package/dist/issues/recurrence.js +35 -8
- package/dist/issues/recurrence.js.map +1 -1
- package/dist/issues/report.js +12 -8
- package/dist/issues/report.js.map +1 -1
- package/dist/issues/reportBridge.js +40 -9
- package/dist/issues/reportBridge.js.map +1 -1
- package/dist/issues/schema.js +2 -2
- package/dist/issues/schema.js.map +1 -1
- package/dist/issues/sourceRevision.js +2 -2
- package/dist/issues/sourceRevision.js.map +1 -1
- package/dist/issues/store.js +110 -32
- package/dist/issues/store.js.map +1 -1
- package/dist/lib/abortScope.js +48 -0
- package/dist/lib/abortScope.js.map +1 -0
- package/dist/lib/android.js +84 -8
- package/dist/lib/android.js.map +1 -1
- package/dist/lib/coordSpace.js +1 -1
- package/dist/lib/coordSpace.js.map +1 -1
- package/dist/lib/device.js +53 -12
- package/dist/lib/device.js.map +1 -1
- package/dist/lib/gestures.js +141 -0
- package/dist/lib/gestures.js.map +1 -0
- package/dist/lib/gitignore.js +4 -3
- package/dist/lib/gitignore.js.map +1 -1
- package/dist/lib/image.js +12 -3
- package/dist/lib/image.js.map +1 -1
- package/dist/lib/lockfile.js +399 -0
- package/dist/lib/lockfile.js.map +1 -0
- package/dist/lib/needsInput.js +9 -6
- package/dist/lib/needsInput.js.map +1 -1
- package/dist/lib/png.js +4 -3
- package/dist/lib/png.js.map +1 -1
- package/dist/lib/redact.js +170 -9
- package/dist/lib/redact.js.map +1 -1
- package/dist/lib/result.js +94 -10
- package/dist/lib/result.js.map +1 -1
- package/dist/lib/schemaHash.js +7 -5
- package/dist/lib/schemaHash.js.map +1 -1
- package/dist/lib/sensitive.js +6 -3
- package/dist/lib/sensitive.js.map +1 -1
- package/dist/lib/simctl.js +3 -3
- package/dist/lib/simctl.js.map +1 -1
- package/dist/lib/spawn.js +78 -17
- package/dist/lib/spawn.js.map +1 -1
- package/dist/lib/toolAnnotations.js +114 -0
- package/dist/lib/toolAnnotations.js.map +1 -0
- package/dist/lib/wda.js +321 -25
- package/dist/lib/wda.js.map +1 -1
- package/dist/lib/wdaConfig.js +12 -5
- package/dist/lib/wdaConfig.js.map +1 -1
- package/dist/lib/wdaTune.js +52 -23
- package/dist/lib/wdaTune.js.map +1 -1
- package/dist/mobileAudit/checks.js +150 -28
- package/dist/mobileAudit/checks.js.map +1 -1
- package/dist/mobileAudit/evidence.js +4 -4
- package/dist/mobileAudit/evidence.js.map +1 -1
- package/dist/mobileAudit/profiles.js +121 -20
- package/dist/mobileAudit/profiles.js.map +1 -1
- package/dist/mobileAudit/results.js +9 -4
- package/dist/mobileAudit/results.js.map +1 -1
- package/dist/mobileAudit/runner.js +214 -35
- package/dist/mobileAudit/runner.js.map +1 -1
- package/dist/oracle/auth.js +1 -1
- package/dist/oracle/auth.js.map +1 -1
- package/dist/oracle/failures.js +1085 -145
- package/dist/oracle/failures.js.map +1 -1
- package/dist/oracle/health.js +148 -26
- package/dist/oracle/health.js.map +1 -1
- package/dist/oracle/locator.js +148 -19
- package/dist/oracle/locator.js.map +1 -1
- package/dist/oracle/record.js +3 -3
- package/dist/oracle/record.js.map +1 -1
- package/dist/orchestration/envelope.js +2 -2
- package/dist/orchestration/envelope.js.map +1 -1
- package/dist/orchestration/goal.js +7 -13
- package/dist/orchestration/goal.js.map +1 -1
- package/dist/orchestration/testThis/execute.js +167 -0
- package/dist/orchestration/testThis/execute.js.map +1 -0
- package/dist/orchestration/testThis/pipeline.js +413 -0
- package/dist/orchestration/testThis/pipeline.js.map +1 -0
- package/dist/orchestration/testThis/plan.js +519 -0
- package/dist/orchestration/testThis/plan.js.map +1 -0
- package/dist/orchestration/testThis/sessionIntent.js +72 -0
- package/dist/orchestration/testThis/sessionIntent.js.map +1 -0
- package/dist/orchestration/testThis/terminal.js +136 -0
- package/dist/orchestration/testThis/terminal.js.map +1 -0
- package/dist/orchestration/testThis/types.js +12 -0
- package/dist/orchestration/testThis/types.js.map +1 -0
- package/dist/plan/plan.js +9 -9
- package/dist/plan/plan.js.map +1 -1
- package/dist/prompts/index.js +24 -24
- package/dist/prompts/index.js.map +1 -1
- package/dist/report/coverage.js +0 -1
- package/dist/report/coverage.js.map +1 -1
- package/dist/report/evidence.js.map +1 -1
- package/dist/report/export.js +449 -72
- package/dist/report/export.js.map +1 -1
- package/dist/report/findingsDedupe.js +41 -0
- package/dist/report/findingsDedupe.js.map +1 -0
- package/dist/report/flake.js +13 -14
- package/dist/report/flake.js.map +1 -1
- package/dist/report/history.js +72 -38
- package/dist/report/history.js.map +1 -1
- package/dist/report/policy.js +18 -7
- package/dist/report/policy.js.map +1 -1
- package/dist/report/qaLevel.js +10 -16
- package/dist/report/qaLevel.js.map +1 -1
- package/dist/report/readiness.js +42 -12
- package/dist/report/readiness.js.map +1 -1
- package/dist/report/sarifSources.js +160 -0
- package/dist/report/sarifSources.js.map +1 -0
- package/dist/report/summary.js +2 -2
- package/dist/report/summary.js.map +1 -1
- package/dist/report/testCatalog.js +4 -4
- package/dist/report/testCatalog.js.map +1 -1
- package/dist/report/timing.js +23 -23
- package/dist/report/timing.js.map +1 -1
- package/dist/report/toolHealth.js +124 -0
- package/dist/report/toolHealth.js.map +1 -0
- package/dist/server.js +501 -69
- package/dist/server.js.map +1 -1
- package/dist/services/automationGenerate.js +8 -2
- package/dist/services/automationGenerate.js.map +1 -1
- package/dist/services/build.js +10 -4
- package/dist/services/build.js.map +1 -1
- package/dist/services/flowGenerate.js +75 -0
- package/dist/services/flowGenerate.js.map +1 -0
- package/dist/services/preflight.js +40 -8
- package/dist/services/preflight.js.map +1 -1
- package/dist/services/prepareAndroid.js +92 -18
- package/dist/services/prepareAndroid.js.map +1 -1
- package/dist/services/prepareIos.js +94 -17
- package/dist/services/prepareIos.js.map +1 -1
- package/dist/services/report.js +271 -80
- package/dist/services/report.js.map +1 -1
- package/dist/services/smoke.js +68 -22
- package/dist/services/smoke.js.map +1 -1
- package/dist/services/suiteGenerate.js +43 -6
- package/dist/services/suiteGenerate.js.map +1 -1
- package/dist/services/testSuiteKnowledge.js +78 -33
- package/dist/services/testSuiteKnowledge.js.map +1 -1
- package/dist/session/attach.js +284 -4
- package/dist/session/attach.js.map +1 -1
- package/dist/session/processRegistry.js +433 -0
- package/dist/session/processRegistry.js.map +1 -0
- package/dist/session/progress.js +1 -1
- package/dist/session/progress.js.map +1 -1
- package/dist/session/retention.js +201 -0
- package/dist/session/retention.js.map +1 -0
- package/dist/session/store.js +459 -59
- package/dist/session/store.js.map +1 -1
- package/dist/snapshot/overlays.js +60 -10
- package/dist/snapshot/overlays.js.map +1 -1
- package/dist/snapshot/parse.js +30 -12
- package/dist/snapshot/parse.js.map +1 -1
- package/dist/snapshot/present.js +36 -6
- package/dist/snapshot/present.js.map +1 -1
- package/dist/snapshot/settle.js +39 -9
- package/dist/snapshot/settle.js.map +1 -1
- package/dist/state/consent.js +99 -0
- package/dist/state/consent.js.map +1 -0
- package/dist/state/profile.js +82 -11
- package/dist/state/profile.js.map +1 -1
- package/dist/suite/compile.js +15 -6
- package/dist/suite/compile.js.map +1 -1
- package/dist/suite/lint.js +22 -4
- package/dist/suite/lint.js.map +1 -1
- package/dist/suite/pom.js +75 -44
- package/dist/suite/pom.js.map +1 -1
- package/dist/suite/secretGuard.js +266 -0
- package/dist/suite/secretGuard.js.map +1 -0
- package/dist/suite/testcase.js +15 -11
- package/dist/suite/testcase.js.map +1 -1
- package/dist/testSuite/exporter.js +7 -3
- package/dist/testSuite/exporter.js.map +1 -1
- package/dist/testSuite/generator.js +43 -14
- package/dist/testSuite/generator.js.map +1 -1
- package/dist/testSuite/history.js +1 -1
- package/dist/testSuite/history.js.map +1 -1
- package/dist/testSuite/issueLinks.js +3 -3
- package/dist/testSuite/issueLinks.js.map +1 -1
- package/dist/testSuite/lint.js +4 -4
- package/dist/testSuite/lint.js.map +1 -1
- package/dist/testSuite/merge.js +13 -7
- package/dist/testSuite/merge.js.map +1 -1
- package/dist/testSuite/schema.js +21 -16
- package/dist/testSuite/schema.js.map +1 -1
- package/dist/testSuite/store.js +12 -4
- package/dist/testSuite/store.js.map +1 -1
- package/dist/testSuite/traceability.js +2 -2
- package/dist/testSuite/traceability.js.map +1 -1
- package/dist/tools/act.js +868 -174
- package/dist/tools/act.js.map +1 -1
- package/dist/tools/agent.js +521 -112
- package/dist/tools/agent.js.map +1 -1
- package/dist/tools/appControl.js +82 -19
- package/dist/tools/appControl.js.map +1 -1
- package/dist/tools/appMap.js +393 -189
- package/dist/tools/appMap.js.map +1 -1
- package/dist/tools/build.js +92 -51
- package/dist/tools/build.js.map +1 -1
- package/dist/tools/bundletool.js +141 -40
- package/dist/tools/bundletool.js.map +1 -1
- package/dist/tools/clearOverlay.js +98 -18
- package/dist/tools/clearOverlay.js.map +1 -1
- package/dist/tools/device.js +108 -19
- package/dist/tools/device.js.map +1 -1
- package/dist/tools/doctor.js +98 -35
- package/dist/tools/doctor.js.map +1 -1
- package/dist/tools/explore.js +110 -42
- package/dist/tools/explore.js.map +1 -1
- package/dist/tools/featureTesting.js +152 -130
- package/dist/tools/featureTesting.js.map +1 -1
- package/dist/tools/firstRun.js +94 -66
- package/dist/tools/firstRun.js.map +1 -1
- package/dist/tools/flow.js +347 -132
- package/dist/tools/flow.js.map +1 -1
- package/dist/tools/flowRepair.js +42 -10
- package/dist/tools/flowRepair.js.map +1 -1
- package/dist/tools/generate.js +199 -0
- package/dist/tools/generate.js.map +1 -0
- package/dist/tools/getArtifact.js +37 -8
- package/dist/tools/getArtifact.js.map +1 -1
- package/dist/tools/health.js +17 -12
- package/dist/tools/health.js.map +1 -1
- package/dist/tools/ios.js +148 -194
- package/dist/tools/ios.js.map +1 -1
- package/dist/tools/issues.js +256 -171
- package/dist/tools/issues.js.map +1 -1
- package/dist/tools/jobs.js +55 -11
- package/dist/tools/jobs.js.map +1 -1
- package/dist/tools/metro.js +84 -38
- package/dist/tools/metro.js.map +1 -1
- package/dist/tools/mobileAudit.js +83 -26
- package/dist/tools/mobileAudit.js.map +1 -1
- package/dist/tools/network.js +36 -14
- package/dist/tools/network.js.map +1 -1
- package/dist/tools/note.js +31 -17
- package/dist/tools/note.js.map +1 -1
- package/dist/tools/prepareIosTarget.js +31 -14
- package/dist/tools/prepareIosTarget.js.map +1 -1
- package/dist/tools/prepareTarget.js +193 -47
- package/dist/tools/prepareTarget.js.map +1 -1
- package/dist/tools/report.js +16 -8
- package/dist/tools/report.js.map +1 -1
- package/dist/tools/resolveArtifact.js +12 -12
- package/dist/tools/resolveArtifact.js.map +1 -1
- package/dist/tools/resolveTarget.js +81 -18
- package/dist/tools/resolveTarget.js.map +1 -1
- package/dist/tools/screenRecord.js +85 -20
- package/dist/tools/screenRecord.js.map +1 -1
- package/dist/tools/screenshot.js +42 -18
- package/dist/tools/screenshot.js.map +1 -1
- package/dist/tools/smoke.js +29 -12
- package/dist/tools/smoke.js.map +1 -1
- package/dist/tools/snapshot.js +157 -107
- package/dist/tools/snapshot.js.map +1 -1
- package/dist/tools/startSession.js +117 -84
- package/dist/tools/startSession.js.map +1 -1
- package/dist/tools/suite.js +391 -310
- package/dist/tools/suite.js.map +1 -1
- package/dist/tools/testSuite.js +112 -36
- package/dist/tools/testSuite.js.map +1 -1
- package/dist/tools/testThis.js +35 -802
- package/dist/tools/testThis.js.map +1 -1
- package/dist/tools/visual.js +698 -116
- package/dist/tools/visual.js.map +1 -1
- package/dist/tools/wait.js +9 -23
- package/dist/tools/wait.js.map +1 -1
- package/dist/tools/wda.js +312 -54
- package/dist/tools/wda.js.map +1 -1
- package/dist/version.js +37 -64
- package/dist/version.js.map +1 -1
- package/dist/visual/ocr.js +65 -8
- package/dist/visual/ocr.js.map +1 -1
- package/dist/visual/provider.js +87 -15
- package/dist/visual/provider.js.map +1 -1
- package/docs/README.md +24 -10
- package/docs/ci-reports.md +328 -0
- package/docs/concepts.md +227 -0
- package/docs/flows.md +153 -0
- package/docs/mcp-server.md +210 -104
- package/docs/physical-devices.md +84 -0
- package/docs/tools.md +808 -217
- package/package.json +16 -6
- package/dist/appMap/diff.js +0 -60
- package/dist/appMap/diff.js.map +0 -1
- package/dist/automation/maestroIr.js +0 -282
- package/dist/automation/maestroIr.js.map +0 -1
- package/dist/interop/maestro.js +0 -151
- package/dist/interop/maestro.js.map +0 -1
- package/dist/tools/assertVisual.js +0 -74
- package/dist/tools/assertVisual.js.map +0 -1
- package/dist/tools/automationGenerate.js +0 -394
- package/dist/tools/automationGenerate.js.map +0 -1
- package/dist/tools/capabilities.js +0 -209
- package/dist/tools/capabilities.js.map +0 -1
- package/dist/tools/detectContext.js +0 -41
- package/dist/tools/detectContext.js.map +0 -1
- package/dist/tools/flowGenerate.js +0 -55
- package/dist/tools/flowGenerate.js.map +0 -1
- package/dist/tools/history.js +0 -56
- package/dist/tools/history.js.map +0 -1
- package/dist/tools/idling.js +0 -104
- package/dist/tools/idling.js.map +0 -1
- package/dist/tools/inputCapabilities.js +0 -30
- package/dist/tools/inputCapabilities.js.map +0 -1
- package/dist/tools/locator.js +0 -57
- package/dist/tools/locator.js.map +0 -1
- package/dist/tools/maestro.js +0 -78
- package/dist/tools/maestro.js.map +0 -1
- package/dist/tools/permissions.js +0 -149
- package/dist/tools/permissions.js.map +0 -1
- package/dist/tools/plan.js +0 -49
- package/dist/tools/plan.js.map +0 -1
- package/dist/tools/screenInfo.js +0 -70
- package/dist/tools/screenInfo.js.map +0 -1
- package/dist/tools/seed.js +0 -101
- package/dist/tools/seed.js.map +0 -1
- package/dist/tools/state.js +0 -170
- package/dist/tools/state.js.map +0 -1
- package/dist/tools/visualText.js +0 -61
- 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).
|
package/docs/mcp-server.md
CHANGED
|
@@ -1,137 +1,243 @@
|
|
|
1
|
-
# MCP
|
|
1
|
+
# MCP server reference
|
|
2
2
|
|
|
3
|
-
Swipium
|
|
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
|
-
-
|
|
9
|
-
|
|
10
|
-
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
```
|
|
17
|
-
{
|
|
125
|
+
```json
|
|
126
|
+
{
|
|
18
127
|
"mcpServers": {
|
|
19
128
|
"swipium": {
|
|
129
|
+
"type": "stdio",
|
|
20
130
|
"command": "npx",
|
|
21
131
|
"args": ["-y", "swipium"],
|
|
22
|
-
"
|
|
23
|
-
"timeout": 600000
|
|
132
|
+
"env": { "SWIPIUM_PROJECT_ROOT": "${workspaceFolder}" }
|
|
24
133
|
}
|
|
25
134
|
}
|
|
26
135
|
}
|
|
27
136
|
```
|
|
28
137
|
|
|
29
|
-
|
|
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
|
-
```
|
|
146
|
+
```json
|
|
32
147
|
{
|
|
33
148
|
"mcpServers": {
|
|
34
149
|
"swipium": {
|
|
35
|
-
"command": "
|
|
36
|
-
"args": [],
|
|
37
|
-
"
|
|
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
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
swipium
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
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
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
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.
|