mobile-debug-mcp 0.32.2 → 0.33.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. package/.agents/plugins/marketplace.json +20 -0
  2. package/{skills → .agents/skills}/mcp-builder/SKILL.md +1 -2
  3. package/{skills → .agents/skills}/spec-review/SKILL.md +1 -1
  4. package/{skills → .agents/skills}/test-authoring/SKILL.md +1 -1
  5. package/.claude-plugin/marketplace.json +14 -0
  6. package/.cursor-plugin/marketplace.json +16 -0
  7. package/.github/copilot-instructions.md +7 -0
  8. package/AGENTS.md +21 -10
  9. package/README.md +67 -5
  10. package/agent-plugin/.claude-plugin/plugin.json +20 -0
  11. package/agent-plugin/.codex-plugin/plugin.json +34 -0
  12. package/agent-plugin/.cursor-plugin/plugin.json +23 -0
  13. package/agent-plugin/.mcp.json +14 -0
  14. package/agent-plugin/LICENSE +201 -0
  15. package/agent-plugin/README.md +29 -0
  16. package/agent-plugin/assets/mobile-debug-tools.svg +28 -0
  17. package/agent-plugin/mcp.json +11 -0
  18. package/agent-plugin/plugin.json +29 -0
  19. package/agent-plugin/skills/mobile-debug-mcp/SKILL.md +124 -0
  20. package/dist/interact/android.js +10 -4
  21. package/dist/interact/conditional-action.js +68 -0
  22. package/dist/interact/index.js +54 -14
  23. package/dist/interact/ios.js +14 -8
  24. package/dist/manage/android.js +4 -3
  25. package/dist/manage/ios.js +3 -2
  26. package/dist/observe/android.js +27 -22
  27. package/dist/observe/evidence.js +273 -0
  28. package/dist/observe/index.js +33 -6
  29. package/dist/observe/ios.js +25 -6
  30. package/dist/observe/readiness-service.js +115 -0
  31. package/dist/observe/readiness.js +81 -0
  32. package/dist/observe/recording.js +165 -0
  33. package/dist/observe/snapshot-metadata.js +10 -2
  34. package/dist/server/common.js +9 -0
  35. package/dist/server/condition-schema.js +32 -0
  36. package/dist/server/journey-schema.js +3 -2
  37. package/dist/server/readiness-schema.js +12 -0
  38. package/dist/server/tool-definitions.js +46 -0
  39. package/dist/server/tool-handlers.js +99 -17
  40. package/dist/server-core.js +1 -1
  41. package/dist/utils/ios/utils.js +4 -4
  42. package/dist/utils/operation-budget.js +24 -2
  43. package/dist/utils/resolve-device.js +7 -0
  44. package/docs/CHANGELOG.md +16 -2
  45. package/docs/benchmarks/ui-tree-performance/README.md +4 -3
  46. package/docs/specs/020-conditional-actions/intent.md +62 -0
  47. package/docs/specs/020-conditional-actions/plan.md +214 -0
  48. package/docs/specs/020-conditional-actions/spec.md +301 -0
  49. package/docs/specs/021-app-readiness-signals/intent.md +40 -0
  50. package/docs/specs/021-app-readiness-signals/plan.md +102 -0
  51. package/docs/specs/021-app-readiness-signals/spec.md +144 -0
  52. package/docs/specs/022-correlated-evidence/device-evidence.json +60 -0
  53. package/docs/specs/022-correlated-evidence/intent.md +37 -0
  54. package/docs/specs/022-correlated-evidence/modul8-evidence.json +1062 -0
  55. package/docs/specs/022-correlated-evidence/modul8-selector-fix-evidence.json +336 -0
  56. package/docs/specs/022-correlated-evidence/plan.md +171 -0
  57. package/docs/specs/022-correlated-evidence/spec.md +123 -0
  58. package/docs/specs/process.md +213 -0
  59. package/docs/tools/TOOLS.md +3 -0
  60. package/docs/tools/evidence.md +79 -0
  61. package/docs/tools/interact.md +125 -2
  62. package/docs/tools/observe.md +64 -2
  63. package/package.json +4 -2
  64. package/scripts/agent-plugin.mjs +98 -0
  65. package/src/interact/android.ts +10 -4
  66. package/src/interact/conditional-action.ts +75 -0
  67. package/src/interact/index.ts +42 -14
  68. package/src/interact/ios.ts +14 -8
  69. package/src/manage/android.ts +4 -3
  70. package/src/manage/ios.ts +3 -2
  71. package/src/observe/android.ts +35 -21
  72. package/src/observe/evidence.ts +255 -0
  73. package/src/observe/index.ts +32 -8
  74. package/src/observe/ios.ts +32 -8
  75. package/src/observe/readiness-service.ts +89 -0
  76. package/src/observe/readiness.ts +78 -0
  77. package/src/observe/snapshot-metadata.ts +12 -1
  78. package/src/server/common.ts +7 -0
  79. package/src/server/condition-schema.ts +32 -0
  80. package/src/server/journey-schema.ts +3 -2
  81. package/src/server/readiness-schema.ts +12 -0
  82. package/src/server/tool-definitions.ts +44 -0
  83. package/src/server/tool-handlers.ts +93 -17
  84. package/src/server-core.ts +1 -1
  85. package/src/types.ts +30 -1
  86. package/src/utils/ios/utils.ts +4 -4
  87. package/src/utils/operation-budget.ts +22 -2
  88. package/src/utils/resolve-device.ts +8 -0
  89. package/test/device/automated/observe/correlated-evidence.smoke.ts +70 -0
  90. package/test/device/manual/interact/conditional_actions.manual.ts +95 -0
  91. package/test/device/manual/interact/modul8_selector_tap.manual.ts +63 -0
  92. package/test/device/manual/interact/readiness.manual.ts +99 -0
  93. package/test/fixtures/readiness-app/MainActivity.java +23 -0
  94. package/test/fixtures/readiness-app/README.md +12 -0
  95. package/test/fixtures/readiness-app/build.ts +37 -0
  96. package/test/fixtures/readiness-app/main.m +27 -0
  97. package/test/unit/observe/android_tree_acquisition.test.ts +6 -0
  98. package/test/unit/observe/capture_debug_snapshot.test.ts +42 -32
  99. package/test/unit/observe/compact_tree_error.test.ts +24 -0
  100. package/test/unit/observe/conditional_snapshots.test.ts +33 -0
  101. package/test/unit/observe/correlated-evidence.test.ts +128 -0
  102. package/test/unit/observe/ios-getlogs.test.ts +3 -3
  103. package/test/unit/observe/ios_tree_acquisition.test.ts +2 -0
  104. package/test/unit/observe/readiness.test.ts +39 -0
  105. package/test/unit/observe/readiness_native.test.ts +68 -0
  106. package/test/unit/server/conditional_actions.test.ts +299 -0
  107. package/test/unit/server/conditional_schema.test.ts +59 -0
  108. package/test/unit/server/correlated-evidence.test.ts +194 -0
  109. package/test/unit/server/readiness.test.ts +170 -0
  110. package/test/unit/server/selector_tap_target.test.ts +79 -0
  111. package/test/unit/server/tap_selector.test.ts +2 -0
  112. package/skills/mobile-debug-tools-usage/SKILL.md +0 -74
  113. package/src/observe/android-tree-bridge.ts +0 -178
  114. package/test/device/automated/ui-tree-performance/bridge-probe.ts +0 -197
  115. package/test/fixtures/ui-tree-bridge/AndroidManifest.xml +0 -6
  116. package/test/fixtures/ui-tree-bridge/build.ts +0 -34
  117. package/test/fixtures/ui-tree-bridge/src/TreeInstrumentation.java +0 -126
  118. package/test/unit/observe/android_tree_bridge_cleanup.test.ts +0 -95
  119. /package/{skills → .agents/skills}/README.md +0 -0
  120. /package/{skills → .agents/skills}/mcp-builder/references/build-flags.md +0 -0
  121. /package/{skills → .agents/skills}/mcp-builder/references/diagnostics-schema.md +0 -0
  122. /package/{skills → .agents/skills}/mcp-builder/references/toolchain-details.md +0 -0
  123. /package/{skills → .agents/skills}/spec-review/references/spec-review-checklist.md +0 -0
  124. /package/{skills → .agents/skills}/spec-review/references/spec-review-template.md +0 -0
  125. /package/{skills → .agents/skills}/test-authoring/references/repo-test-layout.md +0 -0
  126. /package/{skills → .agents/skills}/test-authoring/references/test-authoring-workflow.md +0 -0
  127. /package/{skills → .agents/skills}/test-authoring/references/test-quality-checklist.md +0 -0
