mobile-debug-mcp 0.34.0 → 0.35.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/.agents/skills/mcp-builder/SKILL.md +44 -64
- package/.agents/skills/mcp-builder/references/build-flags.md +44 -43
- package/.agents/skills/mcp-builder/references/diagnostics-schema.md +4 -1
- package/.agents/skills/mcp-builder/references/toolchain-details.md +49 -62
- package/.agents/skills/spec-review/references/spec-review-checklist.md +7 -0
- package/.agents/skills/test-authoring/SKILL.md +7 -6
- package/.agents/skills/test-authoring/references/repo-test-layout.md +3 -1
- package/.agents/skills/test-authoring/references/test-authoring-workflow.md +16 -7
- package/.agents/skills/test-authoring/references/test-quality-checklist.md +2 -1
- package/.github/copilot-instructions.md +14 -36
- package/.github/workflows/ci.yml +4 -4
- package/AGENTS.md +12 -3
- package/CONTRIBUTING.md +79 -0
- package/README.md +156 -129
- package/agent-plugin/.claude-plugin/plugin.json +2 -2
- package/agent-plugin/.codex-plugin/plugin.json +1 -1
- package/agent-plugin/.cursor-plugin/plugin.json +2 -2
- package/agent-plugin/.mcp.json +1 -1
- package/agent-plugin/README.md +16 -6
- package/agent-plugin/mcp.json +1 -1
- package/agent-plugin/plugin.json +1 -1
- package/agent-plugin/skills/mobile-debug-mcp/SKILL.md +27 -2
- package/dist/contracts/execution-controls.js +24 -0
- package/dist/contracts/selector.js +8 -0
- package/dist/contracts/target.js +15 -0
- package/dist/contracts/ui.js +1 -0
- package/dist/debugger/android.js +2 -1
- package/dist/debugger/diagnostics.js +54 -0
- package/dist/debugger/protocol.js +33 -0
- package/dist/debugger/sessions.js +104 -62
- package/dist/debugger/worker.js +53 -42
- package/dist/interact/adjustment/adjustment-context.js +41 -0
- package/dist/interact/adjustment/adjustment-gestures.js +55 -0
- package/dist/interact/adjustment/adjustment-plan.js +18 -0
- package/dist/interact/adjustment/adjustment-resolution.js +127 -0
- package/dist/interact/adjustment/adjustment-result.js +19 -0
- package/dist/interact/adjustment/adjustment-semantic.js +64 -0
- package/dist/interact/adjustment/adjustment-verification.js +35 -0
- package/dist/interact/adjustment/adjustment.js +52 -0
- package/dist/interact/adjustment/control-geometry.js +87 -0
- package/dist/interact/adjustment/control-values.js +136 -0
- package/dist/interact/adjustment/slider-labels.js +84 -0
- package/dist/interact/assertions/screen-assertion.js +37 -0
- package/dist/interact/assertions/state-assertion-context.js +35 -0
- package/dist/interact/assertions/state-assertion.js +76 -0
- package/dist/interact/assertions/state-comparison.js +141 -0
- package/dist/interact/assertions/visibility-assertion.js +34 -0
- package/dist/interact/conditional-action.js +12 -7
- package/dist/interact/index.js +65 -3090
- package/dist/interact/input-service.js +1 -0
- package/dist/interact/interaction-trace.js +21 -0
- package/dist/interact/model.js +1 -0
- package/dist/interact/observation.js +1 -0
- package/dist/interact/targeting/candidate-ancestor.js +58 -0
- package/dist/interact/targeting/candidate-result.js +23 -0
- package/dist/interact/targeting/candidate-scoring.js +50 -0
- package/dist/interact/targeting/element-helpers.js +216 -0
- package/dist/interact/targeting/find-element.js +65 -0
- package/dist/interact/targeting/nearby-control.js +56 -0
- package/dist/interact/targeting/resolved-elements.js +21 -0
- package/dist/interact/targeting/tap-target.js +17 -0
- package/dist/interact/targeting/target-scope.js +104 -0
- package/dist/interact/waits/legacy-log-wait.js +38 -0
- package/dist/interact/waits/legacy-wait-observations.js +103 -0
- package/dist/interact/waits/legacy-wait-state.js +34 -0
- package/dist/interact/waits/legacy-wait.js +48 -0
- package/dist/interact/waits/screen-wait.js +49 -0
- package/dist/interact/waits/ui-change-helpers.js +157 -0
- package/dist/interact/waits/ui-change-state.js +18 -0
- package/dist/interact/waits/ui-change-wait.js +77 -0
- package/dist/interact/waits/ui-wait-condition.js +56 -0
- package/dist/interact/waits/ui-wait-state.js +38 -0
- package/dist/interact/waits/ui-wait.js +106 -0
- package/dist/manage/android.js +55 -51
- package/dist/manage/index.js +38 -75
- package/dist/manage/ios/build-types.js +1 -0
- package/dist/manage/ios/build.js +210 -0
- package/dist/manage/ios/project-discovery.js +29 -0
- package/dist/manage/ios/scheme.js +18 -0
- package/dist/manage/ios.js +42 -256
- package/dist/observe/android/context.js +1 -0
- package/dist/observe/android/current-screen.js +55 -0
- package/dist/observe/android/fingerprint.js +13 -0
- package/dist/observe/android/log-stream.js +132 -0
- package/dist/observe/android/logs.js +107 -0
- package/dist/observe/android/screenshot.js +70 -0
- package/dist/observe/android/ui-tree.js +107 -0
- package/dist/observe/android.js +16 -520
- package/dist/observe/evidence.js +114 -75
- package/dist/observe/index.js +16 -263
- package/dist/observe/ios/context.js +16 -0
- package/dist/observe/ios/fingerprint.js +12 -0
- package/dist/observe/ios/log-stream.js +105 -0
- package/dist/observe/ios/logs.js +168 -0
- package/dist/observe/ios/screenshot.js +22 -0
- package/dist/observe/ios/ui-elements.js +241 -0
- package/dist/observe/ios/ui-tree.js +137 -0
- package/dist/observe/ios.js +17 -715
- package/dist/observe/logs/model.js +1 -0
- package/dist/{network → observe/network}/index.js +2 -2
- package/dist/observe/readiness-service.js +4 -2
- package/dist/observe/readiness.js +29 -10
- package/dist/observe/screenshot-encoding.js +41 -0
- package/dist/observe/snapshot-collection.js +79 -0
- package/dist/observe/snapshot-logs.js +30 -0
- package/dist/observe/snapshot-metadata.js +43 -31
- package/dist/observe/snapshot-semantic.js +115 -0
- package/dist/observe/system-trace.js +22 -13
- package/dist/runtime/action-results.js +270 -0
- package/dist/runtime/clock.js +4 -0
- package/dist/server/common.js +1 -256
- package/dist/server/definitions/assert.js +162 -0
- package/dist/server/definitions/diagnostic.js +118 -0
- package/dist/server/definitions/input.js +274 -0
- package/dist/server/definitions/manage.js +194 -0
- package/dist/server/definitions/observe.js +149 -0
- package/dist/server/definitions/target.js +138 -0
- package/dist/server/definitions/wait.js +105 -0
- package/dist/server/handlers/action-execution.js +163 -0
- package/dist/server/handlers/correlation.js +23 -0
- package/dist/server/{debugger-handlers.js → handlers/debugger-handlers.js} +22 -12
- package/dist/server/handlers/debugger-response.js +9 -0
- package/dist/server/handlers/diagnostic.js +69 -0
- package/dist/server/handlers/handler-types.js +1 -0
- package/dist/server/handlers/input.js +154 -0
- package/dist/server/handlers/interact.js +113 -0
- package/dist/server/handlers/journey-assertions.js +35 -0
- package/dist/server/handlers/journey.js +147 -0
- package/dist/server/handlers/manage.js +119 -0
- package/dist/server/handlers/observe.js +95 -0
- package/dist/server/handlers/payload.js +4 -0
- package/dist/server/handlers/tool-handlers.js +160 -0
- package/dist/server/schemas/condition-schema.js +2 -0
- package/dist/server/{debugger-schema.js → schemas/debugger-schema.js} +11 -6
- package/dist/server/{journey-schema.js → schemas/journey-schema.js} +7 -22
- package/dist/server/tool-definitions.js +58 -1135
- package/dist/server-core.js +2 -2
- package/dist/system/android-status.js +101 -0
- package/dist/system/android.js +37 -27
- package/dist/system/index.js +13 -439
- package/dist/system/ios-status.js +132 -0
- package/dist/system/ios.js +11 -8
- package/dist/system/model.js +1 -0
- package/dist/system/probes.js +105 -0
- package/dist/system/status-summary.js +43 -0
- package/dist/system/unsupported-status.js +52 -0
- package/dist/utils/android/commands.js +89 -0
- package/dist/utils/android/gradle.js +139 -0
- package/dist/utils/android/logs.js +103 -0
- package/dist/utils/android/ui-tree.js +233 -0
- package/dist/utils/android/utils.js +6 -564
- package/dist/utils/cli/idb/idb-helper.js +4 -6
- package/dist/utils/cli/idb/install-idb.js +13 -9
- package/dist/utils/cli/ios/preflight-ios.js +42 -38
- package/dist/utils/ios/utils.js +45 -46
- package/dist/utils/java.js +65 -49
- package/dist/utils/resolve-device.js +4 -2
- package/dist/utils/ui/index.js +26 -26
- package/docs/CHANGELOG.md +44 -0
- package/docs/README.md +38 -0
- package/docs/benchmarks/README.md +18 -0
- package/docs/benchmarks/interaction-latency/README.md +14 -0
- package/docs/benchmarks/interaction-latency/final.md +4 -1
- package/docs/benchmarks/interaction-latency/ios-validation.md +2 -0
- package/docs/benchmarks/ui-tree-performance/README.md +24 -16
- package/docs/benchmarks/ui-tree-performance/comparison.md +11 -10
- package/docs/code-structure.md +118 -0
- package/docs/specs/001-state-verification/spec.md +16 -14
- package/docs/specs/002-richer-element-identity/spec.md +12 -10
- package/docs/specs/003-wait-and-synchronization-reliability/spec.md +12 -10
- package/docs/specs/004-action-verification-routing/spec.md +3 -3
- package/docs/specs/005-unified-action-execution-and-verification-model/spec.md +2 -0
- package/docs/specs/006-runtime-action-instrumentation-and-binding-layer/spec.md +2 -0
- package/docs/specs/007-actionability-resolution-and-executable-target-selection/spec.md +3 -1
- package/docs/specs/008-adjustable-control-support-and-semantic-value-manipulation/spec.md +3 -4
- package/docs/specs/009-semantic-control-modeling-for-custom-and-composite-controls/spec.md +2 -0
- package/docs/specs/010-verification-stabilization-and-temporal-convergence/spec.md +2 -2
- package/docs/specs/011-recovery-and-replanning-for-failed-or-ambiguous-interaction-flows/spec.md +2 -2
- package/docs/specs/011.1-recovery-contract-types-and-runtime-wiring-spec/spec.md +2 -0
- package/docs/specs/012-action-trace-and-xecution-observability/spec.md +2 -3
- package/docs/specs/013-wait-and-synchronization-reliability/spec.md +19 -19
- package/docs/specs/014-actionability-resolution/spec.md +20 -18
- package/docs/specs/015-adjustable-control-support/spec.md +17 -15
- package/docs/specs/016-environment-tools/spec.md +20 -20
- package/docs/specs/018-interaction-latency-and-batched-journeys/spec.md +2 -0
- package/docs/specs/019-ui-tree-observation-performance/spec.md +3 -1
- package/docs/specs/020-conditional-actions/intent.md +5 -3
- package/docs/specs/020-conditional-actions/plan.md +8 -9
- package/docs/specs/020-conditional-actions/spec.md +4 -2
- package/docs/specs/021-app-readiness-signals/intent.md +4 -2
- package/docs/specs/021-app-readiness-signals/plan.md +7 -6
- package/docs/specs/021-app-readiness-signals/spec.md +3 -1
- package/docs/specs/022-correlated-evidence/intent.md +4 -4
- package/docs/specs/022-correlated-evidence/plan.md +10 -11
- package/docs/specs/022-correlated-evidence/spec.md +3 -1
- package/docs/specs/023-android-system-traces/intent.md +3 -2
- package/docs/specs/023-android-system-traces/plan.md +5 -7
- package/docs/specs/023-android-system-traces/spec.md +3 -1
- package/docs/specs/024-android-heap-dump-capture/intent.md +3 -1
- package/docs/specs/025-android-runtime-debugger/intent.md +4 -3
- package/docs/specs/025-android-runtime-debugger/plan.md +3 -1
- package/docs/specs/025-android-runtime-debugger/spec.md +4 -3
- package/docs/specs/026-code-structure-and-quality-gates/health-plan.md +88 -0
- package/docs/specs/026-code-structure-and-quality-gates/intent.md +47 -0
- package/docs/specs/026-code-structure-and-quality-gates/plan.md +191 -0
- package/docs/specs/026-code-structure-and-quality-gates/spec.md +138 -0
- package/docs/specs/026-code-structure-and-quality-gates/verification-final.json +200 -0
- package/docs/specs/026-code-structure-and-quality-gates/verification-thin-facade.json +154 -0
- package/docs/specs/026-code-structure-and-quality-gates/verification.json +136 -0
- package/docs/specs/027-debugger-failure-diagnostics/intent.md +43 -0
- package/docs/specs/027-debugger-failure-diagnostics/plan.md +86 -0
- package/docs/specs/027-debugger-failure-diagnostics/spec.md +133 -0
- package/docs/specs/028-compact-debugger-responses/intent.md +41 -0
- package/docs/specs/028-compact-debugger-responses/plan.md +112 -0
- package/docs/specs/028-compact-debugger-responses/spec.md +108 -0
- package/docs/specs/029-kotlin-locals-validation/report.md +119 -0
- package/docs/specs/030-android-coroutine-validation/evidence.json +475 -0
- package/docs/specs/030-android-coroutine-validation/intent.md +47 -0
- package/docs/specs/030-android-coroutine-validation/plan.md +147 -0
- package/docs/specs/030-android-coroutine-validation/report.md +240 -0
- package/docs/specs/030-android-coroutine-validation/spec.md +107 -0
- package/docs/tools/TOOLS.md +31 -18
- package/docs/tools/{evidence.md → correlated-evidence.md} +9 -1
- package/docs/tools/debugger.md +76 -0
- package/docs/tools/interact.md +42 -20
- package/docs/tools/manage.md +25 -44
- package/docs/tools/observe.md +55 -23
- package/docs/tools/system-traces.md +9 -1
- package/docs/tools/system.md +12 -5
- package/package.json +11 -8
- package/scripts/architecture-graph.mjs +69 -0
- package/scripts/check-architecture.mjs +47 -0
- package/scripts/code-quality-baseline.json +1 -0
- package/scripts/code-quality.mjs +161 -0
- package/src/contracts/execution-controls.ts +26 -0
- package/src/contracts/selector.ts +17 -0
- package/src/contracts/target.ts +19 -0
- package/src/contracts/ui.ts +94 -0
- package/src/debugger/android.ts +2 -1
- package/src/debugger/diagnostics.ts +43 -0
- package/src/debugger/guard.ts +6 -1
- package/{worker → src/debugger/java}/DebuggerWorker.java +9 -3
- package/src/debugger/protocol.ts +37 -0
- package/src/debugger/sessions.ts +314 -155
- package/src/debugger/worker.ts +51 -38
- package/src/interact/adjustment/adjustment-context.ts +83 -0
- package/src/interact/adjustment/adjustment-gestures.ts +48 -0
- package/src/interact/adjustment/adjustment-plan.ts +23 -0
- package/src/interact/adjustment/adjustment-resolution.ts +104 -0
- package/src/interact/adjustment/adjustment-result.ts +34 -0
- package/src/interact/adjustment/adjustment-semantic.ts +53 -0
- package/src/interact/adjustment/adjustment-verification.ts +60 -0
- package/src/interact/adjustment/adjustment.ts +49 -0
- package/src/interact/adjustment/control-geometry.ts +120 -0
- package/src/interact/adjustment/control-values.ts +141 -0
- package/src/interact/adjustment/slider-labels.ts +84 -0
- package/src/interact/assertions/screen-assertion.ts +39 -0
- package/src/interact/assertions/state-assertion-context.ts +48 -0
- package/src/interact/assertions/state-assertion.ts +64 -0
- package/src/interact/assertions/state-comparison.ts +168 -0
- package/src/interact/assertions/visibility-assertion.ts +41 -0
- package/src/interact/conditional-action.ts +18 -12
- package/src/interact/index.ts +76 -3492
- package/src/interact/input-service.ts +11 -0
- package/src/interact/interaction-trace.ts +36 -0
- package/src/interact/model.ts +109 -0
- package/src/interact/observation.ts +7 -0
- package/src/interact/targeting/candidate-ancestor.ts +49 -0
- package/src/interact/targeting/candidate-result.ts +24 -0
- package/src/interact/targeting/candidate-scoring.ts +42 -0
- package/src/interact/targeting/element-helpers.ts +243 -0
- package/src/interact/targeting/find-element.ts +47 -0
- package/src/interact/targeting/nearby-control.ts +46 -0
- package/src/interact/targeting/resolved-elements.ts +20 -0
- package/src/interact/targeting/tap-target.ts +22 -0
- package/src/interact/targeting/target-scope.ts +121 -0
- package/src/interact/waits/legacy-log-wait.ts +30 -0
- package/src/interact/waits/legacy-wait-observations.ts +55 -0
- package/src/interact/waits/legacy-wait-state.ts +48 -0
- package/src/interact/waits/legacy-wait.ts +34 -0
- package/src/interact/waits/screen-wait.ts +37 -0
- package/src/interact/waits/ui-change-helpers.ts +184 -0
- package/src/interact/waits/ui-change-state.ts +26 -0
- package/src/interact/waits/ui-change-wait.ts +59 -0
- package/src/interact/waits/ui-wait-condition.ts +52 -0
- package/src/interact/waits/ui-wait-state.ts +55 -0
- package/src/interact/waits/ui-wait.ts +84 -0
- package/src/manage/android.ts +56 -50
- package/src/manage/index.ts +63 -93
- package/src/manage/ios/build-types.ts +14 -0
- package/src/manage/ios/build.ts +230 -0
- package/src/manage/ios/project-discovery.ts +26 -0
- package/src/manage/ios/scheme.ts +16 -0
- package/src/manage/ios.ts +65 -298
- package/src/observe/android/context.ts +1 -0
- package/src/observe/android/current-screen.ts +63 -0
- package/src/observe/android/fingerprint.ts +13 -0
- package/src/observe/android/log-stream.ts +127 -0
- package/src/observe/android/logs.ts +110 -0
- package/src/observe/android/screenshot.ts +79 -0
- package/src/observe/android/ui-tree.ts +113 -0
- package/src/observe/android.ts +17 -531
- package/src/observe/evidence.ts +122 -70
- package/src/observe/index.ts +24 -286
- package/src/observe/ios/context.ts +22 -0
- package/src/observe/ios/fingerprint.ts +12 -0
- package/src/observe/ios/log-stream.ts +103 -0
- package/src/observe/ios/logs.ts +179 -0
- package/src/observe/ios/screenshot.ts +26 -0
- package/src/observe/ios/ui-elements.ts +266 -0
- package/src/observe/ios/ui-tree.ts +143 -0
- package/src/observe/ios.ts +18 -749
- package/src/observe/logs/model.ts +11 -0
- package/src/{network → observe/network}/index.ts +2 -2
- package/src/observe/readiness-service.ts +5 -3
- package/src/observe/readiness.ts +39 -18
- package/src/observe/screenshot-encoding.ts +32 -0
- package/src/observe/snapshot-collection.ts +69 -0
- package/src/observe/snapshot-logs.ts +26 -0
- package/src/observe/snapshot-metadata.ts +51 -31
- package/src/observe/snapshot-semantic.ts +153 -0
- package/src/observe/system-trace.ts +24 -15
- package/src/runtime/action-results.ts +376 -0
- package/src/runtime/clock.ts +9 -0
- package/src/server/common.ts +9 -359
- package/src/server/definitions/assert.ts +164 -0
- package/src/server/definitions/diagnostic.ts +120 -0
- package/src/server/definitions/input.ts +276 -0
- package/src/server/definitions/manage.ts +196 -0
- package/src/server/definitions/observe.ts +151 -0
- package/src/server/definitions/target.ts +140 -0
- package/src/server/definitions/wait.ts +107 -0
- package/src/server/handlers/action-execution.ts +164 -0
- package/src/server/handlers/correlation.ts +20 -0
- package/src/server/handlers/debugger-handlers.ts +39 -0
- package/src/server/handlers/debugger-response.ts +7 -0
- package/src/server/handlers/diagnostic.ts +79 -0
- package/src/server/handlers/handler-types.ts +7 -0
- package/src/server/handlers/input.ts +173 -0
- package/src/server/handlers/interact.ts +135 -0
- package/src/server/handlers/journey-assertions.ts +39 -0
- package/src/server/handlers/journey.ts +132 -0
- package/src/server/handlers/manage.ts +141 -0
- package/src/server/handlers/observe.ts +116 -0
- package/src/server/handlers/payload.ts +36 -0
- package/src/server/handlers/tool-handlers.ts +159 -0
- package/src/server/schemas/condition-schema.ts +2 -0
- package/src/server/{debugger-schema.ts → schemas/debugger-schema.ts} +13 -7
- package/src/server/{journey-schema.ts → schemas/journey-schema.ts} +7 -22
- package/src/server/{system-trace-schema.ts → schemas/system-trace-schema.ts} +3 -3
- package/src/server/tool-definitions.ts +67 -1143
- package/src/server-core.ts +2 -2
- package/src/server.ts +1 -1
- package/src/system/android-status.ts +124 -0
- package/src/system/android.ts +33 -21
- package/src/system/index.ts +21 -525
- package/src/system/ios-status.ts +147 -0
- package/src/system/ios.ts +14 -10
- package/src/system/model.ts +41 -0
- package/src/system/probes.ts +114 -0
- package/src/system/status-summary.ts +47 -0
- package/src/system/unsupported-status.ts +55 -0
- package/src/types.ts +16 -106
- package/src/utils/android/commands.ts +81 -0
- package/src/utils/android/gradle.ts +132 -0
- package/src/utils/android/logs.ts +103 -0
- package/src/utils/android/ui-tree.ts +239 -0
- package/src/utils/android/utils.ts +16 -556
- package/src/utils/cli/idb/check-idb.ts +4 -4
- package/src/utils/cli/idb/idb-helper.ts +6 -8
- package/src/utils/cli/idb/install-idb.ts +15 -9
- package/src/utils/cli/ios/preflight-ios.ts +39 -31
- package/src/utils/cli/ios/run-ios-ui-tree-tap.ts +4 -4
- package/src/utils/ios/utils.ts +57 -61
- package/src/utils/java.ts +62 -43
- package/src/utils/resolve-device.ts +9 -6
- package/src/utils/ui/index.ts +28 -28
- package/test/device/automated/debugger/coroutine-lifecycle.ts +27 -0
- package/test/device/automated/debugger/coroutine-support.ts +140 -0
- package/test/device/automated/debugger/coroutine.android.test.ts +169 -0
- package/test/device/automated/debugger/kotlin.android.test.ts +127 -0
- package/test/device/automated/debugger/runtime.android.test.ts +19 -3
- package/test/device/automated/interact/interaction.android.test.ts +56 -0
- package/test/device/automated/observe/system-trace.smoke.ts +1 -1
- package/test/device/manual/interact/modul8_selector_tap.manual.ts +1 -1
- package/test/fixtures/contracts/tool-definitions.json +3536 -0
- package/test/fixtures/coroutine-app/MainActivity.kt +100 -0
- package/test/fixtures/coroutine-app/README.md +48 -0
- package/test/fixtures/coroutine-app/build.ts +35 -0
- package/test/fixtures/debugger-app/MainActivity.java +21 -0
- package/test/fixtures/debugger-app/MainActivity.kt +32 -0
- package/test/fixtures/debugger-app/README.md +52 -0
- package/test/fixtures/debugger-app/build.ts +25 -15
- package/test/fixtures/latency-journey-app/README.md +2 -0
- package/test/fixtures/readiness-app/README.md +2 -0
- package/test/unit/debugger/coroutine-lifecycle.test.ts +43 -0
- package/test/unit/debugger/diagnostic-sessions.test.ts +67 -0
- package/test/unit/debugger/diagnostics.test.ts +80 -0
- package/test/unit/debugger/guards.test.ts +4 -0
- package/test/unit/debugger/preparation.test.ts +32 -0
- package/test/unit/debugger/protocol.test.ts +15 -0
- package/test/unit/debugger/sessions.test.ts +1 -1
- package/test/unit/interact/adjustment_service.test.ts +42 -0
- package/test/unit/interact/adjustment_verification.test.ts +35 -0
- package/test/unit/interact/clock_dependencies.test.ts +63 -0
- package/test/unit/interact/element_helpers.test.ts +19 -0
- package/test/unit/interact/legacy_wait_service.test.ts +17 -0
- package/test/unit/interact/state_comparison.test.ts +20 -0
- package/test/unit/interact/target_scope.test.ts +35 -0
- package/test/unit/network/get_network_activity.test.ts +1 -1
- package/test/unit/observe/screenshot-encoding.test.ts +30 -0
- package/test/unit/observe/snapshot-logs.test.ts +14 -0
- package/test/unit/quality/architecture.test.ts +60 -0
- package/test/unit/quality/code-quality.test.ts +58 -0
- package/test/unit/quality/interaction_boundaries.test.ts +24 -0
- package/test/unit/server/conditional_actions.test.ts +1 -1
- package/test/unit/server/conditional_schema.test.ts +2 -2
- package/test/unit/server/debugger-response.test.ts +63 -0
- package/test/unit/server/tool_definitions_parity.test.ts +8 -0
- package/dist/server/tool-handlers.js +0 -1000
- package/docs/ROADMAP.md +0 -646
- package/docs/benchmarks/ui-tree-performance/bridge-probe.json +0 -29
- package/docs/benchmarks/ui-tree-performance/initial-baseline.json +0 -59560
- package/docs/specs/baseline-spec-v0.md +0 -312
- package/docs/specs/mcp-tooling-spec-v1.md +0 -446
- package/src/server/debugger-handlers.ts +0 -29
- package/src/server/tool-handlers.ts +0 -1008
- /package/dist/{server/condition-schema.js → contracts/condition.js} +0 -0
- /package/dist/server/{readiness-schema.js → schemas/readiness-schema.js} +0 -0
- /package/dist/server/{system-trace-schema.js → schemas/system-trace-schema.js} +0 -0
- /package/src/{server/condition-schema.ts → contracts/condition.ts} +0 -0
- /package/src/server/{readiness-schema.ts → schemas/readiness-schema.ts} +0 -0
|
@@ -22,11 +22,10 @@ async function findFirst(root, patterns, maxDepth = 4) {
|
|
|
22
22
|
console.error('DEBUG findFirst: entries', ents.map(e => e.name));
|
|
23
23
|
for (const e of ents) {
|
|
24
24
|
const full = path.join(dir, e.name);
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
25
|
+
const matched = patterns.some(pattern => e.name.endsWith(pattern));
|
|
26
|
+
if (matched) {
|
|
27
|
+
console.error('DEBUG findFirst: matched', full);
|
|
28
|
+
return full;
|
|
30
29
|
}
|
|
31
30
|
if (e.isDirectory() && depth < maxDepth)
|
|
32
31
|
queue.push({ dir: full, depth: depth + 1 });
|
|
@@ -52,26 +51,7 @@ function startCompanionIfNeeded(companionPath, udid) {
|
|
|
52
51
|
}
|
|
53
52
|
}
|
|
54
53
|
async function main() {
|
|
55
|
-
const
|
|
56
|
-
let projectArg;
|
|
57
|
-
let udid;
|
|
58
|
-
let startCompanion = false;
|
|
59
|
-
let kmpBuild = null;
|
|
60
|
-
for (let i = 0; i < args.length; i++) {
|
|
61
|
-
const a = args[i];
|
|
62
|
-
if (a === '--project' && args[i + 1]) {
|
|
63
|
-
projectArg = args[i + 1];
|
|
64
|
-
i++;
|
|
65
|
-
}
|
|
66
|
-
else if (a === '--udid' && args[i + 1]) {
|
|
67
|
-
udid = args[i + 1];
|
|
68
|
-
i++;
|
|
69
|
-
}
|
|
70
|
-
else if (a === '--start-companion')
|
|
71
|
-
startCompanion = true;
|
|
72
|
-
else if (!projectArg)
|
|
73
|
-
projectArg = a;
|
|
74
|
-
}
|
|
54
|
+
const { projectArg, udid, startCompanion, kmpBuild } = argumentsForPreflight(process.argv.slice(2));
|
|
75
55
|
const cwd = process.cwd();
|
|
76
56
|
const projectRoot = projectArg ? path.resolve(projectArg) : cwd;
|
|
77
57
|
// If user passed a direct .xcodeproj or .xcworkspace path, accept it as the projectFile
|
|
@@ -108,15 +88,8 @@ async function main() {
|
|
|
108
88
|
// 4) idb_companion
|
|
109
89
|
const companionPath = commandWhich('idb_companion');
|
|
110
90
|
const companionAvailable = !!companionPath;
|
|
111
|
-
const suggestions =
|
|
112
|
-
|
|
113
|
-
suggestions.push('Provide correct project path or ensure .xcodeproj/.xcworkspace exists in project dir');
|
|
114
|
-
if (!kmpFramework)
|
|
115
|
-
suggestions.push('Run KMP Gradle task to produce Shared.framework before xcodebuild (e.g., :shared:embedAndSignAppleFrameworkForXcode)');
|
|
116
|
-
if (!idbAvailable)
|
|
117
|
-
suggestions.push('Ensure idb is in PATH or set MCP_IDB_PATH / IDB_PATH');
|
|
118
|
-
if (!companionAvailable)
|
|
119
|
-
suggestions.push('Install idb_companion and ensure it is in PATH');
|
|
91
|
+
const suggestions = preflightSuggestions(projectFile, kmpFramework, idbAvailable, companionAvailable);
|
|
92
|
+
const companionInfo = { cmd: companionPath, installed: companionAvailable };
|
|
120
93
|
const result = {
|
|
121
94
|
ok: !!projectFile && !!idbAvailable,
|
|
122
95
|
project: {
|
|
@@ -133,10 +106,7 @@ async function main() {
|
|
|
133
106
|
cmd: idbPath,
|
|
134
107
|
installed: idbAvailable
|
|
135
108
|
},
|
|
136
|
-
idb_companion:
|
|
137
|
-
cmd: companionPath,
|
|
138
|
-
installed: companionAvailable
|
|
139
|
-
},
|
|
109
|
+
idb_companion: companionInfo,
|
|
140
110
|
suggestions
|
|
141
111
|
};
|
|
142
112
|
if (startCompanion && udid) {
|
|
@@ -153,3 +123,37 @@ main().catch(e => {
|
|
|
153
123
|
console.log(JSON.stringify({ ok: false, error: e instanceof Error ? e.message : String(e) }, null, 2));
|
|
154
124
|
process.exit(2);
|
|
155
125
|
});
|
|
126
|
+
function argumentsForPreflight(args) {
|
|
127
|
+
let projectArg;
|
|
128
|
+
let udid;
|
|
129
|
+
let startCompanion = false;
|
|
130
|
+
const kmpBuild = null;
|
|
131
|
+
for (let i = 0; i < args.length; i++) {
|
|
132
|
+
const a = args[i];
|
|
133
|
+
if (a === '--project' && args[i + 1]) {
|
|
134
|
+
projectArg = args[i + 1];
|
|
135
|
+
i++;
|
|
136
|
+
}
|
|
137
|
+
else if (a === '--udid' && args[i + 1]) {
|
|
138
|
+
udid = args[i + 1];
|
|
139
|
+
i++;
|
|
140
|
+
}
|
|
141
|
+
else if (a === '--start-companion')
|
|
142
|
+
startCompanion = true;
|
|
143
|
+
else if (!projectArg)
|
|
144
|
+
projectArg = a;
|
|
145
|
+
}
|
|
146
|
+
return { projectArg, udid, startCompanion, kmpBuild };
|
|
147
|
+
}
|
|
148
|
+
function preflightSuggestions(projectFile, kmpFramework, idbAvailable, companionAvailable) {
|
|
149
|
+
const suggestions = [];
|
|
150
|
+
if (!projectFile)
|
|
151
|
+
suggestions.push('Provide correct project path or ensure .xcodeproj/.xcworkspace exists in project dir');
|
|
152
|
+
if (!kmpFramework)
|
|
153
|
+
suggestions.push('Run KMP Gradle task to produce Shared.framework before xcodebuild (e.g., :shared:embedAndSignAppleFrameworkForXcode)');
|
|
154
|
+
if (!idbAvailable)
|
|
155
|
+
suggestions.push('Ensure idb is in PATH or set MCP_IDB_PATH / IDB_PATH');
|
|
156
|
+
if (!companionAvailable)
|
|
157
|
+
suggestions.push('Install idb_companion and ensure it is in PATH');
|
|
158
|
+
return suggestions;
|
|
159
|
+
}
|
package/dist/utils/ios/utils.js
CHANGED
|
@@ -19,16 +19,14 @@ export function getConfiguredIdbPath() {
|
|
|
19
19
|
if (!p)
|
|
20
20
|
continue;
|
|
21
21
|
try {
|
|
22
|
-
if (fs.existsSync(p))
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
}
|
|
31
|
-
}
|
|
22
|
+
if (!fs.existsSync(p))
|
|
23
|
+
continue;
|
|
24
|
+
const raw = fs.readFileSync(p, 'utf8');
|
|
25
|
+
const json = JSON.parse(raw);
|
|
26
|
+
if (json?.idbPath)
|
|
27
|
+
return json.idbPath;
|
|
28
|
+
if (json?.IDB_PATH)
|
|
29
|
+
return json.IDB_PATH;
|
|
32
30
|
}
|
|
33
31
|
catch { }
|
|
34
32
|
}
|
|
@@ -214,18 +212,18 @@ export async function getIOSDeviceMetadata(deviceId = "booted") {
|
|
|
214
212
|
const devicesMap = data.devices || {};
|
|
215
213
|
for (const runtime in devicesMap) {
|
|
216
214
|
const devices = devicesMap[runtime];
|
|
217
|
-
if (Array.isArray(devices))
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
215
|
+
if (!Array.isArray(devices))
|
|
216
|
+
continue;
|
|
217
|
+
for (const device of devices) {
|
|
218
|
+
if (deviceId === "booted" || device.udid === deviceId) {
|
|
219
|
+
resolve({
|
|
220
|
+
platform: "ios",
|
|
221
|
+
id: device.udid,
|
|
222
|
+
osVersion: parseRuntimeName(runtime),
|
|
223
|
+
model: device.name,
|
|
224
|
+
simulator: true,
|
|
225
|
+
});
|
|
226
|
+
return;
|
|
229
227
|
}
|
|
230
228
|
}
|
|
231
229
|
}
|
|
@@ -257,36 +255,37 @@ export async function listIOSDevices(appId) {
|
|
|
257
255
|
const bmap = bdata.devices || {};
|
|
258
256
|
for (const rt in bmap) {
|
|
259
257
|
const devs = bmap[rt];
|
|
260
|
-
if (Array.isArray(devs))
|
|
261
|
-
|
|
262
|
-
|
|
258
|
+
if (!Array.isArray(devs))
|
|
259
|
+
continue;
|
|
260
|
+
for (const d of devs)
|
|
261
|
+
bootedSet.add(d.udid);
|
|
263
262
|
}
|
|
264
263
|
}
|
|
265
264
|
catch { }
|
|
266
265
|
}
|
|
267
266
|
for (const runtime in devicesMap) {
|
|
268
267
|
const devices = devicesMap[runtime];
|
|
269
|
-
if (Array.isArray(devices))
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
268
|
+
if (!Array.isArray(devices))
|
|
269
|
+
continue;
|
|
270
|
+
for (const device of devices) {
|
|
271
|
+
const info = {
|
|
272
|
+
platform: 'ios',
|
|
273
|
+
id: device.udid,
|
|
274
|
+
osVersion: parseRuntimeName(runtime),
|
|
275
|
+
model: device.name,
|
|
276
|
+
simulator: true,
|
|
277
|
+
booted: bootedSet.has(device.udid)
|
|
278
|
+
};
|
|
279
|
+
if (appId) {
|
|
280
|
+
// check if installed
|
|
281
|
+
const p = execCommand(['simctl', 'get_app_container', device.udid, appId, 'data'], device.udid)
|
|
282
|
+
.then(() => { info.appInstalled = true; })
|
|
283
|
+
.catch(() => { info.appInstalled = false; })
|
|
284
|
+
.then(() => { out.push(info); });
|
|
285
|
+
checks.push(p);
|
|
286
|
+
}
|
|
287
|
+
else {
|
|
288
|
+
out.push(info);
|
|
290
289
|
}
|
|
291
290
|
}
|
|
292
291
|
}
|
package/dist/utils/java.js
CHANGED
|
@@ -39,27 +39,9 @@ export async function detectJavaHome(options = {}) {
|
|
|
39
39
|
}
|
|
40
40
|
debug('[java.detect] ANDROID_STUDIO_JDK present but java -version did not match expected versions');
|
|
41
41
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
'/Applications/Android Studio.app/Contents/jbr/Contents/Home',
|
|
46
|
-
'/Applications/Android Studio Preview.app/Contents/jbr',
|
|
47
|
-
'/Applications/Android Studio Preview.app/Contents/jbr/Contents/Home',
|
|
48
|
-
'/Applications/Android Studio Preview 2022.3.app/Contents/jbr',
|
|
49
|
-
'/Applications/Android Studio Preview 2022.3.app/Contents/jbr/Contents/Home',
|
|
50
|
-
'/Applications/Android Studio Preview 2023.1.app/Contents/jbr',
|
|
51
|
-
'/Applications/Android Studio Preview 2023.1.app/Contents/jbr/Contents/Home'
|
|
52
|
-
];
|
|
53
|
-
for (const p of jbrCandidates) {
|
|
54
|
-
const javaBin = path.join(p, 'bin', 'java');
|
|
55
|
-
if (existsSync(javaBin)) {
|
|
56
|
-
const v = javaVersionOf(javaBin);
|
|
57
|
-
if (isJavaVersionAcceptable(v)) {
|
|
58
|
-
debug('[java.detect] Found Android Studio JBR at:', p);
|
|
59
|
-
return p;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
}
|
|
42
|
+
const jbr = findStudioJava(debug);
|
|
43
|
+
if (jbr)
|
|
44
|
+
return jbr;
|
|
63
45
|
// 3) If JAVA_HOME set, validate it (accept 17 or 21)
|
|
64
46
|
if (process.env.JAVA_HOME) {
|
|
65
47
|
try {
|
|
@@ -96,40 +78,74 @@ export async function detectJavaHome(options = {}) {
|
|
|
96
78
|
catch (e) {
|
|
97
79
|
debug('[java.detect] /usr/libexec/java_home -v 21 failed: ' + String(e));
|
|
98
80
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
81
|
+
const commonHome = findMacJavaHome(debug);
|
|
82
|
+
if (commonHome)
|
|
83
|
+
return commonHome;
|
|
84
|
+
return findLinuxJavaHome(debug);
|
|
85
|
+
}
|
|
86
|
+
catch (e) {
|
|
87
|
+
debug('[java.detect] error detecting java home:', e instanceof Error ? e.message : String(e));
|
|
88
|
+
}
|
|
89
|
+
return undefined;
|
|
90
|
+
}
|
|
91
|
+
function findStudioJava(debug) {
|
|
92
|
+
// 2) Android Studio JBR candidates (prefer these over JAVA_HOME)
|
|
93
|
+
const jbrCandidates = [
|
|
94
|
+
'/Applications/Android Studio.app/Contents/jbr',
|
|
95
|
+
'/Applications/Android Studio.app/Contents/jbr/Contents/Home',
|
|
96
|
+
'/Applications/Android Studio Preview.app/Contents/jbr',
|
|
97
|
+
'/Applications/Android Studio Preview.app/Contents/jbr/Contents/Home',
|
|
98
|
+
'/Applications/Android Studio Preview 2022.3.app/Contents/jbr',
|
|
99
|
+
'/Applications/Android Studio Preview 2022.3.app/Contents/jbr/Contents/Home',
|
|
100
|
+
'/Applications/Android Studio Preview 2023.1.app/Contents/jbr',
|
|
101
|
+
'/Applications/Android Studio Preview 2023.1.app/Contents/jbr/Contents/Home'
|
|
102
|
+
];
|
|
103
|
+
for (const p of jbrCandidates) {
|
|
104
|
+
const javaBin = path.join(p, 'bin', 'java');
|
|
105
|
+
if (existsSync(javaBin)) {
|
|
106
|
+
const v = javaVersionOf(javaBin);
|
|
107
|
+
if (isJavaVersionAcceptable(v)) {
|
|
108
|
+
debug('[java.detect] Found Android Studio JBR at:', p);
|
|
109
|
+
return p;
|
|
107
110
|
}
|
|
108
111
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
'
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
];
|
|
121
|
-
for (const p of linuxCandidates) {
|
|
122
|
-
try {
|
|
123
|
-
if (existsSync(p))
|
|
124
|
-
return p;
|
|
125
|
-
}
|
|
126
|
-
catch (e) {
|
|
127
|
-
debug(`[java.detect] checking linux candidate ${p} failed: ${String(e)}`);
|
|
112
|
+
}
|
|
113
|
+
return undefined;
|
|
114
|
+
}
|
|
115
|
+
function findMacJavaHome(debug) {
|
|
116
|
+
// 6) macOS common JDK locations
|
|
117
|
+
try {
|
|
118
|
+
const homes = execSync('ls -1 /Library/Java/JavaVirtualMachines || true', { stdio: ['ignore', 'pipe', 'inherit'] }).toString().split(/\r?\n/).filter(Boolean);
|
|
119
|
+
for (const h of homes) {
|
|
120
|
+
if (h.toLowerCase().includes('17') || h.toLowerCase().includes('jdk-17') || h.toLowerCase().includes('21') || h.toLowerCase().includes('jdk-21')) {
|
|
121
|
+
const candidate = `/Library/Java/JavaVirtualMachines/${h}/Contents/Home`;
|
|
122
|
+
return candidate;
|
|
128
123
|
}
|
|
129
124
|
}
|
|
130
125
|
}
|
|
131
126
|
catch (e) {
|
|
132
|
-
debug('[java.detect]
|
|
127
|
+
debug('[java.detect] listing /Library/Java/JavaVirtualMachines failed: ' + String(e));
|
|
128
|
+
}
|
|
129
|
+
return undefined;
|
|
130
|
+
}
|
|
131
|
+
function findLinuxJavaHome(debug) {
|
|
132
|
+
// 7) Linux locations
|
|
133
|
+
const linuxCandidates = [
|
|
134
|
+
'/usr/lib/jvm/java-17-openjdk-amd64',
|
|
135
|
+
'/usr/lib/jvm/java-17-openjdk',
|
|
136
|
+
'/usr/lib/jvm/zulu17',
|
|
137
|
+
'/usr/lib/jvm/temurin-17-jdk',
|
|
138
|
+
'/usr/lib/jvm/temurin-21-jdk',
|
|
139
|
+
'/usr/lib/jvm/java-21-openjdk-amd64'
|
|
140
|
+
];
|
|
141
|
+
for (const p of linuxCandidates) {
|
|
142
|
+
try {
|
|
143
|
+
if (existsSync(p))
|
|
144
|
+
return p;
|
|
145
|
+
}
|
|
146
|
+
catch (e) {
|
|
147
|
+
debug(`[java.detect] checking linux candidate ${p} failed: ${String(e)}`);
|
|
148
|
+
}
|
|
133
149
|
}
|
|
134
150
|
return undefined;
|
|
135
151
|
}
|
|
@@ -66,6 +66,9 @@ async function resolveDevice(opts) {
|
|
|
66
66
|
throw new Error(`Device '${deviceId}' not found for platform ${platform}`);
|
|
67
67
|
return found;
|
|
68
68
|
}
|
|
69
|
+
return selectDevice(devices, platform, appId, prefer);
|
|
70
|
+
}
|
|
71
|
+
function selectDevice(devices, platform, appId, prefer) {
|
|
69
72
|
let candidates = devices.slice();
|
|
70
73
|
if (prefer === "physical")
|
|
71
74
|
candidates = candidates.filter(d => !d.simulator);
|
|
@@ -99,8 +102,7 @@ async function resolveDevice(opts) {
|
|
|
99
102
|
return candidates[0];
|
|
100
103
|
}
|
|
101
104
|
const list = candidates.map(d => ({ id: d.id, platform: d.platform, osVersion: d.osVersion, model: d.model, simulator: d.simulator, appInstalled: d.appInstalled }));
|
|
102
|
-
const err = new Error(`Multiple matching devices found: ${JSON.stringify(list, null, 2)}`);
|
|
103
|
-
err.devices = list;
|
|
105
|
+
const err = Object.assign(new Error(`Multiple matching devices found: ${JSON.stringify(list, null, 2)}`), { devices: list });
|
|
104
106
|
throw err;
|
|
105
107
|
}
|
|
106
108
|
throw new Error(`No devices found for platform ${platform}`);
|
package/dist/utils/ui/index.js
CHANGED
|
@@ -73,36 +73,11 @@ export function computeScreenFingerprint(tree, current, platform, limit = 50) {
|
|
|
73
73
|
}
|
|
74
74
|
export async function scrollToElementShared(opts) {
|
|
75
75
|
const { selector, direction = 'down', maxScrolls = 10, scrollAmount = 0.7, deviceId, fetchTree, swipe, stabilizationDelayMs = 350 } = opts;
|
|
76
|
-
const matchElement = (el) => {
|
|
77
|
-
if (!el)
|
|
78
|
-
return false;
|
|
79
|
-
if (selector.text !== undefined && selector.text !== el.text)
|
|
80
|
-
return false;
|
|
81
|
-
if (selector.resourceId !== undefined && selector.resourceId !== el.resourceId)
|
|
82
|
-
return false;
|
|
83
|
-
if (selector.contentDesc !== undefined && selector.contentDesc !== el.contentDescription)
|
|
84
|
-
return false;
|
|
85
|
-
if (selector.className !== undefined && selector.className !== el.type)
|
|
86
|
-
return false;
|
|
87
|
-
return true;
|
|
88
|
-
};
|
|
89
|
-
const isVisible = (el, resolution) => {
|
|
90
|
-
if (!el)
|
|
91
|
-
return false;
|
|
92
|
-
if (el.visible === false)
|
|
93
|
-
return false;
|
|
94
|
-
if (!el.bounds || !resolution || !resolution.width || !resolution.height)
|
|
95
|
-
return (el.visible === undefined ? true : !!el.visible);
|
|
96
|
-
const [left, top, right, bottom] = el.bounds;
|
|
97
|
-
const withinY = bottom > 0 && top < resolution.height;
|
|
98
|
-
const withinX = right > 0 && left < resolution.width;
|
|
99
|
-
return withinX && withinY;
|
|
100
|
-
};
|
|
101
76
|
const findVisibleMatch = (elements, resolution) => {
|
|
102
77
|
if (!Array.isArray(elements))
|
|
103
78
|
return null;
|
|
104
79
|
for (const e of elements) {
|
|
105
|
-
if (matchElement(e) && isVisible(e, resolution))
|
|
80
|
+
if (matchElement(selector, e) && isVisible(e, resolution))
|
|
106
81
|
return e;
|
|
107
82
|
}
|
|
108
83
|
return null;
|
|
@@ -169,3 +144,28 @@ export async function scrollToElementShared(opts) {
|
|
|
169
144
|
}
|
|
170
145
|
return { success: false, reason: 'Element not found after scrolling', scrollsPerformed: scrollsPerformed };
|
|
171
146
|
}
|
|
147
|
+
function matchElement(selector, el) {
|
|
148
|
+
if (!el)
|
|
149
|
+
return false;
|
|
150
|
+
if (selector.text !== undefined && selector.text !== el.text)
|
|
151
|
+
return false;
|
|
152
|
+
if (selector.resourceId !== undefined && selector.resourceId !== el.resourceId)
|
|
153
|
+
return false;
|
|
154
|
+
if (selector.contentDesc !== undefined && selector.contentDesc !== el.contentDescription)
|
|
155
|
+
return false;
|
|
156
|
+
if (selector.className !== undefined && selector.className !== el.type)
|
|
157
|
+
return false;
|
|
158
|
+
return true;
|
|
159
|
+
}
|
|
160
|
+
function isVisible(el, resolution) {
|
|
161
|
+
if (!el)
|
|
162
|
+
return false;
|
|
163
|
+
if (el.visible === false)
|
|
164
|
+
return false;
|
|
165
|
+
if (!el.bounds || !resolution || !resolution.width || !resolution.height)
|
|
166
|
+
return (el.visible === undefined ? true : !!el.visible);
|
|
167
|
+
const [left, top, right, bottom] = el.bounds;
|
|
168
|
+
const withinY = bottom > 0 && top < resolution.height;
|
|
169
|
+
const withinX = right > 0 && left < resolution.width;
|
|
170
|
+
return withinX && withinY;
|
|
171
|
+
}
|
package/docs/CHANGELOG.md
CHANGED
|
@@ -1,9 +1,53 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
[Documentation](README.md)
|
|
4
|
+
|
|
5
|
+
Entries describe their release at the time it was recorded. Historical source
|
|
6
|
+
paths and commands may have moved; use the [contribution guide](../CONTRIBUTING.md)
|
|
7
|
+
and [tool reference](tools/TOOLS.md) for the current checkout.
|
|
8
|
+
|
|
3
9
|
All notable changes to the **Mobile Debug MCP** project will be documented in this file.
|
|
4
10
|
|
|
5
11
|
## Unreleased
|
|
6
12
|
|
|
13
|
+
## [0.35.0]
|
|
14
|
+
|
|
15
|
+
- Updated the agent plugin to `0.0.4`, pinned to MCP `0.35.0`.
|
|
16
|
+
|
|
17
|
+
- Added an opt-in isolated Android coroutine debugger assessment fixture for
|
|
18
|
+
suspension, dispatcher changes, nested work, stepping and cancellation, with
|
|
19
|
+
explicit local dependencies. This does not add coroutine reconstruction.
|
|
20
|
+
- Added an opt-in isolated Kotlin debugger validation journey for named locals
|
|
21
|
+
before/after assignment, compiler scope tables, stale references and app recovery.
|
|
22
|
+
This adds evidence and regression coverage without changing debugger behaviour.
|
|
23
|
+
- Added opt-in debugger `responseMode: "compact"` to omit repeated target metadata
|
|
24
|
+
from routine commands while retaining diagnostics, execution state and cleanup.
|
|
25
|
+
Existing full responses remain the default; discovery and state stay complete.
|
|
26
|
+
- Android debugger failures now include bounded, sanitized stage/reason diagnostics
|
|
27
|
+
and static recovery guidance while preserving error codes. Capability probes
|
|
28
|
+
report ordered prerequisite diagnostics; terminal summaries retain failure evidence.
|
|
29
|
+
Raw stderr, exception messages and app locals are excluded from diagnostics.
|
|
30
|
+
|
|
31
|
+
- **Runtime requirement:** Node.js 22 or newer is now required. Updated Sharp,
|
|
32
|
+
Zod and transitive dependencies to clear the dependency audit findings; CI
|
|
33
|
+
configuration now uses Node 22. Public tool definitions remain unchanged.
|
|
34
|
+
- Split observation, snapshot, iOS build, Android utility and system diagnostic
|
|
35
|
+
responsibilities into typed services. Removed all 136 legacy quality exceptions;
|
|
36
|
+
production source meets the default size, complexity, nesting and explicit-any
|
|
37
|
+
limits. Added screenshot encoding and snapshot log normalization regressions.
|
|
38
|
+
|
|
39
|
+
- Split server handlers by capability, share target/execution-control contracts, and inject clocks into interaction polling services while preserving tool contracts. Added deterministic timing tests and an Android labelled-slider convergence journey.
|
|
40
|
+
|
|
41
|
+
- Added ArchUnitTS architecture checks to lint and CI for shared contracts, server boundaries, pure interaction calculations and runtime dependency cycles. Negative controls cover NodeNext resolution, aliases, dynamic imports and re-exports.
|
|
42
|
+
|
|
43
|
+
- Group interaction services by adjustment, targeting, waits and assertions; separate server schemas and handlers, and place log-derived network observations under `observe/network`. Tool contracts and behaviour are unchanged.
|
|
44
|
+
|
|
45
|
+
- Reduced `ToolsInteract` to a typed composition facade within the enforced class budget. Extracted adjustment, candidate resolution, synchronization and assertion services without new legacy exceptions, and added an isolated Android interaction journey plus a permanent default-budget regression check.
|
|
46
|
+
|
|
47
|
+
- Added code-quality gates to lint and CI for source/class/function size, complexity, nesting, explicit `any`, and interaction/runtime import boundaries. Legacy exceptions have per-symbol ceilings that cannot grow unnoticed.
|
|
48
|
+
- Extracted typed UI/control helpers, bounded handle storage, action-result construction and capability-specific tool definitions; clarified and typed debugger session operations and worker protocol messages while retaining public tool contracts.
|
|
49
|
+
- Fixed the debugger device check to fingerprint Java sources in `src/debugger/java/` after the worker relocation.
|
|
50
|
+
|
|
7
51
|
## [0.34.0]
|
|
8
52
|
- Added optional Android JDI runtime debugging: explicit device/process attach, source breakpoints/events, bounded stacks and shallow locals, stepping/resume, stale-reference rejection, pause-aware UI guards/readiness, expiry and owned detach/cleanup. Requires a host JDK 17+ and a running debuggable app; evaluation, mutation, native/coroutine and iOS debugging remain unsupported.
|
|
9
53
|
- Added optional bounded Android Perfetto capture with capability/start/status/stop/cancel tools, explicit journey trace linkage, local artifacts, process-ownership checks and retryable cleanup. iOS tracing and automatic trace analysis remain unsupported.
|
package/docs/README.md
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Documentation
|
|
2
|
+
|
|
3
|
+
Mobile Debug MCP provides tools for building, controlling, and inspecting Android
|
|
4
|
+
and iOS apps. Start with the [project README](../README.md) for requirements,
|
|
5
|
+
installation, and client configuration.
|
|
6
|
+
|
|
7
|
+
## Choose a starting point
|
|
8
|
+
|
|
9
|
+
- **New to the server?** See the [project overview and installation options](../README.md#start-here).
|
|
10
|
+
- **Looking up a tool?** Use the [tool reference](tools/TOOLS.md) for inputs,
|
|
11
|
+
responses, examples, and shared interaction principles.
|
|
12
|
+
- **Troubleshooting setup?** Check [environment diagnostics](tools/system.md) and
|
|
13
|
+
the [tool path settings](../README.md#environment-setup).
|
|
14
|
+
- **Investigating an app failure?** Start with [observations](tools/observe.md)
|
|
15
|
+
and [evidence correlation](tools/correlated-evidence.md). For deeper Android
|
|
16
|
+
investigation, use [system traces](tools/system-traces.md) or the
|
|
17
|
+
[runtime debugger](tools/debugger.md).
|
|
18
|
+
- **Installing a client plugin?** See [client installation](../README.md#agent-plugin)
|
|
19
|
+
and the [plugin guide](../agent-plugin/README.md) for packaging and versioning.
|
|
20
|
+
|
|
21
|
+
## Contributing
|
|
22
|
+
|
|
23
|
+
- [Contribution guide](../CONTRIBUTING.md): local setup, validation, and documentation conventions.
|
|
24
|
+
- [Code structure and quality checks](code-structure.md): module ownership, enforced limits, and existing debt.
|
|
25
|
+
- [Development process](specs/process.md): maintenance and feature workflows.
|
|
26
|
+
- [Agent entrypoint](../AGENTS.md) and [repository skills](../.agents/skills/README.md).
|
|
27
|
+
|
|
28
|
+
## Design and evidence
|
|
29
|
+
|
|
30
|
+
- [Design records](specs/): feature intent, specifications, and dated verification
|
|
31
|
+
records, grouped by feature.
|
|
32
|
+
- [Changelog](CHANGELOG.md): release history.
|
|
33
|
+
- [Benchmark index](benchmarks/README.md): reproducible performance checks and recorded limits.
|
|
34
|
+
|
|
35
|
+
The tool reference describes the current checkout. Specifications record design
|
|
36
|
+
intent and may contain earlier contracts; approval alone does not establish that
|
|
37
|
+
a feature shipped. Verification records describe the named build and environment,
|
|
38
|
+
not every supported platform or the currently published npm package.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Benchmarks
|
|
2
|
+
|
|
3
|
+
[Documentation](../README.md)
|
|
4
|
+
|
|
5
|
+
Use these guides to run a benchmark or inspect its recorded results. Each
|
|
6
|
+
benchmark has one directory containing its instructions, report, and supporting
|
|
7
|
+
data. Generated filenames are retained so the harness can update them directly.
|
|
8
|
+
|
|
9
|
+
These reports describe particular builds and devices. Passing a smoke check does
|
|
10
|
+
not establish a performance improvement, and Android timings do not establish
|
|
11
|
+
iOS latency.
|
|
12
|
+
|
|
13
|
+
| Benchmark | Protocol | Recorded results | Design |
|
|
14
|
+
| --- | --- | --- | --- |
|
|
15
|
+
| Interaction latency | [Run the benchmark](interaction-latency/README.md) | [Android measurements](interaction-latency/final.md), [iOS interaction validation](interaction-latency/ios-validation.md) | [018](../specs/018-interaction-latency-and-batched-journeys/spec.md) |
|
|
16
|
+
| UI-tree observation | [Run the paired benchmark](ui-tree-performance/README.md) | [Comparison and limitations](ui-tree-performance/comparison.md) | [019](../specs/019-ui-tree-observation-performance/spec.md) |
|
|
17
|
+
|
|
18
|
+
Fixture instructions: [latency journey app](../../test/fixtures/latency-journey-app/README.md).
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Interaction latency benchmark
|
|
2
2
|
|
|
3
|
+
[Benchmark index](../README.md) · [Documentation](../../README.md)
|
|
4
|
+
|
|
3
5
|
Run after `npm run verify`:
|
|
4
6
|
|
|
5
7
|
```sh
|
|
@@ -24,3 +26,15 @@ See [iOS simulator validation](ios-validation.md) for the interaction checks.
|
|
|
24
26
|
The process exits unsuccessfully on >10% full p95 regression or <30% light p50
|
|
25
27
|
improvement. A failed run is reported and excluded from percentiles as the spec
|
|
26
28
|
requires; inspect its selector and tool or step before accepting the result.
|
|
29
|
+
|
|
30
|
+
## Recorded results
|
|
31
|
+
|
|
32
|
+
- [Android measurements](final.md): latency summaries and acceptance gates.
|
|
33
|
+
- [Raw Android report](final.json): requests, timing components, and per-run outcomes.
|
|
34
|
+
- [iOS interaction validation](ios-validation.md): correctness checks, separate
|
|
35
|
+
from the Android latency measurements.
|
|
36
|
+
|
|
37
|
+
The harness overwrites `final.md` and `final.json` when run. These checked-in
|
|
38
|
+
results describe the recorded build and environment; they do not establish the
|
|
39
|
+
performance of the current checkout. Review generated reports and preserve any
|
|
40
|
+
unresolved limitations when recording a new run.
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Interaction latency benchmark
|
|
2
2
|
|
|
3
|
+
[Benchmark index](../README.md) · [Documentation](../../README.md)
|
|
4
|
+
|
|
3
5
|
Commit: d3e6ae720db1ad1da294795790689df5a80b56b0 (working tree candidate). Fixture: 1.0, SHA-256 98244deeeba0a21da7d99a3e4b43c97806d6f8a8787ad7fe38249e5d311a6fb6.
|
|
4
6
|
|
|
5
7
|
Environment: Pixel_9_Pro, Android 16, API 36. Three warm-ups and ten measured runs per mode. Failed runs excluded.
|
|
@@ -14,4 +16,5 @@ First failure by mode: baseline: none; full: none; light: none.
|
|
|
14
16
|
|
|
15
17
|
Full p95 gate: true. Light p50 gate: true.
|
|
16
18
|
|
|
17
|
-
See final.json for requests, timing components, and failure selectors.
|
|
19
|
+
See the [raw report](final.json) for requests, timing components, and failure selectors.
|
|
20
|
+
See the [benchmark instructions](README.md) to run a new measurement.
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Spec 018 iOS device validation
|
|
2
2
|
|
|
3
|
+
[Benchmark index](../README.md) · [Documentation](../../README.md)
|
|
4
|
+
|
|
3
5
|
Validated on 27 September 2026 with the booted iPhone Air simulator (iOS 26.4.1).
|
|
4
6
|
|
|
5
7
|
- `npm run test:device` passed all six Android and iOS screenshot, log, and UI-tree smoke checks.
|