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/dist/oracle/failures.js
CHANGED
|
@@ -1,136 +1,1059 @@
|
|
|
1
|
-
// Failure taxonomy
|
|
1
|
+
// Failure taxonomy. Every failure Swipium can detect maps to a
|
|
2
2
|
// stable code with: a bucket (so qa_report can group failures the way a developer triages them),
|
|
3
3
|
// a severity, a default retry-safety, and an actionable recovery line. This turns "something
|
|
4
|
-
// failed" into "this class of failure, here's whether to retry, here's the fix"
|
|
4
|
+
// failed" into "this class of failure, here's whether to retry, here's the fix". The
|
|
5
5
|
// structured/actionable error practice, applied to mobile QA.
|
|
6
6
|
//
|
|
7
7
|
// Buckets (what a developer does about it):
|
|
8
|
-
// app_bug
|
|
9
|
-
// environment
|
|
10
|
-
// missing_data
|
|
11
|
-
// mcp_limitation
|
|
12
|
-
// unsafe_refused
|
|
8
|
+
// app_bug : the app is broken; fix the app.
|
|
9
|
+
// environment : device/toolchain/network/build setup; fix the environment.
|
|
10
|
+
// missing_data : a precondition / test account / fixture is absent; provide it.
|
|
11
|
+
// mcp_limitation : automation couldn't proceed (opaque UI, stale ref, overlay); adjust approach.
|
|
12
|
+
// unsafe_refused : a guardrail intentionally refused a destructive action; expected, not a bug.
|
|
13
13
|
export const FAILURES = {
|
|
14
|
-
NATIVE_CRASH: {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
14
|
+
NATIVE_CRASH: {
|
|
15
|
+
bucket: 'app_bug',
|
|
16
|
+
severity: 'high',
|
|
17
|
+
retrySafe: false,
|
|
18
|
+
summary: 'Native process crashed',
|
|
19
|
+
recovery: 'Capture the crash log (qa_check_health) and fix the crash; do not blindly retry.',
|
|
20
|
+
},
|
|
21
|
+
ANR: {
|
|
22
|
+
bucket: 'app_bug',
|
|
23
|
+
severity: 'high',
|
|
24
|
+
retrySafe: false,
|
|
25
|
+
summary: 'App not responding (ANR)',
|
|
26
|
+
recovery: 'Main thread is blocked. Profile the slow work; retrying will not help.',
|
|
27
|
+
},
|
|
28
|
+
ERROR_BOUNDARY: {
|
|
29
|
+
bucket: 'app_bug',
|
|
30
|
+
severity: 'high',
|
|
31
|
+
retrySafe: false,
|
|
32
|
+
summary: 'App error screen / error boundary',
|
|
33
|
+
recovery: 'A render/runtime error surfaced to the user. Inspect logs and fix the failing screen.',
|
|
34
|
+
},
|
|
35
|
+
REDBOX: {
|
|
36
|
+
bucket: 'app_bug',
|
|
37
|
+
severity: 'high',
|
|
38
|
+
retrySafe: false,
|
|
39
|
+
summary: 'Framework red-box error',
|
|
40
|
+
recovery: 'A fatal JS/runtime error. Read the error text; often a bad bundle or thrown error.',
|
|
41
|
+
},
|
|
42
|
+
LOGBOX: {
|
|
43
|
+
bucket: 'app_bug',
|
|
44
|
+
severity: 'medium',
|
|
45
|
+
retrySafe: true,
|
|
46
|
+
summary: 'Framework warning overlay',
|
|
47
|
+
recovery: 'Non-fatal warning(s). Dismiss with qa_clear_overlay; review before release.',
|
|
48
|
+
},
|
|
49
|
+
BACKEND_ERROR: {
|
|
50
|
+
bucket: 'app_bug',
|
|
51
|
+
severity: 'high',
|
|
52
|
+
retrySafe: false,
|
|
53
|
+
summary: 'Backend/error surface shown to the user',
|
|
54
|
+
recovery: 'An error toast/banner/HTTP-error screen appeared. Check the API response and error handling.',
|
|
55
|
+
},
|
|
56
|
+
BLANK_SCREEN: {
|
|
57
|
+
bucket: 'app_bug',
|
|
58
|
+
severity: 'high',
|
|
59
|
+
retrySafe: false,
|
|
60
|
+
summary: 'Blank/empty screen',
|
|
61
|
+
recovery: 'Nothing rendered. Check for a failed initial fetch, missing data state, or a swallowed error.',
|
|
62
|
+
},
|
|
63
|
+
INFINITE_SPINNER: {
|
|
64
|
+
bucket: 'app_bug',
|
|
65
|
+
severity: 'high',
|
|
66
|
+
retrySafe: false,
|
|
67
|
+
summary: 'Stuck loading indicator',
|
|
68
|
+
recovery: 'A loading state never resolved. Check the pending request/timeout handling.',
|
|
69
|
+
},
|
|
70
|
+
ASSERTION_FAILED: {
|
|
71
|
+
bucket: 'app_bug',
|
|
72
|
+
severity: 'high',
|
|
73
|
+
retrySafe: false,
|
|
74
|
+
summary: 'Expected UI was not present',
|
|
75
|
+
recovery: 'The asserted text/element was missing. Either a real regression or the flow needs updating for a UI change.',
|
|
76
|
+
},
|
|
77
|
+
NO_DEVICE: {
|
|
78
|
+
bucket: 'environment',
|
|
79
|
+
severity: 'high',
|
|
80
|
+
retrySafe: true,
|
|
81
|
+
summary: 'No online device or bootable emulator',
|
|
82
|
+
recovery: 'Create an Android AVD (Android Studio > Device Manager, or avdmanager create avd …) or an iOS Simulator (Xcode), then re-run qa_test_this. It boots it for you.',
|
|
83
|
+
},
|
|
84
|
+
ADB_NOT_FOUND: {
|
|
85
|
+
bucket: 'environment',
|
|
86
|
+
severity: 'high',
|
|
87
|
+
retrySafe: true,
|
|
88
|
+
summary: 'adb (Android platform-tools) is not installed or not on PATH',
|
|
89
|
+
recovery: 'Install Android platform-tools + emulator (Android Studio SDK Manager or sdkmanager), put them on PATH or set ANDROID_HOME, create an AVD, then re-run qa_test_this.',
|
|
90
|
+
},
|
|
91
|
+
NO_ARTIFACT: {
|
|
92
|
+
bucket: 'environment',
|
|
93
|
+
severity: 'high',
|
|
94
|
+
retrySafe: true,
|
|
95
|
+
summary: 'No installable app artifact found',
|
|
96
|
+
recovery: 'Provide an APK path (qa_prepare_target { apk }) or place one under the project.',
|
|
97
|
+
},
|
|
98
|
+
INVALID_FLOW: {
|
|
99
|
+
bucket: 'environment',
|
|
100
|
+
severity: 'high',
|
|
101
|
+
retrySafe: true,
|
|
102
|
+
summary: 'Flow file is missing or invalid',
|
|
103
|
+
recovery: 'Fix the flow YAML or pass a valid --flow/--flow-yaml before rerunning CI.',
|
|
104
|
+
},
|
|
105
|
+
WRONG_ARCH: {
|
|
106
|
+
bucket: 'environment',
|
|
107
|
+
severity: 'high',
|
|
108
|
+
retrySafe: true,
|
|
109
|
+
summary: 'App architecture does not match the target device',
|
|
110
|
+
recovery: 'Use an app artifact built for this target. For iOS simulator, provide a simulator-SDK .app; for Android, use a device/emulator whose ABI matches the APK.',
|
|
111
|
+
},
|
|
112
|
+
INSTALL_FAILED: {
|
|
113
|
+
bucket: 'environment',
|
|
114
|
+
severity: 'high',
|
|
115
|
+
retrySafe: true,
|
|
116
|
+
summary: 'App install failed',
|
|
117
|
+
recovery: 'Check the surfaced reason (storage, signature mismatch, min-SDK, corrupt artifact) and fix it.',
|
|
118
|
+
},
|
|
119
|
+
BUNDLE_ID_NOT_FOUND: {
|
|
120
|
+
bucket: 'environment',
|
|
121
|
+
severity: 'high',
|
|
122
|
+
retrySafe: true,
|
|
123
|
+
summary: 'Bundle identifier was not found on the device',
|
|
124
|
+
recovery: 'Confirm the app is installed for this simulator/device and that the configured bundle id is correct.',
|
|
125
|
+
},
|
|
126
|
+
SIMULATOR_RUNTIME_MISSING: {
|
|
127
|
+
bucket: 'environment',
|
|
128
|
+
severity: 'high',
|
|
129
|
+
retrySafe: true,
|
|
130
|
+
summary: 'No usable iOS simulator runtime/device is installed',
|
|
131
|
+
recovery: 'Install an iOS simulator runtime in Xcode, create an iPhone simulator, then retry qa_ios list/boot.',
|
|
132
|
+
},
|
|
133
|
+
SIMULATOR_BOOT_FAILED: {
|
|
134
|
+
bucket: 'environment',
|
|
135
|
+
severity: 'high',
|
|
136
|
+
retrySafe: true,
|
|
137
|
+
summary: 'iOS simulator failed to boot',
|
|
138
|
+
recovery: 'Retry boot, free host resources, erase the simulator if policy allows it, or choose another simulator runtime.',
|
|
139
|
+
},
|
|
140
|
+
SIMULATOR_BOOT_TIMEOUT: {
|
|
141
|
+
bucket: 'environment',
|
|
142
|
+
severity: 'high',
|
|
143
|
+
retrySafe: true,
|
|
144
|
+
summary: 'iOS simulator boot timed out',
|
|
145
|
+
recovery: 'Check Simulator/Xcode health, free host resources, or boot a known-good simulator before retrying.',
|
|
146
|
+
},
|
|
147
|
+
EMULATOR_BOOT_FAILED: {
|
|
148
|
+
bucket: 'environment',
|
|
149
|
+
severity: 'high',
|
|
150
|
+
retrySafe: true,
|
|
151
|
+
summary: 'Emulator failed to boot',
|
|
152
|
+
recovery: 'Retry boot, free resources, or pick a different AVD (qa_doctor).',
|
|
153
|
+
},
|
|
154
|
+
DEVICE_NOT_READY: {
|
|
155
|
+
bucket: 'environment',
|
|
156
|
+
severity: 'high',
|
|
157
|
+
retrySafe: true,
|
|
158
|
+
summary: 'Device exists but is not ready for automation',
|
|
159
|
+
recovery: 'Wait for the device to finish booting/unlocking, then rerun the preflight or select a ready device explicitly.',
|
|
160
|
+
},
|
|
161
|
+
MULTIPLE_DEVICES: {
|
|
162
|
+
bucket: 'environment',
|
|
163
|
+
severity: 'medium',
|
|
164
|
+
retrySafe: true,
|
|
165
|
+
summary: 'More than one device is online',
|
|
166
|
+
recovery: 'Pass an explicit device to qa_prepare_target so the target is unambiguous.',
|
|
167
|
+
},
|
|
168
|
+
DEV_SERVER_DOWN: {
|
|
169
|
+
bucket: 'environment',
|
|
170
|
+
severity: 'high',
|
|
171
|
+
retrySafe: true,
|
|
172
|
+
summary: 'Dev/bundler server not reachable',
|
|
173
|
+
recovery: 'Start the dev server so a debug build can fetch its bundle.',
|
|
174
|
+
},
|
|
175
|
+
NETWORK_SERVICE_UNAVAILABLE: {
|
|
176
|
+
bucket: 'environment',
|
|
177
|
+
severity: 'high',
|
|
178
|
+
retrySafe: true,
|
|
179
|
+
summary: 'Required network service is unavailable',
|
|
180
|
+
recovery: 'Start the required service, fix the URL, or remove it from ci.requiredServices before rerunning CI.',
|
|
181
|
+
},
|
|
182
|
+
NETWORK_OFFLINE: {
|
|
183
|
+
bucket: 'environment',
|
|
184
|
+
severity: 'medium',
|
|
185
|
+
retrySafe: true,
|
|
186
|
+
summary: 'Device is offline',
|
|
187
|
+
recovery: 'Restore connectivity before network-dependent flows.',
|
|
188
|
+
},
|
|
189
|
+
WRONG_FOREGROUND: {
|
|
190
|
+
bucket: 'environment',
|
|
191
|
+
severity: 'medium',
|
|
192
|
+
retrySafe: true,
|
|
193
|
+
summary: 'A different app is in the foreground',
|
|
194
|
+
recovery: 'Relaunch the app under test with qa_prepare_target.',
|
|
195
|
+
},
|
|
196
|
+
WDA_UNREACHABLE: {
|
|
197
|
+
bucket: 'environment',
|
|
198
|
+
severity: 'high',
|
|
199
|
+
retrySafe: true,
|
|
200
|
+
summary: 'WebDriverAgent is unreachable or did not return UI source',
|
|
201
|
+
recovery: 'Check qa_wda status/logs, restart WDA, and confirm it is attached to the intended device.',
|
|
202
|
+
},
|
|
203
|
+
WDA_BUILD_FAILED: {
|
|
204
|
+
bucket: 'environment',
|
|
205
|
+
severity: 'high',
|
|
206
|
+
retrySafe: true,
|
|
207
|
+
summary: 'WebDriverAgent build failed',
|
|
208
|
+
recovery: 'Open the WDA build log artifact, fix the Xcode build error, then retry qa_wda build.',
|
|
209
|
+
},
|
|
210
|
+
WDA_SIGNING_FAILED: {
|
|
211
|
+
bucket: 'environment',
|
|
212
|
+
severity: 'high',
|
|
213
|
+
retrySafe: false,
|
|
214
|
+
summary: 'WebDriverAgent signing/provisioning failed',
|
|
215
|
+
recovery: 'Configure a valid development team, certificate, provisioning profile, and trusted device before retrying WDA build.',
|
|
216
|
+
},
|
|
217
|
+
WDA_START_FAILED: {
|
|
218
|
+
bucket: 'environment',
|
|
219
|
+
severity: 'high',
|
|
220
|
+
retrySafe: true,
|
|
221
|
+
summary: 'WebDriverAgent did not start',
|
|
222
|
+
recovery: 'Check qa_wda logs/status, confirm the target device is booted/trusted, and restart WDA.',
|
|
223
|
+
},
|
|
224
|
+
WDA_SESSION_FAILED: {
|
|
225
|
+
bucket: 'environment',
|
|
226
|
+
severity: 'high',
|
|
227
|
+
retrySafe: true,
|
|
228
|
+
summary: 'WebDriverAgent session creation failed',
|
|
229
|
+
recovery: 'Confirm WDA is paired with the intended device and that the app bundle id is installed, then retry attach.',
|
|
230
|
+
},
|
|
231
|
+
WDA_SOURCE_SLOW: {
|
|
232
|
+
bucket: 'mcp_limitation',
|
|
233
|
+
severity: 'medium',
|
|
234
|
+
retrySafe: true,
|
|
235
|
+
summary: 'WDA page-source retrieval is slow',
|
|
236
|
+
recovery: 'Tune snapshot depth/attributes, avoid XPath, and reduce large accessibility hierarchies where possible.',
|
|
237
|
+
},
|
|
238
|
+
WDA_APP_NOT_IDLE: {
|
|
239
|
+
bucket: 'mcp_limitation',
|
|
240
|
+
severity: 'medium',
|
|
241
|
+
retrySafe: true,
|
|
242
|
+
summary: 'WDA/XCTest is waiting for app idle',
|
|
243
|
+
recovery: 'Reduce animations, fix main-thread work, or add app-side idling hooks so XCTest can interact reliably.',
|
|
244
|
+
},
|
|
245
|
+
WDA_HIERARCHY_TOO_LARGE: {
|
|
246
|
+
bucket: 'mcp_limitation',
|
|
247
|
+
severity: 'medium',
|
|
248
|
+
retrySafe: true,
|
|
249
|
+
summary: 'WDA accessibility hierarchy is too large or deep',
|
|
250
|
+
recovery: 'Limit snapshot depth/children and simplify accessibility trees on complex screens.',
|
|
251
|
+
},
|
|
252
|
+
WDA_XPATH_REFUSED: {
|
|
253
|
+
bucket: 'mcp_limitation',
|
|
254
|
+
severity: 'medium',
|
|
255
|
+
retrySafe: false,
|
|
256
|
+
summary: 'XPath locator refused for WDA reliability',
|
|
257
|
+
recovery: 'Use accessibility id, predicate string, or class chain; Swipium does not generate XPath for iOS.',
|
|
258
|
+
},
|
|
259
|
+
WDA_MAIN_THREAD_BUSY: {
|
|
260
|
+
bucket: 'app_bug',
|
|
261
|
+
severity: 'medium',
|
|
262
|
+
retrySafe: true,
|
|
263
|
+
summary: 'App main thread appears busy during WDA automation',
|
|
264
|
+
recovery: 'Profile main-thread work, loading states, and animations; WDA tuning cannot fully fix app-side non-idleness.',
|
|
265
|
+
},
|
|
266
|
+
WDA_PORT_CONFLICT: {
|
|
267
|
+
bucket: 'environment',
|
|
268
|
+
severity: 'medium',
|
|
269
|
+
retrySafe: true,
|
|
270
|
+
summary: 'WebDriverAgent port is already in use or points at the wrong server',
|
|
271
|
+
recovery: 'Stop the stale process or choose a different WDA port, then verify /status before attaching.',
|
|
272
|
+
},
|
|
273
|
+
STALE_WDA_DEVICE: {
|
|
274
|
+
bucket: 'environment',
|
|
275
|
+
severity: 'high',
|
|
276
|
+
retrySafe: false,
|
|
277
|
+
summary: 'WDA appears bound to a different device than the session target',
|
|
278
|
+
recovery: 'Stop the stale WDA process or start a new session for the intended UDID; do not reuse ambiguous device mappings.',
|
|
279
|
+
},
|
|
280
|
+
PERMISSION_DIALOG: {
|
|
281
|
+
bucket: 'environment',
|
|
282
|
+
severity: 'medium',
|
|
283
|
+
retrySafe: false,
|
|
284
|
+
summary: 'Runtime permission dialog is visible',
|
|
285
|
+
recovery: 'Handle the permission prompt deliberately, or pre-grant permissions only when policy allows it.',
|
|
286
|
+
},
|
|
287
|
+
NATIVE_ALERT: {
|
|
288
|
+
bucket: 'environment',
|
|
289
|
+
severity: 'medium',
|
|
290
|
+
retrySafe: false,
|
|
291
|
+
summary: 'Native alert is visible',
|
|
292
|
+
recovery: 'Inspect/dismiss the alert intentionally before continuing the flow.',
|
|
293
|
+
},
|
|
294
|
+
SEED_FAILED: {
|
|
295
|
+
bucket: 'environment',
|
|
296
|
+
severity: 'medium',
|
|
297
|
+
retrySafe: true,
|
|
298
|
+
summary: 'Seeding a precondition failed (setup, not an app bug)',
|
|
299
|
+
recovery: 'Fix the fixture seed (deep link/script/api) and re-run the flow; this is a setup failure, not an app defect.',
|
|
300
|
+
},
|
|
301
|
+
ARTIFACT_PATH_UNWRITABLE: {
|
|
302
|
+
bucket: 'environment',
|
|
303
|
+
severity: 'high',
|
|
304
|
+
retrySafe: true,
|
|
305
|
+
summary: 'Artifact or report output path is not writable',
|
|
306
|
+
recovery: 'Create the output directory, fix permissions, or point --json/--report/--junit/--artifacts-dir at a writable location.',
|
|
307
|
+
},
|
|
308
|
+
REPORT_UPLOAD_SKIPPED: {
|
|
309
|
+
bucket: 'environment',
|
|
310
|
+
severity: 'medium',
|
|
311
|
+
retrySafe: true,
|
|
312
|
+
summary: 'CI report upload or publication was skipped',
|
|
313
|
+
recovery: 'Use if: always()/equivalent artifact upload steps and upload the full Swipium run directory even when tests fail.',
|
|
314
|
+
},
|
|
315
|
+
SECRET_IN_GENERATED_OUTPUT: {
|
|
316
|
+
bucket: 'unsafe_refused',
|
|
317
|
+
severity: 'high',
|
|
318
|
+
retrySafe: false,
|
|
319
|
+
owner: 'swipium',
|
|
320
|
+
summary: 'Generated test asset would contain a registered secret value in plaintext; nothing was written',
|
|
321
|
+
recovery: 'Report this as a Swipium bug (the recorded step should have become a ${VAR}); meanwhile re-record the credential step through a secure field or provide it via qa_continue_from_blocker so it is recorded as a variable.',
|
|
322
|
+
},
|
|
323
|
+
SECRET_ARTIFACT_IN_EVIDENCE: {
|
|
324
|
+
bucket: 'unsafe_refused',
|
|
325
|
+
severity: 'high',
|
|
326
|
+
retrySafe: false,
|
|
327
|
+
owner: 'user',
|
|
328
|
+
summary: 'Certification evidence references a secret-bearing artifact',
|
|
329
|
+
recovery: 'Remove .env/private-key/provisioning/service-account files from evidence and replace them with redacted derived proof.',
|
|
330
|
+
},
|
|
331
|
+
VISUAL_MASKING_STATUS_MISSING: {
|
|
332
|
+
bucket: 'mcp_limitation',
|
|
333
|
+
severity: 'medium',
|
|
334
|
+
retrySafe: false,
|
|
335
|
+
owner: 'user',
|
|
336
|
+
summary: 'Visual/OCR/AI evidence does not declare screenshot masking status',
|
|
337
|
+
recovery: 'Record lane.privacy.screenshotMasking or manifest.privacy.screenshotMasking before using visual/OCR/AI evidence for certification.',
|
|
338
|
+
},
|
|
339
|
+
EVIDENCE_RETENTION_UNDECLARED: {
|
|
340
|
+
bucket: 'mcp_limitation',
|
|
341
|
+
severity: 'low',
|
|
342
|
+
retrySafe: true,
|
|
343
|
+
owner: 'user',
|
|
344
|
+
summary: 'Evidence bundle has no artifact retention policy',
|
|
345
|
+
recovery: 'Declare artifact retention in the CI manifest or .swipium config so reviewers know how long screenshots/logs/reports are kept.',
|
|
346
|
+
},
|
|
347
|
+
AUTH_GATE: {
|
|
348
|
+
bucket: 'missing_data',
|
|
349
|
+
severity: 'medium',
|
|
350
|
+
retrySafe: false,
|
|
351
|
+
summary: 'Login required, no usable credentials',
|
|
352
|
+
recovery: 'Provide a test account (a fixture with a testAccount, plus SWIPIUM_TEST_EMAIL/SWIPIUM_TEST_PASSWORD).',
|
|
353
|
+
},
|
|
354
|
+
MISSING_FIXTURE: {
|
|
355
|
+
bucket: 'missing_data',
|
|
356
|
+
severity: 'medium',
|
|
357
|
+
retrySafe: false,
|
|
358
|
+
summary: 'A required precondition/fixture is absent',
|
|
359
|
+
recovery: 'Create the declared required state, or run a setup step, then re-run.',
|
|
360
|
+
},
|
|
361
|
+
MISSING_SECRET: {
|
|
362
|
+
bucket: 'missing_data',
|
|
363
|
+
severity: 'medium',
|
|
364
|
+
retrySafe: false,
|
|
365
|
+
summary: 'Required secret or flow variable is missing',
|
|
366
|
+
recovery: 'Provide the variable as an environment variable of the Swipium server/CI job (e.g. SWIPIUM_TEST_PASSWORD), or answer the needs_input question via qa_continue_from_blocker; never inline secrets in flows.',
|
|
367
|
+
},
|
|
368
|
+
OCR_NOT_CONFIGURED: {
|
|
369
|
+
bucket: 'environment',
|
|
370
|
+
severity: 'low',
|
|
371
|
+
retrySafe: false,
|
|
372
|
+
owner: 'user',
|
|
373
|
+
summary: 'No local OCR provider is configured (none is bundled)',
|
|
374
|
+
recovery: 'Set ocrCommand in .swipium/config.json (argv array with an {image} placeholder) or SWIPIUM_OCR_CMD; the command must print JSON regions [{text, confidence 0..1, bbox:{x,y,width,height} in screenshot px}]. Or use qa_visual mode:"find_image".',
|
|
375
|
+
},
|
|
376
|
+
OCR_PROVIDER_FAILED: {
|
|
377
|
+
bucket: 'environment',
|
|
378
|
+
severity: 'medium',
|
|
379
|
+
retrySafe: false,
|
|
380
|
+
owner: 'user',
|
|
381
|
+
summary: 'The configured OCR/visual-mask provider exited non-zero or timed out (its result was not trusted as "text not found")',
|
|
382
|
+
recovery: 'Read the returned exitCode + stderr, run the provider standalone from the project root on a PNG, and fix it (missing tesseract, bad script path, Python error). Relative argv paths resolve against the project root.',
|
|
383
|
+
},
|
|
384
|
+
FLOW_NOT_FOUND: {
|
|
385
|
+
bucket: 'environment',
|
|
386
|
+
severity: 'low',
|
|
387
|
+
retrySafe: true,
|
|
388
|
+
owner: 'user',
|
|
389
|
+
summary: 'The named flow file does not exist under the resolved project root',
|
|
390
|
+
recovery: 'Pass an existing flow name (.swipium/flows/<name>.yaml) or path, inline flowYaml, or projectRoot / sessionId so the flow can be resolved (SWIPIUM_PROJECT_ROOT also works).',
|
|
391
|
+
},
|
|
392
|
+
VISUAL_ONLY_SCREEN: {
|
|
393
|
+
bucket: 'mcp_limitation',
|
|
394
|
+
severity: 'low',
|
|
395
|
+
retrySafe: false,
|
|
396
|
+
summary: 'Screen has no usable UI tree (canvas/map/webview)',
|
|
397
|
+
recovery: 'Use qa_screenshot, coordinate taps, and qa_visual mode:"assert".',
|
|
398
|
+
},
|
|
399
|
+
VISUAL_LOCATOR_DRIFT: {
|
|
400
|
+
bucket: 'mcp_limitation',
|
|
401
|
+
severity: 'medium',
|
|
402
|
+
retrySafe: true,
|
|
403
|
+
summary: 'Visual/OCR locator drifted',
|
|
404
|
+
recovery: 'Refresh the screenshot crop/OCR confidence and add a fallback structured locator where the UI tree exposes one.',
|
|
405
|
+
},
|
|
406
|
+
SNAPSHOT_FAILED: {
|
|
407
|
+
bucket: 'mcp_limitation',
|
|
408
|
+
severity: 'low',
|
|
409
|
+
retrySafe: true,
|
|
410
|
+
summary: 'Could not capture the UI tree',
|
|
411
|
+
recovery: 'Retry; after repeated failures Swipium switches to visual-fallback.',
|
|
412
|
+
},
|
|
413
|
+
SNAPSHOT_TOO_DEEP: {
|
|
414
|
+
bucket: 'mcp_limitation',
|
|
415
|
+
severity: 'medium',
|
|
416
|
+
retrySafe: true,
|
|
417
|
+
summary: 'UI snapshot was too deep or slow to retrieve reliably',
|
|
418
|
+
recovery: 'Narrow the screen state, reduce UI complexity, or use visual assertions for this screen.',
|
|
419
|
+
},
|
|
420
|
+
UI_IDLE_TIMEOUT: {
|
|
421
|
+
bucket: 'mcp_limitation',
|
|
422
|
+
severity: 'medium',
|
|
423
|
+
retrySafe: true,
|
|
424
|
+
summary: 'UI did not become idle before timeout',
|
|
425
|
+
recovery: 'Wait for animations/network work to settle or add a targeted wait before interacting.',
|
|
426
|
+
},
|
|
427
|
+
STALE_REF: {
|
|
428
|
+
bucket: 'mcp_limitation',
|
|
429
|
+
severity: 'low',
|
|
430
|
+
retrySafe: true,
|
|
431
|
+
summary: 'Element ref is stale (screen changed)',
|
|
432
|
+
recovery: 'Re-run qa_snapshot to refresh refs, then retry.',
|
|
433
|
+
},
|
|
434
|
+
INVALID_SELECTOR: {
|
|
435
|
+
bucket: 'mcp_limitation',
|
|
436
|
+
severity: 'low',
|
|
437
|
+
retrySafe: true,
|
|
438
|
+
summary: 'Selector syntax or strategy is invalid',
|
|
439
|
+
recovery: 'Fix the selector syntax/strategy; for iOS WDA use accessibility id, name, predicate string, or class chain.',
|
|
440
|
+
},
|
|
441
|
+
AMBIGUOUS_SELECTOR: {
|
|
442
|
+
bucket: 'mcp_limitation',
|
|
443
|
+
severity: 'medium',
|
|
444
|
+
retrySafe: false,
|
|
445
|
+
summary: 'Selector matched more than one element',
|
|
446
|
+
recovery: 'Add a more precise locator with class/text/bounds hints or a unique testID/accessibility identifier; Swipium will not fall back to coordinates silently.',
|
|
447
|
+
},
|
|
448
|
+
ELEMENT_NOT_FOUND: {
|
|
449
|
+
bucket: 'mcp_limitation',
|
|
450
|
+
severity: 'low',
|
|
451
|
+
retrySafe: true,
|
|
452
|
+
summary: 'Target element not found',
|
|
453
|
+
recovery: 'Re-snapshot and check the selector; the element may be off-screen (scroll) or renamed (UI change).',
|
|
454
|
+
},
|
|
455
|
+
ELEMENT_NOT_HITTABLE: {
|
|
456
|
+
bucket: 'mcp_limitation',
|
|
457
|
+
severity: 'medium',
|
|
458
|
+
retrySafe: true,
|
|
459
|
+
summary: 'Element exists but is not hittable',
|
|
460
|
+
recovery: 'Inspect for overlays, disabled state, off-screen bounds, or use scroll/clear overlay before retrying.',
|
|
461
|
+
},
|
|
462
|
+
KEYBOARD_OBSTRUCTION: {
|
|
463
|
+
bucket: 'mcp_limitation',
|
|
464
|
+
severity: 'low',
|
|
465
|
+
retrySafe: true,
|
|
466
|
+
summary: 'Keyboard is covering the target',
|
|
467
|
+
recovery: 'qa_act already tried hiding the keyboard, so it could not be hidden or the target is still covered. Submit (press enter), scroll the target above the keyboard, or qa_clear_overlay hide_keyboard, then retry.',
|
|
468
|
+
},
|
|
469
|
+
KEYBOARD_NOT_DISMISSIBLE: {
|
|
470
|
+
bucket: 'mcp_limitation',
|
|
471
|
+
severity: 'low',
|
|
472
|
+
retrySafe: false,
|
|
473
|
+
summary: 'The soft keyboard is up and the backend could not dismiss it',
|
|
474
|
+
recovery: 'The app offers no generic dismiss (e.g. WDA "Did not know how to dismiss the keyboard"): submit with qa_act press key:"enter", tap outside the field (qa_clear_overlay strategy:"tap_outside") or the app\'s own Done button, then retry.',
|
|
475
|
+
},
|
|
476
|
+
TEXT_INPUT_UNSUPPORTED: {
|
|
477
|
+
bucket: 'mcp_limitation',
|
|
478
|
+
severity: 'medium',
|
|
479
|
+
retrySafe: false,
|
|
480
|
+
summary: 'Backend cannot safely type this text value',
|
|
481
|
+
recovery: 'Use ASCII-safe fixture data, configure a Unicode-safe backend, or tune WDA/Appium typing settings before replay.',
|
|
482
|
+
},
|
|
483
|
+
WEBVIEW_UNAVAILABLE: {
|
|
484
|
+
bucket: 'mcp_limitation',
|
|
485
|
+
severity: 'medium',
|
|
486
|
+
retrySafe: true,
|
|
487
|
+
summary: 'WebView context or content is unavailable to native automation',
|
|
488
|
+
recovery: 'Use visual assertions, add accessibility identifiers around the web content, or wait for the WebView to finish loading.',
|
|
489
|
+
},
|
|
490
|
+
ANIMATION_IDLE_BLOCKED: {
|
|
491
|
+
bucket: 'mcp_limitation',
|
|
492
|
+
severity: 'medium',
|
|
493
|
+
retrySafe: true,
|
|
494
|
+
summary: 'Animation prevented UI idle',
|
|
495
|
+
recovery: 'Wait for the animation to finish or disable/reduce animations in the test environment.',
|
|
496
|
+
},
|
|
497
|
+
NO_CHANGE_LOOP: {
|
|
498
|
+
bucket: 'mcp_limitation',
|
|
499
|
+
severity: 'medium',
|
|
500
|
+
retrySafe: false,
|
|
501
|
+
summary: 'Repeated actions changed nothing',
|
|
502
|
+
recovery: 'Likely wrong coordinates, a disabled control, an overlay, or an auth wall. Stop and inspect.',
|
|
503
|
+
},
|
|
504
|
+
OVERLAY_OBSTRUCTION: {
|
|
505
|
+
bucket: 'mcp_limitation',
|
|
506
|
+
severity: 'low',
|
|
507
|
+
retrySafe: true,
|
|
508
|
+
summary: 'An overlay is covering the target',
|
|
509
|
+
recovery: 'Clear it with qa_clear_overlay (keyboard/dialog/banner), then retry.',
|
|
510
|
+
},
|
|
511
|
+
STALE_CLIENT: {
|
|
512
|
+
bucket: 'mcp_limitation',
|
|
513
|
+
severity: 'medium',
|
|
514
|
+
retrySafe: true,
|
|
515
|
+
summary: 'MCP client is running an old server build',
|
|
516
|
+
recovery: 'Restart the client so it reloads the current Swipium build.',
|
|
517
|
+
},
|
|
518
|
+
BACKEND_UNSUPPORTED: {
|
|
519
|
+
bucket: 'mcp_limitation',
|
|
520
|
+
severity: 'low',
|
|
521
|
+
retrySafe: false,
|
|
522
|
+
summary: 'Operation not supported by the current backend',
|
|
523
|
+
recovery: 'For structured iOS tap/type/snapshot, attach WebDriverAgent with qa_wda. Without WDA, use qa_visual mode:"assert" and qa_ios lifecycle/deep links.',
|
|
524
|
+
},
|
|
525
|
+
BUNDLE_LOSS_REFUSED: {
|
|
526
|
+
bucket: 'unsafe_refused',
|
|
527
|
+
severity: 'low',
|
|
528
|
+
retrySafe: false,
|
|
529
|
+
summary: 'Refused a clear/reset that would wipe a debug bundle',
|
|
530
|
+
recovery: 'Expected guardrail. Use a release build for clean-state tests, or run destructive steps last.',
|
|
531
|
+
},
|
|
532
|
+
DESTRUCTIVE_REFUSED: {
|
|
533
|
+
bucket: 'unsafe_refused',
|
|
534
|
+
severity: 'low',
|
|
535
|
+
retrySafe: false,
|
|
536
|
+
summary: 'Refused a destructive action pending consent',
|
|
537
|
+
recovery: 'Expected guardrail. Approve the consent prompt only if you intend the side effect.',
|
|
538
|
+
},
|
|
539
|
+
GIT_SCOPE_FORBIDDEN: {
|
|
540
|
+
bucket: 'unsafe_refused',
|
|
541
|
+
severity: 'low',
|
|
542
|
+
retrySafe: false,
|
|
543
|
+
owner: 'user',
|
|
544
|
+
summary: 'Git command refused because Git is outside Swipium scope',
|
|
545
|
+
recovery: 'Run Git operations yourself outside Swipium; configure QA seed/provider commands to use non-Git executables.',
|
|
546
|
+
},
|
|
547
|
+
UNSAFE_ACTION_REFUSED: {
|
|
548
|
+
bucket: 'unsafe_refused',
|
|
549
|
+
severity: 'low',
|
|
550
|
+
retrySafe: false,
|
|
551
|
+
owner: 'user',
|
|
552
|
+
summary: 'Refused an unsafe action (purchase/delete/send) during exploration',
|
|
553
|
+
recovery: 'Expected guardrail. Explicitly allow this action class (e.g. allowDestructive) only if you intend its side effect.',
|
|
554
|
+
},
|
|
555
|
+
CONSENT_DECLINED: {
|
|
556
|
+
bucket: 'unsafe_refused',
|
|
557
|
+
severity: 'low',
|
|
558
|
+
retrySafe: false,
|
|
559
|
+
owner: 'user',
|
|
560
|
+
summary: 'The user declined a consent prompt (MCP elicitation); nothing ran',
|
|
561
|
+
recovery: 'Expected guardrail. Do not retry; ask the user before attempting the action again.',
|
|
562
|
+
},
|
|
563
|
+
CONSENT_CANCELLED: {
|
|
564
|
+
bucket: 'unsafe_refused',
|
|
565
|
+
severity: 'low',
|
|
566
|
+
retrySafe: true,
|
|
567
|
+
owner: 'user',
|
|
568
|
+
summary: 'A consent prompt was dismissed, timed out, or failed. Treated as a refusal; nothing ran',
|
|
569
|
+
recovery: 'Re-call the tool (without consentId) to show the user a fresh consent prompt.',
|
|
570
|
+
},
|
|
571
|
+
CANCELLED: {
|
|
572
|
+
// Not a failure: the MCP request was aborted or the job cancelled. Never recorded as a tool
|
|
573
|
+
// error, snapshot failure, finding or health verdict (lib/abortScope.ts isAbortError).
|
|
574
|
+
bucket: 'unsafe_refused',
|
|
575
|
+
severity: 'low',
|
|
576
|
+
retrySafe: true,
|
|
577
|
+
owner: 'user',
|
|
578
|
+
summary: 'The call or job was cancelled before it finished. Not a failure; nothing was recorded against the app or the tool',
|
|
579
|
+
recovery: 'Re-run the call if you still need its result.',
|
|
580
|
+
},
|
|
581
|
+
CONSENT_REFUSED: {
|
|
582
|
+
bucket: 'unsafe_refused',
|
|
583
|
+
severity: 'low',
|
|
584
|
+
retrySafe: false,
|
|
585
|
+
owner: 'user',
|
|
586
|
+
summary: 'SWIPIUM_REQUIRE_ELICITATION=1 refused a consent-gated action because the client cannot elicit',
|
|
587
|
+
recovery: 'Connect with an MCP client that supports elicitation, or unset SWIPIUM_REQUIRE_ELICITATION.',
|
|
588
|
+
},
|
|
589
|
+
VISUAL_PATH_REFUSED: {
|
|
590
|
+
bucket: 'unsafe_refused',
|
|
591
|
+
severity: 'medium',
|
|
592
|
+
retrySafe: false,
|
|
593
|
+
summary: 'Visual baseline name or template path escapes the allowed directory',
|
|
594
|
+
recovery: 'Use a plain baseline name matching [A-Za-z0-9._-]{1,64} (no leading dot) and a find_image template inside the project root or a swipium:// artifact URI from this session.',
|
|
595
|
+
},
|
|
596
|
+
SENSITIVE_MODE_REFUSED: {
|
|
597
|
+
bucket: 'unsafe_refused',
|
|
598
|
+
severity: 'low',
|
|
599
|
+
retrySafe: false,
|
|
600
|
+
owner: 'user',
|
|
601
|
+
summary: 'Pixel/video/log capture refused because the session was started in sensitive mode',
|
|
602
|
+
recovery: 'Expected guardrail: rely on structured snapshot + health (no screen contents), or start a non-sensitive session (omit sensitive:true) to capture pixels/logs.',
|
|
603
|
+
},
|
|
604
|
+
CAPTURE_WITHHELD_SECURE: {
|
|
605
|
+
bucket: 'unsafe_refused',
|
|
606
|
+
severity: 'low',
|
|
607
|
+
retrySafe: false,
|
|
608
|
+
summary: 'Screen capture withheld because a secure field (password/OTP) is on screen',
|
|
609
|
+
recovery: 'Expected guardrail (pixels cannot be redacted): capture a non-sensitive screen, or pass force:true only if the artifact may contain the secret.',
|
|
610
|
+
},
|
|
611
|
+
PHYSICAL_DEVICE_UNSUPPORTED: {
|
|
612
|
+
bucket: 'unsafe_refused',
|
|
613
|
+
severity: 'low',
|
|
614
|
+
retrySafe: false,
|
|
615
|
+
owner: 'user',
|
|
616
|
+
summary: 'A physical device is visible but Swipium is simulator/emulator-only by policy',
|
|
617
|
+
recovery: 'Expected scope guardrail (THREAT_MODEL.md non-goals, docs/physical-devices.md): real devices carry real user data. Test on an emulator/simulator, or unplug the device if it was selected by accident.',
|
|
618
|
+
},
|
|
619
|
+
// --- project detection ---
|
|
620
|
+
NOT_MOBILE_PROJECT: {
|
|
621
|
+
bucket: 'environment',
|
|
622
|
+
severity: 'high',
|
|
623
|
+
retrySafe: true,
|
|
624
|
+
owner: 'user',
|
|
625
|
+
summary: 'No supported mobile project found at the resolved root',
|
|
626
|
+
recovery: 'Pass an explicit projectRoot that contains an Expo/RN/native-Android/native-iOS/Flutter app, or run from inside one.',
|
|
627
|
+
},
|
|
628
|
+
MONOREPO_TARGET_AMBIGUOUS: {
|
|
629
|
+
bucket: 'environment',
|
|
630
|
+
severity: 'medium',
|
|
631
|
+
retrySafe: true,
|
|
632
|
+
owner: 'user',
|
|
633
|
+
summary: 'Monorepo has multiple app targets, none chosen',
|
|
634
|
+
recovery: 'Specify which app/package to test (projectRoot or target) so Swipium does not guess.',
|
|
635
|
+
},
|
|
636
|
+
PROJECT_ROOT_EMPTY: {
|
|
637
|
+
bucket: 'environment',
|
|
638
|
+
severity: 'high',
|
|
639
|
+
retrySafe: true,
|
|
640
|
+
owner: 'user',
|
|
641
|
+
summary: 'Project root is empty',
|
|
642
|
+
recovery: 'Run inside a project directory or pass projectRoot to a real app.',
|
|
643
|
+
},
|
|
644
|
+
PROJECT_ROOT_UNRESOLVED: {
|
|
645
|
+
bucket: 'environment',
|
|
646
|
+
severity: 'high',
|
|
647
|
+
retrySafe: true,
|
|
648
|
+
owner: 'user',
|
|
649
|
+
summary: 'Could not resolve a project root (no projectRoot arg, MCP roots, SWIPIUM_PROJECT_ROOT, or usable cwd)',
|
|
650
|
+
recovery: 'Pass projectRoot="/absolute/path/to/app", or set SWIPIUM_PROJECT_ROOT in the MCP server env.',
|
|
651
|
+
},
|
|
652
|
+
UNSUPPORTED_FRAMEWORK: {
|
|
653
|
+
bucket: 'environment',
|
|
654
|
+
severity: 'high',
|
|
655
|
+
retrySafe: false,
|
|
656
|
+
owner: 'user',
|
|
657
|
+
summary: 'Project framework is not supported',
|
|
658
|
+
recovery: 'Swipium supports Expo, bare React Native, native Android, native iOS, and Flutter. File a request for other frameworks.',
|
|
659
|
+
},
|
|
660
|
+
// --- artifact resolution / install ---
|
|
661
|
+
NO_BUILD_ARTIFACT: {
|
|
662
|
+
bucket: 'environment',
|
|
663
|
+
severity: 'high',
|
|
664
|
+
retrySafe: true,
|
|
665
|
+
owner: 'swipium',
|
|
666
|
+
selfFixable: true,
|
|
667
|
+
summary: 'No installable build artifact (APK/AAB/IPA/.app) found',
|
|
668
|
+
recovery: 'Build from source, pass an explicit artifact path, or drop a build under the project.',
|
|
669
|
+
},
|
|
670
|
+
MULTIPLE_ARTIFACTS_AMBIGUOUS: {
|
|
671
|
+
bucket: 'environment',
|
|
672
|
+
severity: 'medium',
|
|
673
|
+
retrySafe: true,
|
|
674
|
+
owner: 'user',
|
|
675
|
+
summary: 'Multiple candidate artifacts found, none clearly newest/best',
|
|
676
|
+
recovery: 'Pass an explicit artifact path, or accept the ranked top candidate Swipium proposes.',
|
|
677
|
+
},
|
|
678
|
+
ARTIFACT_OUTSIDE_ROOT_REQUIRES_APPROVAL: {
|
|
679
|
+
bucket: 'environment',
|
|
680
|
+
severity: 'medium',
|
|
681
|
+
retrySafe: true,
|
|
682
|
+
owner: 'user',
|
|
683
|
+
summary: 'Best artifact is outside the project root',
|
|
684
|
+
recovery: 'Re-run with allowOutsideRoot:true to use an artifact from a download/DerivedData path outside the project.',
|
|
685
|
+
},
|
|
686
|
+
BUNDLETOOL_MISSING: {
|
|
687
|
+
bucket: 'environment',
|
|
688
|
+
severity: 'high',
|
|
689
|
+
retrySafe: true,
|
|
690
|
+
owner: 'environment',
|
|
691
|
+
summary: 'bundletool is required but not installed',
|
|
692
|
+
recovery: 'Install bundletool (brew install bundletool), set $BUNDLETOOL_JAR, or build an installable APK directly.',
|
|
693
|
+
},
|
|
694
|
+
AAB_NEEDS_BUNDLETOOL: {
|
|
695
|
+
bucket: 'environment',
|
|
696
|
+
severity: 'high',
|
|
697
|
+
retrySafe: true,
|
|
698
|
+
owner: 'environment',
|
|
699
|
+
summary: 'Only a .aab exists and bundletool is not installed',
|
|
700
|
+
recovery: 'Install bundletool (brew install bundletool) so Swipium can build an installable universal APK set, or build an APK directly.',
|
|
701
|
+
},
|
|
702
|
+
AAB_BUILD_APKS_FAILED: {
|
|
703
|
+
bucket: 'environment',
|
|
704
|
+
severity: 'high',
|
|
705
|
+
retrySafe: true,
|
|
706
|
+
owner: 'environment',
|
|
707
|
+
summary: 'bundletool build-apks failed for the .aab',
|
|
708
|
+
recovery: 'Open the bundletool log, confirm the keystore/signing config, and retry; or build a universal APK directly.',
|
|
709
|
+
},
|
|
710
|
+
AAB_DEVICE_SPEC_FAILED: {
|
|
711
|
+
bucket: 'environment',
|
|
712
|
+
severity: 'high',
|
|
713
|
+
retrySafe: true,
|
|
714
|
+
owner: 'environment',
|
|
715
|
+
summary: 'bundletool could not build a device-specific APK set for the connected device',
|
|
716
|
+
recovery: 'Confirm the device is online (adb), retry the connected-device build, or fall back to a universal APK set.',
|
|
717
|
+
},
|
|
718
|
+
AAB_INSTALL_FAILED: {
|
|
719
|
+
bucket: 'environment',
|
|
720
|
+
severity: 'high',
|
|
721
|
+
retrySafe: true,
|
|
722
|
+
owner: 'environment',
|
|
723
|
+
summary: 'bundletool install-apks failed',
|
|
724
|
+
recovery: 'Confirm the device ABI/min-SDK match the generated APK set; check the install log and retry.',
|
|
725
|
+
},
|
|
726
|
+
APK_ARCH_INCOMPATIBLE: {
|
|
727
|
+
bucket: 'environment',
|
|
728
|
+
severity: 'high',
|
|
729
|
+
retrySafe: true,
|
|
730
|
+
owner: 'environment',
|
|
731
|
+
summary: 'APK native ABIs do not match the target device',
|
|
732
|
+
recovery: 'Use an APK built for the device ABI (or an emulator whose ABI matches), or build a universal APK.',
|
|
733
|
+
},
|
|
734
|
+
ANDROID_MIN_SDK_INCOMPATIBLE: {
|
|
735
|
+
bucket: 'environment',
|
|
736
|
+
severity: 'high',
|
|
737
|
+
retrySafe: false,
|
|
738
|
+
owner: 'environment',
|
|
739
|
+
summary: "APK minSdkVersion is higher than the device's API level",
|
|
740
|
+
recovery: 'Install on a device/emulator whose API level meets the APK minSdk, or lower minSdkVersion in the build and rebuild. Retrying the same install will not help.',
|
|
741
|
+
},
|
|
742
|
+
ANDROID_SIGNATURE_CONFLICT: {
|
|
743
|
+
bucket: 'environment',
|
|
744
|
+
severity: 'high',
|
|
745
|
+
retrySafe: false,
|
|
746
|
+
owner: 'swipium',
|
|
747
|
+
selfFixable: true,
|
|
748
|
+
summary: 'Installed app was signed with a different key (signature conflict)',
|
|
749
|
+
recovery: 'Uninstall the existing app (adb uninstall <package>) then reinstall; the new build is signed with a different key. This wipes the app data on that device.',
|
|
750
|
+
},
|
|
751
|
+
ANDROID_SIGNING_FAILED: {
|
|
752
|
+
bucket: 'environment',
|
|
753
|
+
severity: 'high',
|
|
754
|
+
retrySafe: true,
|
|
755
|
+
owner: 'environment',
|
|
756
|
+
summary: 'Android signing failed for the APK set',
|
|
757
|
+
recovery: 'Provide a valid debug/release keystore, or let bundletool use the default debug keystore for emulator installs.',
|
|
758
|
+
},
|
|
759
|
+
IPA_INSTALL_UNSUPPORTED: {
|
|
760
|
+
bucket: 'environment',
|
|
761
|
+
severity: 'high',
|
|
762
|
+
retrySafe: false,
|
|
763
|
+
owner: 'environment',
|
|
764
|
+
summary: 'Installing a .ipa is not supported in this environment',
|
|
765
|
+
recovery: 'Use a simulator-SDK .app for the simulator, or install the .ipa on a real device via Apple tooling (Xcode/devicectl).',
|
|
766
|
+
},
|
|
767
|
+
IPA_NEEDS_REAL_DEVICE: {
|
|
768
|
+
bucket: 'environment',
|
|
769
|
+
severity: 'high',
|
|
770
|
+
retrySafe: false,
|
|
771
|
+
owner: 'user',
|
|
772
|
+
summary: 'A .ipa targets a real device, not the simulator',
|
|
773
|
+
recovery: 'Connect a provisioned real device, or build a simulator .app for simulator testing.',
|
|
774
|
+
},
|
|
775
|
+
IPA_SIGNING_REQUIRED: {
|
|
776
|
+
bucket: 'environment',
|
|
777
|
+
severity: 'high',
|
|
778
|
+
retrySafe: false,
|
|
779
|
+
owner: 'user',
|
|
780
|
+
summary: 'Installing this app on a real device requires signing',
|
|
781
|
+
recovery: 'Configure a development team, certificate, and provisioning profile, then re-sign/rebuild the .ipa.',
|
|
782
|
+
},
|
|
783
|
+
IOS_APP_WRONG_ARCH: {
|
|
784
|
+
bucket: 'environment',
|
|
785
|
+
severity: 'high',
|
|
786
|
+
retrySafe: true,
|
|
787
|
+
owner: 'environment',
|
|
788
|
+
summary: 'iOS .app was built for the wrong destination',
|
|
789
|
+
recovery: 'Provide a simulator-SDK .app for the simulator (iphonesimulator), or a device build for a real device.',
|
|
790
|
+
},
|
|
791
|
+
IOS_SIMULATOR_APP_MISSING: {
|
|
792
|
+
bucket: 'environment',
|
|
793
|
+
severity: 'high',
|
|
794
|
+
retrySafe: true,
|
|
795
|
+
owner: 'swipium',
|
|
796
|
+
selfFixable: true,
|
|
797
|
+
summary: 'No simulator-compatible .app found',
|
|
798
|
+
recovery: 'Build an iOS simulator app, or pass an explicit simulator .app path.',
|
|
799
|
+
},
|
|
107
800
|
// --- Dev2 plan §6: iOS real-device lane ---
|
|
108
|
-
REAL_DEVICE_NOT_CONNECTED: {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
801
|
+
REAL_DEVICE_NOT_CONNECTED: {
|
|
802
|
+
bucket: 'environment',
|
|
803
|
+
severity: 'high',
|
|
804
|
+
retrySafe: true,
|
|
805
|
+
owner: 'user',
|
|
806
|
+
summary: 'No eligible connected real iOS device for a real-device run',
|
|
807
|
+
recovery: 'Connect an iPhone/iPad over USB, unlock it, trust this Mac, and enable Developer Mode, then retry.',
|
|
808
|
+
},
|
|
809
|
+
REAL_DEVICE_UDID_NOT_PROVISIONED: {
|
|
810
|
+
bucket: 'environment',
|
|
811
|
+
severity: 'high',
|
|
812
|
+
retrySafe: false,
|
|
813
|
+
owner: 'user',
|
|
814
|
+
summary: "Target device UDID is not in the artifact's provisioning profile",
|
|
815
|
+
recovery: 'Add the device UDID to the provisioning profile (or use an automatic-signing development build) and re-sign the .ipa, then retry.',
|
|
816
|
+
},
|
|
817
|
+
REAL_DEVICE_BUNDLE_ID_MISMATCH: {
|
|
818
|
+
bucket: 'environment',
|
|
819
|
+
severity: 'high',
|
|
820
|
+
retrySafe: false,
|
|
821
|
+
owner: 'user',
|
|
822
|
+
summary: 'Artifact bundle id does not match the provisioning profile / target',
|
|
823
|
+
recovery: 'Sign the .ipa with a provisioning profile whose app id matches the bundle id under test, then retry.',
|
|
824
|
+
},
|
|
825
|
+
REAL_DEVICE_TEAM_MISMATCH: {
|
|
826
|
+
bucket: 'environment',
|
|
827
|
+
severity: 'high',
|
|
828
|
+
retrySafe: false,
|
|
829
|
+
owner: 'user',
|
|
830
|
+
summary: 'Signing team does not match the provisioning profile team',
|
|
831
|
+
recovery: 'Re-sign the .ipa so the codesign team identifier matches the provisioning profile team, then retry.',
|
|
832
|
+
},
|
|
833
|
+
// --- build-from-source ---
|
|
834
|
+
BUILD_COMMAND_UNAVAILABLE: {
|
|
835
|
+
bucket: 'environment',
|
|
836
|
+
severity: 'high',
|
|
837
|
+
retrySafe: true,
|
|
838
|
+
owner: 'environment',
|
|
839
|
+
summary: 'No build command is available for this framework/platform',
|
|
840
|
+
recovery: 'Install the required toolchain (Gradle/Xcode/Flutter/Expo CLI) or provide a prebuilt artifact.',
|
|
841
|
+
},
|
|
842
|
+
BUILD_FAILED: {
|
|
843
|
+
bucket: 'environment',
|
|
844
|
+
severity: 'high',
|
|
845
|
+
retrySafe: false,
|
|
846
|
+
owner: 'app',
|
|
847
|
+
selfFixable: false,
|
|
848
|
+
summary: 'Build from source failed',
|
|
849
|
+
recovery: 'Open the build log artifact, fix the compile/config error, then re-run the build. A build failure is NOT a test failure.',
|
|
850
|
+
},
|
|
851
|
+
BUILD_ARTIFACT_UNRESOLVED_AFTER_SUCCESS: {
|
|
852
|
+
bucket: 'environment',
|
|
853
|
+
severity: 'high',
|
|
854
|
+
retrySafe: true,
|
|
855
|
+
owner: 'swipium',
|
|
856
|
+
selfFixable: true,
|
|
857
|
+
summary: 'Build succeeded but Swipium could not resolve the produced app',
|
|
858
|
+
recovery: 'The build command succeeded. This is an artifact-resolution gap, not an app build failure. Pass an explicit artifact path, or for Expo iOS point Swipium at the .app under Xcode DerivedData.',
|
|
859
|
+
},
|
|
860
|
+
BUILD_TIMED_OUT: {
|
|
861
|
+
bucket: 'environment',
|
|
862
|
+
severity: 'high',
|
|
863
|
+
retrySafe: true,
|
|
864
|
+
owner: 'environment',
|
|
865
|
+
summary: 'Build exceeded its time budget',
|
|
866
|
+
recovery: 'Increase the build timeout, warm caches, or build once manually then re-run Swipium against the artifact.',
|
|
867
|
+
},
|
|
868
|
+
DEPENDENCY_INSTALL_REQUIRED: {
|
|
869
|
+
bucket: 'environment',
|
|
870
|
+
severity: 'medium',
|
|
871
|
+
retrySafe: true,
|
|
872
|
+
owner: 'environment',
|
|
873
|
+
summary: 'Dependencies must be installed before building',
|
|
874
|
+
recovery: 'Run the project install step (npm/yarn/pnpm install, pod install, flutter pub get), then re-run the build.',
|
|
875
|
+
},
|
|
876
|
+
EXPO_PREBUILD_REQUIRED: {
|
|
877
|
+
bucket: 'environment',
|
|
878
|
+
severity: 'medium',
|
|
879
|
+
retrySafe: true,
|
|
880
|
+
owner: 'swipium',
|
|
881
|
+
selfFixable: true,
|
|
882
|
+
summary: 'Expo project has no native android/ios directories',
|
|
883
|
+
recovery: 'Run `npx expo prebuild` (or build with `npx expo run:*` which prebuilds) before a native build.',
|
|
884
|
+
},
|
|
885
|
+
GRADLE_FAILED: {
|
|
886
|
+
bucket: 'environment',
|
|
887
|
+
severity: 'high',
|
|
888
|
+
retrySafe: false,
|
|
889
|
+
owner: 'app',
|
|
890
|
+
summary: 'Gradle build failed',
|
|
891
|
+
recovery: 'Open the Gradle log artifact and fix the reported error (SDK/dependency/compile), then retry.',
|
|
892
|
+
},
|
|
893
|
+
XCODEBUILD_FAILED: {
|
|
894
|
+
bucket: 'environment',
|
|
895
|
+
severity: 'high',
|
|
896
|
+
retrySafe: false,
|
|
897
|
+
owner: 'app',
|
|
898
|
+
summary: 'xcodebuild failed',
|
|
899
|
+
recovery: 'Open the xcodebuild log artifact and fix the reported error (scheme/signing/compile), then retry.',
|
|
900
|
+
},
|
|
901
|
+
FLUTTER_BUILD_FAILED: {
|
|
902
|
+
bucket: 'environment',
|
|
903
|
+
severity: 'high',
|
|
904
|
+
retrySafe: false,
|
|
905
|
+
owner: 'app',
|
|
906
|
+
summary: 'flutter build failed',
|
|
907
|
+
recovery: 'Open the flutter build log artifact and fix the reported error, then retry.',
|
|
908
|
+
},
|
|
909
|
+
// --- runtime ---
|
|
910
|
+
METRO_REQUIRED: {
|
|
911
|
+
bucket: 'environment',
|
|
912
|
+
severity: 'high',
|
|
913
|
+
retrySafe: true,
|
|
914
|
+
owner: 'swipium',
|
|
915
|
+
selfFixable: true,
|
|
916
|
+
summary: 'A debug RN/Expo build needs Metro running',
|
|
917
|
+
recovery: 'Start the bundler so the debug build can fetch its JS bundle.',
|
|
918
|
+
},
|
|
919
|
+
METRO_FAILED: {
|
|
920
|
+
bucket: 'environment',
|
|
921
|
+
severity: 'high',
|
|
922
|
+
retrySafe: true,
|
|
923
|
+
owner: 'environment',
|
|
924
|
+
summary: 'Metro/dev server failed to start or stay healthy',
|
|
925
|
+
recovery: 'Check the Metro log artifact (port in use, dependency error), free the port, then restart.',
|
|
926
|
+
},
|
|
927
|
+
DEVICE_BOOT_FAILED: {
|
|
928
|
+
bucket: 'environment',
|
|
929
|
+
severity: 'high',
|
|
930
|
+
retrySafe: true,
|
|
931
|
+
owner: 'swipium',
|
|
932
|
+
selfFixable: true,
|
|
933
|
+
summary: 'Emulator/simulator failed to boot',
|
|
934
|
+
recovery: 'Retry boot, free host resources, or pick a different AVD/simulator runtime.',
|
|
935
|
+
},
|
|
936
|
+
APP_LAUNCH_FAILED: {
|
|
937
|
+
bucket: 'environment',
|
|
938
|
+
severity: 'high',
|
|
939
|
+
retrySafe: true,
|
|
940
|
+
owner: 'environment',
|
|
941
|
+
summary: 'App was installed but failed to launch',
|
|
942
|
+
recovery: 'Confirm the bundle/app id, check the device log for the launch error, and verify Metro (for debug builds) is reachable.',
|
|
943
|
+
},
|
|
944
|
+
// --- automation / durability ---
|
|
945
|
+
MISSING_DURABLE_LOCATOR: {
|
|
946
|
+
bucket: 'mcp_limitation',
|
|
947
|
+
severity: 'medium',
|
|
948
|
+
retrySafe: false,
|
|
949
|
+
owner: 'app',
|
|
950
|
+
summary: 'A UI element has no durable locator (no testID/accessibilityIdentifier/resource-id)',
|
|
951
|
+
recovery: 'Add an accessibilityIdentifier (iOS) / testID / resource-id to the element so automation is stable; coordinate fallback is brittle.',
|
|
952
|
+
},
|
|
953
|
+
COORDINATE_ONLY_FLOW: {
|
|
954
|
+
bucket: 'mcp_limitation',
|
|
955
|
+
severity: 'medium',
|
|
956
|
+
retrySafe: false,
|
|
957
|
+
owner: 'app',
|
|
958
|
+
summary: 'Flow relies on coordinate taps (brittle)',
|
|
959
|
+
recovery: 'Add testIDs/accessibility identifiers to the tapped elements, then regenerate the flow for durable selectors.',
|
|
960
|
+
},
|
|
961
|
+
VISUAL_ONLY_ASSERTION: {
|
|
962
|
+
bucket: 'mcp_limitation',
|
|
963
|
+
severity: 'low',
|
|
964
|
+
retrySafe: false,
|
|
965
|
+
owner: 'swipium',
|
|
966
|
+
summary: 'Verification was visual-only, not structurally asserted',
|
|
967
|
+
recovery: 'Treat as weaker evidence. Add structured assertions where the UI tree is available; keep the screenshot as evidence.',
|
|
968
|
+
},
|
|
969
|
+
AUTH_REQUIRED: {
|
|
970
|
+
bucket: 'missing_data',
|
|
971
|
+
severity: 'medium',
|
|
972
|
+
retrySafe: false,
|
|
973
|
+
owner: 'user',
|
|
974
|
+
summary: 'Login required to reach this workflow',
|
|
975
|
+
recovery: 'Provide test credentials (SWIPIUM_TEST_EMAIL/SWIPIUM_TEST_PASSWORD in the server env, or via qa_continue_from_blocker), or accept pre-login-only coverage.',
|
|
976
|
+
},
|
|
977
|
+
MISSING_TEST_DATA: {
|
|
978
|
+
bucket: 'missing_data',
|
|
979
|
+
severity: 'medium',
|
|
980
|
+
retrySafe: false,
|
|
981
|
+
owner: 'user',
|
|
982
|
+
summary: 'Required test data/fixture is missing',
|
|
983
|
+
recovery: 'Seed or provide the required state (account, record, entitlement), then re-run; do not fake coverage.',
|
|
984
|
+
},
|
|
985
|
+
// --- tool-local codes ---
|
|
986
|
+
ISSUE_LOG_TOO_VAGUE: {
|
|
987
|
+
bucket: 'missing_data',
|
|
988
|
+
severity: 'low',
|
|
989
|
+
retrySafe: true,
|
|
990
|
+
owner: 'user',
|
|
991
|
+
summary: 'The issue title has no identifying words once ids/numbers are scrubbed, so it would merge with unrelated issues',
|
|
992
|
+
recovery: 'Log it with a descriptive title (what broke, where), or pass a failureCode.',
|
|
993
|
+
},
|
|
994
|
+
ISSUE_NOT_FOUND: {
|
|
995
|
+
bucket: 'missing_data',
|
|
996
|
+
severity: 'low',
|
|
997
|
+
retrySafe: true,
|
|
998
|
+
owner: 'user',
|
|
999
|
+
summary: 'No issue in the project ledger matches the given issueId/fingerprint',
|
|
1000
|
+
recovery: 'List issues with qa_issue_log mode:"history" and pass an existing issueId.',
|
|
1001
|
+
},
|
|
1002
|
+
ISSUE_STATE_INVALID: {
|
|
1003
|
+
bucket: 'unsafe_refused',
|
|
1004
|
+
severity: 'low',
|
|
1005
|
+
retrySafe: false,
|
|
1006
|
+
owner: 'user',
|
|
1007
|
+
summary: "The requested lifecycle transition is not allowed from the issue's current state",
|
|
1008
|
+
recovery: 'mark_fixed only applies to an active issue, verify_fixed only to a fixed one, unsuppress only to a suppressed one. Check the state with mode:"history".',
|
|
1009
|
+
},
|
|
1010
|
+
ISSUE_EVIDENCE_REQUIRED: {
|
|
1011
|
+
bucket: 'missing_data',
|
|
1012
|
+
severity: 'low',
|
|
1013
|
+
retrySafe: true,
|
|
1014
|
+
owner: 'user',
|
|
1015
|
+
summary: 'verify_fixed needs evidence from the current run',
|
|
1016
|
+
recovery: 'Pass a reportUri, testCaseId, auditCheckId, or evidenceUris from the run that proves the fix.',
|
|
1017
|
+
},
|
|
1018
|
+
NO_APP_MAP: {
|
|
1019
|
+
bucket: 'missing_data',
|
|
1020
|
+
severity: 'low',
|
|
1021
|
+
retrySafe: true,
|
|
1022
|
+
owner: 'swipium',
|
|
1023
|
+
selfFixable: true,
|
|
1024
|
+
summary: 'No app knowledge map exists for this project yet',
|
|
1025
|
+
recovery: 'Build it with qa_app_map_build (qa_test_this and qa_explore also update it).',
|
|
1026
|
+
},
|
|
1027
|
+
NO_RECORDED_ACTIONS: {
|
|
1028
|
+
bucket: 'missing_data',
|
|
1029
|
+
severity: 'low',
|
|
1030
|
+
retrySafe: true,
|
|
1031
|
+
owner: 'swipium',
|
|
1032
|
+
summary: 'The session has no recorded actions to generate assets from',
|
|
1033
|
+
recovery: 'Drive the app first (qa_smoke / qa_explore / qa_act), or let qa_generate target:"appium" bootstrap from projectRoot.',
|
|
1034
|
+
},
|
|
1035
|
+
UNEMITTABLE_STEP: {
|
|
1036
|
+
bucket: 'mcp_limitation',
|
|
1037
|
+
severity: 'medium',
|
|
1038
|
+
retrySafe: false,
|
|
1039
|
+
summary: 'A recorded step cannot be emitted as Appium code (no selector or gesture the target language can express)',
|
|
1040
|
+
recovery: 'Re-record the step with a durable selector (testID / accessibilityIdentifier), or remove it before generating.',
|
|
1041
|
+
},
|
|
1042
|
+
INVALID_ARGUMENT: {
|
|
1043
|
+
bucket: 'unsafe_refused',
|
|
1044
|
+
severity: 'low',
|
|
1045
|
+
retrySafe: true,
|
|
1046
|
+
owner: 'user',
|
|
1047
|
+
summary: 'A tool argument is malformed (e.g. a timestamp that does not parse)',
|
|
1048
|
+
recovery: 'Fix the argument as described in the error and re-call the tool.',
|
|
1049
|
+
},
|
|
1050
|
+
UNKNOWN: {
|
|
1051
|
+
bucket: 'mcp_limitation',
|
|
1052
|
+
severity: 'low',
|
|
1053
|
+
retrySafe: true,
|
|
1054
|
+
summary: 'Unclassified failure',
|
|
1055
|
+
recovery: 'Inspect the message; consider filing it so the taxonomy can cover it.',
|
|
1056
|
+
},
|
|
134
1057
|
};
|
|
135
1058
|
/** Default owner derived from the failure bucket, unless the entry sets one explicitly (§10). */
|
|
136
1059
|
const OWNER_BY_BUCKET = {
|
|
@@ -140,40 +1063,57 @@ const OWNER_BY_BUCKET = {
|
|
|
140
1063
|
mcp_limitation: 'swipium',
|
|
141
1064
|
unsafe_refused: 'user',
|
|
142
1065
|
};
|
|
143
|
-
/** Likely owner of a failure code's fix
|
|
1066
|
+
/** Likely owner of a failure code's fix. */
|
|
144
1067
|
export function failureOwner(code) {
|
|
145
1068
|
const info = FAILURES[code];
|
|
146
1069
|
return info.owner ?? OWNER_BY_BUCKET[info.bucket];
|
|
147
1070
|
}
|
|
148
|
-
/** Whether Swipium can plausibly fix this itself
|
|
1071
|
+
/** Whether Swipium can plausibly fix this itself. */
|
|
149
1072
|
export function isSelfFixable(code) {
|
|
150
1073
|
return FAILURES[code].selfFixable ?? false;
|
|
151
1074
|
}
|
|
152
1075
|
/** Map a deterministic health finding kind (oracle) to a failure code. */
|
|
153
1076
|
export function failureForFindingKind(kind) {
|
|
154
1077
|
switch (kind) {
|
|
155
|
-
case 'native_crash':
|
|
156
|
-
|
|
157
|
-
case '
|
|
158
|
-
|
|
159
|
-
case '
|
|
160
|
-
|
|
161
|
-
case '
|
|
162
|
-
|
|
163
|
-
case '
|
|
164
|
-
|
|
165
|
-
case '
|
|
166
|
-
|
|
1078
|
+
case 'native_crash':
|
|
1079
|
+
return 'NATIVE_CRASH';
|
|
1080
|
+
case 'anr':
|
|
1081
|
+
return 'ANR';
|
|
1082
|
+
case 'wrong_foreground_app':
|
|
1083
|
+
return 'WRONG_FOREGROUND';
|
|
1084
|
+
case 'wda_unreachable':
|
|
1085
|
+
return 'WDA_UNREACHABLE';
|
|
1086
|
+
case 'permission_dialog':
|
|
1087
|
+
return 'PERMISSION_DIALOG';
|
|
1088
|
+
case 'native_alert':
|
|
1089
|
+
return 'NATIVE_ALERT';
|
|
1090
|
+
case 'rn_redbox':
|
|
1091
|
+
return 'REDBOX';
|
|
1092
|
+
case 'rn_logbox_error':
|
|
1093
|
+
return 'LOGBOX';
|
|
1094
|
+
case 'app_error_boundary':
|
|
1095
|
+
return 'ERROR_BOUNDARY';
|
|
1096
|
+
case 'webview_error':
|
|
1097
|
+
return 'ERROR_BOUNDARY';
|
|
1098
|
+
case 'unknown_error_surface':
|
|
1099
|
+
return 'BACKEND_ERROR';
|
|
1100
|
+
default:
|
|
1101
|
+
return 'UNKNOWN';
|
|
167
1102
|
}
|
|
168
1103
|
}
|
|
169
1104
|
/** Map a qa_note category to a bucket (for outcomes recorded by the agent). */
|
|
170
1105
|
export function bucketForNoteCategory(category) {
|
|
171
1106
|
switch (category) {
|
|
172
|
-
case 'app_bug':
|
|
173
|
-
|
|
174
|
-
case '
|
|
175
|
-
|
|
176
|
-
|
|
1107
|
+
case 'app_bug':
|
|
1108
|
+
return 'app_bug';
|
|
1109
|
+
case 'missing_test_data':
|
|
1110
|
+
return 'missing_data';
|
|
1111
|
+
case 'destructive_refused':
|
|
1112
|
+
return 'unsafe_refused';
|
|
1113
|
+
case 'mcp_limitation':
|
|
1114
|
+
return 'mcp_limitation';
|
|
1115
|
+
default:
|
|
1116
|
+
return 'mcp_limitation';
|
|
177
1117
|
}
|
|
178
1118
|
}
|
|
179
1119
|
export const ALL_BUCKETS = ['app_bug', 'environment', 'missing_data', 'mcp_limitation', 'unsafe_refused'];
|