@@ -0,0 +1,144 @@
1
+ # Spec 021: app readiness signals
2
+
3
+ Date: 2026-10-29. Status: approved — implementation authorised.
4
+ Source: [issue #65](https://github.com/clivejefferies/mobile-debug-tools/issues/65).
5
+ [Intent](intent.md) approved by the originator’s “yes” in this conversation.
6
+
7
+ ## Behaviour and scope
8
+
9
+ Report readiness of the observed foreground device UI on Android/iOS. This is
10
+ not proof of a particular app’s identity, backend completion, or safe input.
11
+ Reuse snapshot signatures, loading observations, device resolution, and budgets.
12
+ Do not infer readiness from screenshots or input-dispatch success.
13
+
14
+ Initial supported states are `loading`, `transitioning`, `settled`, and `unknown`.
15
+ Reserve `unresponsive` and `debugger_paused`, but report their capabilities as
16
+ unsupported on both platforms: there is currently no authoritative process-health
17
+ or debugger-session provider. A timeout must never manufacture either state.
18
+ Adding those providers requires a subsequent spec decision; this feature does
19
+ not implement a debugger, recovery, restart, or performance profiling.
20
+
21
+ ## Public contracts
22
+
23
+ Add tools `get_app_readiness` and `wait_for_app_ready`, requiring `platform`
24
+ (`android`/`ios`) and optionally accepting `deviceId`. Resolve and pin one concrete
25
+ device per call. Both accept strict integer controls:
26
+
27
+ | Control | Default | Range |
28
+ | --- | --- | --- |
29
+ | `timeoutMs` | get: 15000; wait: 30000 | 100–60000 |
30
+ | `stabilityMs` | 500 | 100–10000 |
31
+ | `pollIntervalMs` (wait only) | 500 | 100–1000 |
32
+
33
+ Reject invalid/unknown arguments as `INVALID_ARGUMENT` before device work.
34
+ `get_app_readiness` takes at most two fresh samples, separating their acquisitions
35
+ by at least `stabilityMs`. A loading first sample can return immediately. The
36
+ wait tool samples until settled or its deadline. Reads are sequential; never
37
+ start a background poller or overlap hierarchy dumps within a call.
38
+
39
+ Both return `{ success, device, readiness, elapsed_ms, failure_code? }`.
40
+ For get, success means a supported state was established; `unknown` is unsuccessful.
41
+ For wait, only `settled` is successful. Unsuccessful codes are
42
+ `READINESS_UNAVAILABLE` (get), `READINESS_TIMEOUT` (wait deadline), and
43
+ `DEVICE_UNAVAILABLE` (resolution/disconnection prevents continuation).
44
+
45
+ `readiness` contains:
46
+
47
+ - `state`, `scope: device_ui`, and `basis` (`observed`, `heuristic`, or `insufficient`).
48
+ - `captured_at_ms` (latest successful sample, or null), `sample_count`,
49
+ `stable_for_ms`, and nullable `snapshot_session_id`/`snapshot_revision`.
50
+ - `evidence`: bounded records of signal code, source, capture time, and snapshot
51
+ revision; maximum eight, newest retained. No full text, logs, screenshots, or trees.
52
+ - `limitations`: applicable codes from `INSUFFICIENT_SAMPLES`, `OBSERVATION_FAILED`,
53
+ `OBSERVATION_INVALID`, `DEADLINE_EXCEEDED`, `NORMALIZED_UI_ONLY`,
54
+ `FOREGROUND_APP_UNVERIFIED`, `UNRESPONSIVE_SIGNAL_UNSUPPORTED`, and
55
+ `DEBUGGER_SIGNAL_UNSUPPORTED`.
56
+ - `capabilities`: true for loading/transition/stability observation; false for
57
+ unresponsive/debugger-paused detection in this version.
58
+
59
+ Add the same `readiness` summary to debug/compact `get_ui_tree` and nested tree
60
+ observations without additional reads. Single-sample summaries can only report
61
+ loading or unknown; separate calls never silently share a stability window.
62
+ Preserve existing fields, compact error evidence, and delta behaviour.
63
+
64
+ Add opt-in `requireReady: boolean` (default false) to `wait_for_ui` and
65
+ `wait_for_ui_change`. When enabled, success requires the existing predicate and
66
+ settled readiness on the same current samples. Reuse those waits’ samples and
67
+ single existing deadline; do not add another wait budget or unrelated tree reads.
68
+ Return `readiness` alongside the existing envelope. On expiry retain the existing
69
+ timeout/failure shape and include readiness limitations. Default calls retain
70
+ existing predicate semantics; no new journey assertion type is introduced.
71
+
72
+ ## Classification rules
73
+
74
+ | Evidence | State / basis |
75
+ | --- | --- |
76
+ | Visible native `android.widget.ProgressBar`, `ActivityIndicator`, or `ProgressIndicator` | loading / observed |
77
+ | Visible label exactly “Loading” or “Please wait”, ignoring case, whitespace, and trailing full stops/ellipsis | loading / heuristic |
78
+ | Two valid consecutive signatures differ | transitioning / observed |
79
+ | At least two valid identical signatures spanning `stabilityMs`, without loading evidence | settled / observed |
80
+ | Missing, failed, invalid, or insufficient evidence | unknown / insufficient |
81
+
82
+ Loading takes precedence over stability. Do not reuse the broad existing
83
+ `loading_state` keyword heuristic as proof: a button named “Progress” is not an
84
+ active loader. Keep that legacy field unchanged for compatibility.
85
+
86
+ Use full normalized snapshot signatures, including state and bounds, not the
87
+ coarser screen fingerprint or truncated delta. A change resets stability;
88
+ failed reads break consecutive-sample continuity. Validate device/session,
89
+ revision, a finite capture timestamp from this acquisition, nonempty elements,
90
+ and positive finite resolution. Never accept retained metadata as a fresh read.
91
+ Track elapsed/stability intervals with a monotonic clock; expose wall-clock
92
+ capture timestamps only as evidence. Results describe their capture window,
93
+ not a guarantee that the UI stays settled afterward.
94
+
95
+ ## Failure, lifecycle, and privacy
96
+
97
+ Bound acquisition, retries, and delays by the remaining operation budget and any
98
+ outer deadline. No late sample may produce success. Terminate/await owned timed-out
99
+ subprocesses; perform no follow-up snapshot after expiry. Waits can retry transient
100
+ observation failures within budget, with continuity reset; disconnect is terminal.
101
+ Retain the last supported state on wait timeout only as timestamped evidence,
102
+ with `DEADLINE_EXCEEDED`; if the latest read failed, current state is unknown.
103
+ There is no cancellation argument. Existing transport cancellation does not
104
+ currently abort platform reads; those reads remain bounded by their deadlines.
105
+ Do not claim immediate cancellation support or create persistent sessions.
106
+ Do not reset network windows, dispatch input, or retain cross-request histories.
107
+ Do not log UI payloads or input text. No permissions, dependencies, migrations,
108
+ or automatic package release are required.
109
+
110
+ ## Acceptance and verification
111
+
112
+ - Loading outranks identical trees; changing trees transition; consecutive stable
113
+ valid trees settle. Text-only loading is explicitly heuristic.
114
+ - A frozen-looking screenshot, stable tree, slow dump, timeout, or missing loader
115
+ cannot establish responsiveness, debugger pause, or app/backend completion.
116
+ - Error/empty/stale-session/wrong-device samples never settle; failures reset
117
+ continuity. Deadlines prevent late success and background work.
118
+ - New summaries preserve compact/debug evidence and existing defaults; opt-in
119
+ waits require both their predicate and readiness.
120
+ - Every state has evidence and limitations; unsupported capabilities are explicit.
121
+
122
+ Use deterministic native-adapter/clock fixtures for transitions, failures,
123
+ timeouts, isolation, and schema parity. Run `npm run verify`, `npm run test:device`,
124
+ and updated-server Android/iOS journeys for stable content, a controlled loader
125
+ transition, bounded waiting, and opt-in predicate waits. Record simulator/build,
126
+ results, and unsupported coverage in the plan after approval.
127
+
128
+ ## Investigation and approval
129
+
130
+ Existing owners: `src/observe/snapshot-metadata.ts`, `src/observe/index.ts`,
131
+ `src/interact/index.ts`, server schemas/handlers, shared types and operation budgets.
132
+ The legacy idle wait can compare null fingerprints; the new classifier must not
133
+ copy that inference. No debugger/readiness module currently exists.
134
+
135
+ Read-only reconnaissance used the connected server (exact build not reported;
136
+ local checkout 0.32.4). Android 16 `emulator-5554`: two fresh 15-element trees,
137
+ same revision 9, no loading hint, reads about 4.4/3.0 seconds. iOS 26.4 iPhone 17
138
+ Pro `F9243BAF-62A8-4990-8A99-17F527F56FDA`: two fresh 14-element trees, revision
139
+ 10, no loading hint, reads about 3.4/2.0 seconds. These establish available
140
+ observation routes, not feature passes; no inputs or settings were changed.
141
+
142
+ Approved by the originator’s “yep” on 2026-10-29 in direct response to this
143
+ spec and first-version scope, including unsupported unresponsive/debugger-paused
144
+ detection and opt-in existing-wait integration.
@@ -0,0 +1,60 @@
1
+ {
2
+ "verified_on": "2026-10-30",
3
+ "source_base": "3701f3987940a8abc76ed893b575ed370e3fb673",
4
+ "source_state": "working tree with correlated evidence changes",
5
+ "node_version": "23.11.0",
6
+ "build_sha256": {
7
+ "dist/server/tool-handlers.js": "4ae4aef2467518216e3b987112aadb91e5ff560679782fe08aefdb389209cc50",
8
+ "dist/observe/evidence.js": "bd7c6ac046ad4adde08117dcb66f68682e0036a83308c0c84f6d5ce141f8a386"
9
+ },
10
+ "journeys": [
11
+ {
12
+ "status": "PASS",
13
+ "server": {
14
+ "name": "mobile-debug-mcp",
15
+ "version": "0.32.4"
16
+ },
17
+ "platform": "android",
18
+ "device": "emulator-5554",
19
+ "osVersion": "16",
20
+ "startingApp": "com.android.settings",
21
+ "actionId": "5fdfe5a0-cfd3-4182-a12b-c440d855cec5",
22
+ "phases": {
23
+ "dispatchStarted": 1793350325789,
24
+ "dispatchCompleted": 1793350326584,
25
+ "screenshotStarted": 1793350327002,
26
+ "screenshotCompleted": 1793350327334
27
+ },
28
+ "screenshot": "captured",
29
+ "logs": "captured",
30
+ "uiTree": "captured",
31
+ "disabledComponents": "omitted",
32
+ "foreignReference": "unavailable",
33
+ "cleanup": "No settings, app data or streams changed; Settings remains foreground. No content artifacts saved."
34
+ },
35
+ {
36
+ "status": "PASS",
37
+ "server": {
38
+ "name": "mobile-debug-mcp",
39
+ "version": "0.32.4"
40
+ },
41
+ "platform": "ios",
42
+ "device": "F9243BAF-62A8-4990-8A99-17F527F56FDA",
43
+ "osVersion": "iOS 26.4",
44
+ "startingApp": "com.apple.Preferences",
45
+ "actionId": "99a4cdc4-8be1-4194-acab-3d08e7bd4a41",
46
+ "phases": {
47
+ "dispatchStarted": 1793350335131,
48
+ "dispatchCompleted": 1793350335486,
49
+ "screenshotStarted": 1793350335806,
50
+ "screenshotCompleted": 1793350336212
51
+ },
52
+ "screenshot": "captured",
53
+ "logs": "captured",
54
+ "uiTree": "captured",
55
+ "disabledComponents": "omitted",
56
+ "foreignReference": "unavailable",
57
+ "cleanup": "No settings, app data or streams changed; Settings remains foreground. No content artifacts saved."
58
+ }
59
+ ]
60
+ }
@@ -0,0 +1,37 @@
1
+ # Intent: correlated evidence
2
+
3
+ Originator: repository maintainer (current conversation).
4
+ Date: 2026-10-29. Status: approved.
5
+ Source: [issue #66](https://github.com/clivejefferies/mobile-debug-tools/issues/66), roadmap priority 3 of 9.
6
+
7
+ ## Problem and outcome
8
+
9
+ MCP clients need to connect Android/iOS actions with screenshots and logs without
10
+ mistaking older observations for evidence of later actions. Existing action IDs,
11
+ snapshot metadata, and elapsed timings do not provide a consistent correlation
12
+ contract.
13
+
14
+ Clients should identify related evidence, distinguish observation capture, input
15
+ dispatch, and verification completion, and recognise stale observations.
16
+ Association must not imply causality or simultaneous capture.
17
+
18
+ ## Scope and success criteria
19
+
20
+ - Extend existing conventions with shared identifiers and explicit phase timing.
21
+ - Identify stale evidence; preserve uncertainty when freshness is unknown.
22
+ - Preserve device targeting and report platform limitations.
23
+ - Allow future system traces to use the same correlation conventions.
24
+ - Preserve behaviour except for changes accepted in the specification.
25
+
26
+ ## Exclusions and decisions
27
+
28
+ Exclude trace capture, runtime debugger, heap dumps, automatic recovery, and
29
+ background recording. Specification must resolve identifier lifetime, association,
30
+ clock semantics, freshness, log windows, compatibility, and resource/privacy
31
+ handling, building on existing helpers.
32
+
33
+ ## Approval
34
+
35
+ The maintainer’s “yes” on 2026-10-29 approved the complete linked intent in this
36
+ conversation. This shorter version preserves that scope; specification approval
37
+ remains pending.