mobile-debug-mcp 0.35.0 → 0.37.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 (247) hide show
  1. package/.cursor-plugin/marketplace.json +1 -1
  2. package/.github/workflows/ci.yml +1 -1
  3. package/README.md +96 -24
  4. package/agent-plugin/.antigravity-plugin/README.md +48 -0
  5. package/agent-plugin/.antigravity-plugin/plugin.json +18 -0
  6. package/agent-plugin/.claude-plugin/plugin.json +2 -2
  7. package/agent-plugin/.codex-plugin/plugin.json +1 -1
  8. package/agent-plugin/.cursor-plugin/plugin.json +2 -2
  9. package/agent-plugin/.mcp.json +1 -1
  10. package/agent-plugin/README.md +37 -8
  11. package/agent-plugin/cursor/.cursor-plugin/plugin.json +23 -0
  12. package/agent-plugin/cursor/LICENSE +201 -0
  13. package/agent-plugin/cursor/README.md +9 -0
  14. package/agent-plugin/cursor/skills/mobile-debug-mcp/SKILL.md +261 -0
  15. package/agent-plugin/mcp.json +1 -1
  16. package/agent-plugin/mcp_config.json +13 -0
  17. package/agent-plugin/plugin.json +1 -1
  18. package/agent-plugin/skills/mobile-debug-mcp/SKILL.md +46 -18
  19. package/dist/contracts/device-readiness.js +1 -0
  20. package/dist/debugger/guard.js +4 -4
  21. package/dist/debugger/ios-worker.js +62 -0
  22. package/dist/debugger/ios.js +57 -0
  23. package/dist/debugger/sessions.js +33 -16
  24. package/dist/debugger/worker.js +6 -4
  25. package/dist/interact/index.js +12 -2
  26. package/dist/interact/waits/ui-change-wait.js +9 -2
  27. package/dist/interact/waits/ui-wait.js +7 -3
  28. package/dist/manage/index.js +3 -0
  29. package/dist/manage/ios.js +2 -0
  30. package/dist/observe/device-readiness.js +116 -0
  31. package/dist/observe/evidence.js +31 -0
  32. package/dist/observe/ios-trace/artifact.js +63 -0
  33. package/dist/observe/ios-trace/capabilities.js +86 -0
  34. package/dist/observe/ios-trace/native.js +93 -0
  35. package/dist/observe/ios-trace/notification.js +35 -0
  36. package/dist/observe/ios-trace/process.js +98 -0
  37. package/dist/observe/ios-trace/sessions.js +246 -0
  38. package/dist/observe/readiness-service.js +22 -10
  39. package/dist/observe/readiness.js +34 -4
  40. package/dist/observe/screenshot-encoding.js +4 -0
  41. package/dist/observe/snapshot-collection.js +7 -2
  42. package/dist/observe/system-trace-error.js +7 -0
  43. package/dist/observe/system-trace-router.js +81 -0
  44. package/dist/observe/system-trace.js +4 -8
  45. package/dist/server/definitions/manage.js +3 -2
  46. package/dist/server/handlers/action-execution.js +23 -14
  47. package/dist/server/handlers/compact-interaction.js +106 -0
  48. package/dist/server/handlers/compact-state.js +47 -0
  49. package/dist/server/handlers/debugger-handlers.js +27 -8
  50. package/dist/server/handlers/diagnostic.js +12 -4
  51. package/dist/server/handlers/input.js +2 -0
  52. package/dist/server/handlers/interact.js +2 -0
  53. package/dist/server/handlers/interaction-diagnostics.js +62 -0
  54. package/dist/server/handlers/journey.js +18 -20
  55. package/dist/server/handlers/observe.js +2 -1
  56. package/dist/server/handlers/tool-handlers.js +28 -14
  57. package/dist/server/schemas/debugger-schema.js +10 -7
  58. package/dist/server/schemas/interaction-diagnostics.js +9 -0
  59. package/dist/server/schemas/system-trace-schema.js +14 -9
  60. package/dist/server/tool-definitions.js +9 -4
  61. package/dist/server-core.js +5 -2
  62. package/dist/server.js +5 -5
  63. package/dist/system/android.js +19 -15
  64. package/dist/system/index.js +2 -1
  65. package/dist/utils/android/utils.js +7 -16
  66. package/dist/utils/app-installation.js +77 -0
  67. package/dist/utils/benchmark-metrics.js +43 -0
  68. package/dist/utils/exec.js +4 -0
  69. package/dist/utils/ios/utils.js +7 -11
  70. package/dist/utils/resolve-device.js +3 -2
  71. package/dist/utils/timing.js +3 -3
  72. package/docs/CHANGELOG.md +48 -1
  73. package/docs/agent-plugin-installation-verification.md +39 -0
  74. package/docs/benchmarks/README.md +1 -0
  75. package/docs/benchmarks/end-to-end-latency/README.md +98 -0
  76. package/docs/benchmarks/end-to-end-latency/android-snapshot-pair.json +6532 -0
  77. package/docs/benchmarks/end-to-end-latency/android-snapshot-pair.md +30 -0
  78. package/docs/benchmarks/end-to-end-latency/baseline-attempt-1.json +15901 -0
  79. package/docs/benchmarks/end-to-end-latency/baseline-attempt-1.md +14 -0
  80. package/docs/benchmarks/end-to-end-latency/baseline.json +233843 -0
  81. package/docs/benchmarks/end-to-end-latency/baseline.md +21 -0
  82. package/docs/benchmarks/end-to-end-latency/investigation.md +128 -0
  83. package/docs/benchmarks/end-to-end-latency/ios-smoke.json +84 -0
  84. package/docs/benchmarks/end-to-end-latency/ios-smoke.md +9 -0
  85. package/docs/benchmarks/end-to-end-latency/smoke.json +19601 -0
  86. package/docs/benchmarks/end-to-end-latency/smoke.md +21 -0
  87. package/docs/code-structure.md +3 -1
  88. package/docs/specs/031-ios-system-traces/intent.md +38 -0
  89. package/docs/specs/031-ios-system-traces/investigation.md +92 -0
  90. package/docs/specs/031-ios-system-traces/late-run-failure-evidence.json +32 -0
  91. package/docs/specs/031-ios-system-traces/plan.md +166 -0
  92. package/docs/specs/031-ios-system-traces/pr102-monitor-evidence.json +22 -0
  93. package/docs/specs/031-ios-system-traces/simulator-evidence.json +47 -0
  94. package/docs/specs/031-ios-system-traces/spec.md +135 -0
  95. package/docs/specs/032-ios-runtime-debugger/evidence.json +176 -0
  96. package/docs/specs/032-ios-runtime-debugger/intent.md +38 -0
  97. package/docs/specs/032-ios-runtime-debugger/plan.md +95 -0
  98. package/docs/specs/032-ios-runtime-debugger/report.md +205 -0
  99. package/docs/specs/032-ios-runtime-debugger/spec.md +153 -0
  100. package/docs/specs/033-device-readiness-blockers/android-evidence.json +437 -0
  101. package/docs/specs/033-device-readiness-blockers/android-physical-evidence.json +28 -0
  102. package/docs/specs/033-device-readiness-blockers/android-physical-power-evidence.json +29 -0
  103. package/docs/specs/033-device-readiness-blockers/intent.md +41 -0
  104. package/docs/specs/033-device-readiness-blockers/ios-investigation.md +55 -0
  105. package/docs/specs/033-device-readiness-blockers/ios-probe-evidence.json +24 -0
  106. package/docs/specs/033-device-readiness-blockers/ios-tool-evidence.json +73 -0
  107. package/docs/specs/033-device-readiness-blockers/plan.md +249 -0
  108. package/docs/specs/033-device-readiness-blockers/spec.md +134 -0
  109. package/docs/specs/034-app-installation-status/intent.md +41 -0
  110. package/docs/specs/034-app-installation-status/native-evidence.json +654 -0
  111. package/docs/specs/034-app-installation-status/plan.md +73 -0
  112. package/docs/specs/034-app-installation-status/spec.md +114 -0
  113. package/docs/specs/035-compact-interaction-results/baseline.md +45 -0
  114. package/docs/specs/035-compact-interaction-results/intent.md +38 -0
  115. package/docs/specs/035-compact-interaction-results/plan.md +43 -0
  116. package/docs/specs/035-compact-interaction-results/spec.md +118 -0
  117. package/docs/specs/035-compact-interaction-results/verification.md +111 -0
  118. package/docs/specs/036-end-to-end-interaction-latency/android-snapshot-amendment.md +60 -0
  119. package/docs/specs/036-end-to-end-interaction-latency/android-snapshot-plan.md +32 -0
  120. package/docs/specs/036-end-to-end-interaction-latency/intent.md +37 -0
  121. package/docs/specs/036-end-to-end-interaction-latency/plan.md +59 -0
  122. package/docs/specs/036-end-to-end-interaction-latency/spec.md +126 -0
  123. package/docs/specs/036-end-to-end-interaction-latency/verification.md +87 -0
  124. package/docs/tools/TOOLS.md +3 -2
  125. package/docs/tools/compact-interactions.md +56 -0
  126. package/docs/tools/correlated-evidence.md +6 -0
  127. package/docs/tools/debugger.md +45 -5
  128. package/docs/tools/interact.md +17 -8
  129. package/docs/tools/manage.md +10 -2
  130. package/docs/tools/observe.md +42 -2
  131. package/docs/tools/system-traces.md +81 -14
  132. package/docs/tools/system.md +6 -0
  133. package/package.json +2 -1
  134. package/scripts/agent-plugin.mjs +55 -5
  135. package/src/contracts/device-readiness.ts +8 -0
  136. package/src/debugger/android.ts +1 -1
  137. package/src/debugger/guard.ts +5 -5
  138. package/src/debugger/ios-worker.ts +49 -0
  139. package/src/debugger/ios.ts +45 -0
  140. package/src/debugger/lldb/breakpoints.py +51 -0
  141. package/src/debugger/lldb/inspection.py +109 -0
  142. package/src/debugger/lldb/worker.py +203 -0
  143. package/src/debugger/sessions.ts +24 -12
  144. package/src/debugger/worker.ts +7 -4
  145. package/src/interact/index.ts +13 -2
  146. package/src/interact/waits/ui-change-wait.ts +7 -2
  147. package/src/interact/waits/ui-wait.ts +6 -3
  148. package/src/manage/index.ts +2 -0
  149. package/src/manage/ios.ts +2 -0
  150. package/src/observe/device-readiness.ts +96 -0
  151. package/src/observe/evidence.ts +30 -1
  152. package/src/observe/ios-trace/artifact.ts +55 -0
  153. package/src/observe/ios-trace/capabilities.ts +74 -0
  154. package/src/observe/ios-trace/native.ts +72 -0
  155. package/src/observe/ios-trace/notification.ts +30 -0
  156. package/src/observe/ios-trace/process.ts +82 -0
  157. package/src/observe/ios-trace/sessions.ts +206 -0
  158. package/src/observe/readiness-service.ts +22 -10
  159. package/src/observe/readiness.ts +37 -4
  160. package/src/observe/screenshot-encoding.ts +4 -0
  161. package/src/observe/snapshot-collection.ts +7 -2
  162. package/src/observe/system-trace-error.ts +3 -0
  163. package/src/observe/system-trace-router.ts +61 -0
  164. package/src/observe/system-trace.ts +4 -4
  165. package/src/server/common.ts +2 -2
  166. package/src/server/definitions/manage.ts +3 -2
  167. package/src/server/handlers/action-execution.ts +22 -14
  168. package/src/server/handlers/compact-interaction.ts +91 -0
  169. package/src/server/handlers/compact-state.ts +43 -0
  170. package/src/server/handlers/debugger-handlers.ts +28 -9
  171. package/src/server/handlers/diagnostic.ts +11 -4
  172. package/src/server/handlers/input.ts +2 -0
  173. package/src/server/handlers/interact.ts +2 -0
  174. package/src/server/handlers/interaction-diagnostics.ts +50 -0
  175. package/src/server/handlers/journey.ts +15 -17
  176. package/src/server/handlers/observe.ts +2 -1
  177. package/src/server/handlers/payload.ts +2 -1
  178. package/src/server/handlers/tool-handlers.ts +29 -14
  179. package/src/server/schemas/debugger-schema.ts +10 -7
  180. package/src/server/schemas/interaction-diagnostics.ts +10 -0
  181. package/src/server/schemas/system-trace-schema.ts +15 -9
  182. package/src/server/tool-definitions.ts +8 -4
  183. package/src/server-core.ts +5 -2
  184. package/src/server.ts +4 -4
  185. package/src/system/android.ts +18 -11
  186. package/src/system/index.ts +2 -1
  187. package/src/types.ts +2 -0
  188. package/src/utils/android/utils.ts +8 -10
  189. package/src/utils/app-installation.ts +73 -0
  190. package/src/utils/benchmark-metrics.ts +42 -0
  191. package/src/utils/exec.ts +5 -0
  192. package/src/utils/ios/utils.ts +7 -10
  193. package/src/utils/resolve-device.ts +4 -2
  194. package/src/utils/timing.ts +3 -2
  195. package/test/device/automated/debugger/runtime.android.test.ts +5 -0
  196. package/test/device/automated/debugger/runtime.ios.test.ts +227 -0
  197. package/test/device/automated/interact/compact-results.smoke.ts +58 -0
  198. package/test/device/automated/latency/end-to-end-environment.ts +61 -0
  199. package/test/device/automated/latency/end-to-end-report.ts +90 -0
  200. package/test/device/automated/latency/end-to-end-session.ts +98 -0
  201. package/test/device/automated/latency/end-to-end.ts +149 -0
  202. package/test/device/automated/latency/owned-transport.ts +81 -0
  203. package/test/device/automated/latency/snapshot-pair.ts +143 -0
  204. package/test/device/automated/latency-ios/benchmark.ts +126 -0
  205. package/test/device/automated/observe/correlated-evidence.smoke.ts +7 -5
  206. package/test/device/automated/observe/device-readiness-cleanup.ts +14 -0
  207. package/test/device/automated/observe/device-readiness.android.smoke.ts +78 -0
  208. package/test/device/automated/observe/ios-system-trace.smoke.ts +119 -0
  209. package/test/device/automated/observe/system-trace.smoke.ts +2 -2
  210. package/test/fixtures/contracts/tool-definitions.json +243 -47
  211. package/test/fixtures/ios-debugger-app/Main.swift +95 -0
  212. package/test/fixtures/ios-debugger-app/README.md +27 -0
  213. package/test/fixtures/ios-debugger-app/build.ts +21 -0
  214. package/test/fixtures/latency-journey-app/build.ts +3 -3
  215. package/test/helpers/ios-trace-shutdown.ts +29 -0
  216. package/test/unit/debugger/handle-guards.test.ts +89 -0
  217. package/test/unit/debugger/ios-preparation.test.ts +57 -0
  218. package/test/unit/debugger/ios.test.ts +104 -0
  219. package/test/unit/debugger/lldb-worker.py +166 -0
  220. package/test/unit/debugger/lldb-worker.test.ts +10 -0
  221. package/test/unit/interact/ui-change-readiness-interruption.test.ts +37 -0
  222. package/test/unit/observe/capture_debug_snapshot.test.ts +66 -12
  223. package/test/unit/observe/device-readiness-cleanup.test.ts +24 -0
  224. package/test/unit/observe/device-readiness.test.ts +97 -0
  225. package/test/unit/observe/ios-trace-native.test.ts +90 -0
  226. package/test/unit/observe/ios-trace-sessions.test.ts +154 -0
  227. package/test/unit/observe/readiness-retained-blockers.test.ts +40 -0
  228. package/test/unit/observe/readiness.test.ts +1 -1
  229. package/test/unit/observe/system-trace-router.test.ts +49 -0
  230. package/test/unit/quality/agent-plugin-export.test.ts +38 -0
  231. package/test/unit/server/compact-interaction.test.ts +87 -0
  232. package/test/unit/server/compact-journey-evidence.test.ts +40 -0
  233. package/test/unit/server/compact-review-regressions.test.ts +78 -0
  234. package/test/unit/server/conditional_actions.test.ts +7 -3
  235. package/test/unit/server/correlated-evidence.test.ts +18 -6
  236. package/test/unit/server/end-to-end-report.test.ts +46 -0
  237. package/test/unit/server/input-device-readiness.test.ts +55 -0
  238. package/test/unit/server/interaction-diagnostics.test.ts +45 -0
  239. package/test/unit/server/owned-benchmark-transport.test.ts +32 -0
  240. package/test/unit/server/readiness-retained-deadline.test.ts +32 -0
  241. package/test/unit/server/readiness.test.ts +24 -1
  242. package/test/unit/server/run_journey.test.ts +2 -1
  243. package/test/unit/server/selector_tap_target.test.ts +2 -1
  244. package/test/unit/server/system-trace.test.ts +18 -7
  245. package/test/unit/utils/app-installation.test.ts +78 -0
  246. package/test/unit/utils/benchmark-metrics.test.ts +36 -0
  247. package/test/unit/utils/resolve_device.test.ts +11 -0
@@ -0,0 +1,73 @@
1
+ # Implementation plan
2
+
3
+ Intent and spec approved by user (“yes”, then “ok”) on 2026-11-05 in this chat.
4
+
5
+ - [x] Add shared installation observations and bounded platform probes.
6
+ - [x] Update inventory, system status, schema and selection diagnostics.
7
+ - [x] Cover status semantics, targeting, serialization and failures with fake tooling.
8
+ - [x] Align documentation and tool-definition fixture.
9
+ - [x] Run focused tests, npm run verify and npm run test:device.
10
+ - [x] Record Android installed/running, absent and no-context journeys; verify iOS separately.
11
+
12
+ Acceptance 1–3: native probes against checkout/build, recording exact device and scope.
13
+ Acceptance 2/4: deterministic unit tests with fake executable responses and selection fixtures.
14
+ Acceptance 5: verify (lint/build/unit/plugin), device suite and focused updated-server calls.
15
+ Node >=22 required; CI uses Node 22, additionally compiles/packages debugger workers;
16
+ Android CI is manual. Local default is Node 23.11.0; inspect available Node 22.
17
+ Android Pixel and emulator available; iOS simulator must be booted for conclusive checks.
18
+ No installation or app lifecycle changes required. Existing operation deadlines cap probes.
19
+
20
+ ## Results (2026-11-05)
21
+
22
+ Implementation complete on `bugfix/app-installed`, uncommitted. Intent/spec approval
23
+ recorded in their documents. Shared bounded probes cover Android inventory and
24
+ system status plus iOS simulator inventory. Schema/handler, serialization,
25
+ selection diagnostics, compatibility fixture, guides and changelog are aligned.
26
+ Startup healthcheck logging now safely handles the existing error-result variant
27
+ with missing platform fields; making unknown installation fields optional exposed
28
+ that union during TypeScript compilation.
29
+
30
+ Native discovery showed Android `pm path` returns a silent nonzero exit for
31
+ missing packages. Added a successful targeted package-list fallback, within the
32
+ same deadline, to establish absence. Failed fallback remains unknown. This is an
33
+ implementation refinement of the accepted installed/absent/unknown semantics.
34
+
35
+ [Native evidence](native-evidence.json) records final MCP stdio calls, build hashes,
36
+ per-device results, baseline reproduction and cleanup. Automated assertions over
37
+ those saved calls passed. Physical Pixel 9 Pro (Android 17), emulator-5554
38
+ (Android 16) and iPhone 17 Pro simulator (iOS 26.4) passed installation observations:
39
+
40
+ - Android missing app context: unknown, no boolean; unchanged HEAD reproduced false.
41
+ - Modul8 dev package: installed on both Android targets; emulator process PID 4064
42
+ was observed before device-suite execution (no claim of foreground readiness).
43
+ - Nonexistent package: absent on both Android targets using successful fallback.
44
+ - Safari installed and nonexistent bundle absent on the booted iOS simulator.
45
+ - Multiple-device system status: per-device installed results, no global boolean.
46
+ - Other unbooted simulators: unknown DEVICE_UNAVAILABLE, without attempted app queries.
47
+
48
+ Focused fake-tool tests pass: installed/absent, missing/invalid context, failed and
49
+ malformed queries, deadline timeout, per-device divergence, single/multiple system
50
+ aggregation and iOS plist parsing (macOS). Selection tests protect unknown status
51
+ and different-app isolation. Actual disconnected/unauthorized device failures
52
+ were not induced; these paths use deterministic failed-query/unavailable coverage.
53
+ The original agent request is unavailable; only the identified missing-context
54
+ failure path was reproduced. Physical iOS remains unsupported.
55
+
56
+ `npm run test:device`: PASS for executed checks (Android/iOS screenshots, logs,
57
+ UI trees and correlated evidence; Android trace lifecycle). The runner explicitly
58
+ reported coroutine/debugger, interaction/readiness fixtures and iOS tracing UNRUN
59
+ where environment selectors/dependencies were unset. These are not installation
60
+ coverage claims. Simulator restored to original Shutdown; suite leaves Android
61
+ Settings foreground, changes no app data or security settings. Native installed
62
+ checks and inventory do not launch or install apps.
63
+
64
+ `npm run verify`: PASS on both complete runs, including final regression coverage.
65
+ Final lint/architecture and build PASS; focused updated installation/selection
66
+ checks PASS. Runtime Node 23.11.0 (supported >=22), whereas CI uses Node 22.
67
+ CI additionally checks optional debugger compilation/package contents; those
68
+ unrelated checks were not rerun locally. Sandbox blocks tsx IPC/native services;
69
+ required suite/native commands succeeded with approved escalation.
70
+
71
+ Focused review found no remaining blocker: unknown booleans omitted, query
72
+ arguments device-scoped, malformed/native failures preserved, shared deadline
73
+ caps fallback/conversion, and no persistent app inventory/cache introduced.
@@ -0,0 +1,114 @@
1
+ # Specification: trustworthy app installation status
2
+
3
+ Status: approved by user “ok” in this chat on 2026-11-05; implementation authorised.
4
+ Intent: [approved scope](intent.md), user response “yes”, 2026-11-05.
5
+ Source: [issue #98](https://github.com/clivejefferies/mobile-debug-tools/issues/98).
6
+
7
+ ## Behaviour and scope
8
+
9
+ Installation is an observation about one app on one device, not a claim that
10
+ the app is running, visible or ready. Fix inventory and Android system-status
11
+ reporting without adding a tool or broadening device support. Existing iOS
12
+ inventory covers simulators; physical iOS installation checks remain unsupported.
13
+
14
+ `list_devices` retains its `{ devices: DeviceInfo[] }` wrapper. Publish the
15
+ already-handled optional `appId: string` input alongside optional `platform`.
16
+ Use only that explicit app ID for inventory checks; do not silently substitute
17
+ environment configuration. Reject blank/invalid identifiers before native calls.
18
+ Accept conventional Android package and iOS bundle identifiers (letters, digits,
19
+ underscores, hyphens and periods); use argument arrays, never shell interpolation.
20
+
21
+ Every returned device gains `appInstallation`:
22
+
23
+ ```ts
24
+ {
25
+ status: 'installed' | 'absent' | 'unknown';
26
+ appId: string | null;
27
+ deviceId: string;
28
+ scope: 'android-current-user' | 'ios-simulator';
29
+ checkedAt: string | null; // UTC ISO timestamp when a native check finished
30
+ reason?: 'APP_ID_NOT_PROVIDED' | 'DEVICE_UNAVAILABLE' |
31
+ 'CHECK_FAILED' | 'UNRECOGNIZED_RESPONSE';
32
+ }
33
+ ```
34
+
35
+ `installed` and `absent` require a successful authoritative query. Unknown
36
+ always includes a reason. `checkedAt` is null when no native check ran.
37
+ Keep legacy `appInstalled: true/false` only for confirmed installed/absent;
38
+ omit it for unknown. This corrects false negatives while retaining boolean
39
+ compatibility for conclusive checks. It intentionally changes callers that
40
+ incorrectly treat a missing boolean as confirmed absence; document this clearly.
41
+ Do not emit raw native errors or app-container paths in this diagnostic object.
42
+
43
+ ## Platform evidence
44
+
45
+ Android: query `pm path <appId>` with explicit serial. A successful result
46
+ containing valid package-path lines confirms installed. Successful empty output
47
+ confirms absence for the device's current Android user; other Android users and
48
+ work profiles are outside that observation. A silent nonzero `pm path` result may be followed by a successful
49
+ `pm list packages <appId>` query: exact membership confirms installation and
50
+ absence from a valid returned package list confirms absence. Otherwise nonzero
51
+ exit, timeout, disconnected,
52
+ offline or unauthorized device means unknown. Unexpected nonempty output means
53
+ unknown, never absent. Metadata failures must not manufacture absence.
54
+
55
+ iOS: for a simulator known to be booted, query `simctl listapps <udid>` using
56
+ its property-list output converted to JSON by macOS `plutil`, and check exact
57
+ bundle-identifier membership. A successfully parsed
58
+ app dictionary confirms installed or absent. Failed queries, malformed responses,
59
+ and simulators without confirmed booted state mean unknown. Replace the current
60
+ `get_app_container` failure-to-absence inference. Do not boot simulators as a
61
+ side effect of inventory. Preserve existing simulator inventory ordering.
62
+
63
+ ## System status and selection
64
+
65
+ `get_system_status` keeps its input schema and existing toolchain status fields.
66
+ Use the existing `MCP_TARGET_PACKAGE`, then `MCP_TARGET_APP_ID` precedence for
67
+ Android app context. Add top-level `appInstallations`, an array of the same
68
+ per-device observations for enumerated Android devices, including unavailable
69
+ devices as unknown. With no app context, observations are unknown with null app ID.
70
+
71
+ Legacy top-level `appInstalled` is present only when exactly one Android device
72
+ was enumerated and its result is conclusive. With multiple devices, no devices,
73
+ missing context or failed query, omit the global boolean. Never run an untargeted
74
+ package query. Report confirmed absence as a device-specific issue; report query
75
+ failures as check failures, not “app not installed”. No iOS app check is implied
76
+ by Android system-status fields. Invalid environment app IDs produce unknown
77
+ CHECK_FAILED observations and a configuration issue, without a subprocess.
78
+
79
+ Device selection may prefer only confirmed installed results for the requested
80
+ app. Retain existing remaining preference rules; unknown must not become an
81
+ absence assertion. Include check context in ambiguity diagnostics. Do not reuse
82
+ installation observations across apps, devices or inventory calls.
83
+
84
+ ## Failure, ownership and privacy
85
+
86
+ Each native installation query has a five-second maximum, capped by any enclosing
87
+ operation deadline, using existing subprocess cleanup. Deadline expiry or interrupted
88
+ checks cannot yield installed/absent. No retries, persistent cache, background
89
+ processes or changed cancellation protocol. Partial inventory retains device rows
90
+ and marks failed checks unknown. Whole inventory-enumeration failures retain the
91
+ existing empty-list behaviour; this does not establish app absence.
92
+
93
+ Checks are read-only: no installs, uninstalls, launches, unlocks or settings changes.
94
+ Return only requested app identity, device identity and bounded status metadata;
95
+ discard unrelated iOS app inventory after exact membership lookup.
96
+
97
+ ## Acceptance and verification
98
+
99
+ 1. Reproduce Android's missing-context false result on the current checkout;
100
+ compare explicit installed and absent app checks on available devices. Record
101
+ limits preventing reconstruction of the original agent session.
102
+ 2. Verify installed/running, absent, missing context, multiple devices, query
103
+ failures, malformed output and unavailable devices without false absence.
104
+ 3. Verify iOS installed/absent on a booted simulator separately; shutdown and
105
+ failed-listapps paths remain unknown. Physical iOS is explicitly unsupported.
106
+ 4. Test schemas, dispatch, serialized omission of unknown booleans, system-status
107
+ aggregation, and selection consumers together using deterministic fake tooling.
108
+ 5. Update tool descriptions, management/system guides and changelog. Run
109
+ `npm run verify`, `npm run test:device`, and focused calls against the updated
110
+ server. Report exact device/build evidence and unrun coverage separately.
111
+
112
+ Initial prerequisites: Android emulator and Pixel 9 Pro are connected; no iOS
113
+ simulator is currently booted. Native inventory required sandbox escalation.
114
+ These are readiness observations, not verification of this proposed behaviour.
@@ -0,0 +1,45 @@
1
+ # Baseline investigation — 2026-11-05
2
+
3
+ Local source fixtures executed using Node v23.11.0 and `node --import tsx` against
4
+ current actionHandler, correlation, evidence and readiness code. Native calls were
5
+ replaced by fixtures. These are response/serialization evidence, not device success.
6
+ Four cases used a concrete fixture device, awake/unlocked readiness, UUID IDs,
7
+ monotonic dispatch evidence and (for observed) one post-dispatch fingerprint capture.
8
+ The failure fixture marked dispatch started and returned ACTION_TIMEOUT; the blocked
9
+ fixture returned ELEMENT_NOT_FOUND without dispatch. Timings vary slightly per run.
10
+
11
+ | Fixture | Current bytes | Proposed projection bytes | Reduction |
12
+ | --- | ---: | ---: | ---: |
13
+ | Dispatch-only success | 1129 | 836 | 26% |
14
+ | Success with one observed fingerprint | 1639 | 854 | 48% |
15
+ | Failed after dispatch | 1157 | 864 | 25% |
16
+ | Blocked before dispatch | 1106 | 831 | 25% |
17
+
18
+ Projection numbers are serialized design prototypes, not implemented behaviour.
19
+ They preserve action fields; remove readiness evidence entries and evidence timing/
20
+ observation arrays; add observed_state and diagnostics UUID references. They establish
21
+ feasibility for a 1,280-byte budget, not validation of the complete contract. Exact
22
+ semantic tests and the full adversarial budget matrix remain implementation work.
23
+ Token estimates use ceil(bytes/4); no tokenizer measurement has been performed.
24
+
25
+ All fixtures currently retain action_id/type, success, lifecycle_state,
26
+ delivery_status, dispatch_started, verification, total timing, full device_readiness
27
+ and full evidence envelope. Failure/blocked fixtures also retain failure_code and
28
+ retryable. Full evidence repeats device/IDs/timestamps per observation. Compact
29
+ currently drops detailed errors even when internally available. Light mode may add
30
+ state_delta arrays; failed conditions can retain an entire observed tree. Journey
31
+ results nest per-action envelopes. These variable-size paths require budget tests.
32
+
33
+ ## Connected server/device evidence
34
+
35
+ The connected MCP server listed Android emulator-5554 (Android 16) and Pixel 9 Pro
36
+ (Android 17); all listed iOS simulators were shut down. A screenshot on emulator-5554
37
+ showed Android Settings. One tap on blank header space (360,80), compact/none,
38
+ reported dispatch delivered and verification not_requested. No post-action UI read
39
+ was performed, so resulting UI state is unknown. No setting change was requested.
40
+
41
+ The connected tap returned 831 UTF-8 bytes (208 tokens using the bytes/4 estimate).
42
+ The connected tap omitted device_readiness, unlike the local checkout. Its exact
43
+ server build is unavailable through this call, so it is not current-source proof.
44
+ The response had full evidence envelope and no observations. Physical Android and
45
+ iOS interaction paths were unrun. No performance conclusion follows from this call.
@@ -0,0 +1,38 @@
1
+ # Intent: concise, trustworthy compact interaction results
2
+
3
+ Status: intent and specification approved; implementation and verification complete locally.
4
+ Originator: GitHub issue #99; author identity not independently checked.
5
+ Captured: 2026-11-05.
6
+ Source: https://github.com/clivejefferies/mobile-debug-tools/issues/99
7
+
8
+ ## Problem
9
+
10
+ Recent agent feedback reports that routine taps return substantial metadata even
11
+ in compact mode. Clients need the action outcome, observed resulting UI state,
12
+ and actionable readiness blockers without repeatedly consuming detailed diagnostics.
13
+ Issue #82 addressed debugger responses; this work concerns ordinary interactions.
14
+
15
+ ## Desired outcome and scope
16
+
17
+ Audit existing compact interaction and journey results on Android and iOS. Record
18
+ representative successful, failed, and blocked response sizes and retained fields.
19
+ Specify and validate an explicit compact output budget, with measured byte/token
20
+ reductions against that baseline. Retain action outcome, verification status,
21
+ observed state or explicit unknown, actionable blockers, and evidence correlation.
22
+ Keep detailed failure diagnostics accessible through an explicit supported path.
23
+
24
+ Check callers, serialization, documentation, and compact/debug compatibility
25
+ together. Device evidence must distinguish actual observations from dispatch-only
26
+ success; no screen may be described as current without an observation.
27
+
28
+ ## Constraints and open questions
29
+
30
+ Exclude debugger redesign, latency optimization, and new interaction capabilities.
31
+ Investigation will establish the budget, retained fields, diagnostics access path,
32
+ and any compatibility impact for specification approval. Preserve verification and
33
+ readiness semantics; concise output must not imply stronger success evidence.
34
+
35
+ ## Approval
36
+
37
+ The user approved this intent with “ok” in this chat on 2026-11-05.
38
+ This approves the problem and scope; the response contract was subsequently approved with “ok” in this chat.
@@ -0,0 +1,43 @@
1
+ # Implementation plan
2
+
3
+ [Intent](intent.md) and [specification](spec.md) approved by the user's two “ok”
4
+ responses on 2026-11-05. Implement on existing feature/compact-interact-results;
5
+ preserve unrelated edits. Compact shape changes are intentional; debug is compatible.
6
+
7
+ ## Ordered work
8
+
9
+ - [x] Preserve full internal action/journey diagnostics until final response boundary.
10
+ - [x] Add bounded session result store, strict diagnostics schema/tool and dispatch.
11
+ - [x] Project final action/child/journey payloads with explicit freshness and byte bounds.
12
+ - [x] Update consumers, contract fixture, tool docs, README, changelog and plugin guidance.
13
+ - [x] Verify regressions, store limits, errors, final serialized budgets and debug parity.
14
+ - [x] Run native checks and record evidence, review diff and report limitations.
15
+
16
+ ## Verification map
17
+
18
+ | Criteria | Checks |
19
+ | --- | --- |
20
+ | Baselines and byte reductions | Existing baseline plus deterministic fixture matrix; UTF-8 bytes and labelled bytes/4 estimate |
21
+ | Bounds and semantics | Final handleToolCall responses; conditional/delta-heavy/multibyte cases, 50 steps, paused/throwing errors, stale/unknown/overlapping evidence |
22
+ | Diagnostics | Fidelity, no replay, injectable clock expiry, count/byte eviction, oversized rejection, invalid UUID/session and concurrent IDs |
23
+ | Compatibility | npm run verify; schema/definition fixture; debug shape, existing journey and correlation tests; docs/plugin consistency |
24
+ | Native | npm run test:device; updated dist server through MCP stdio on emulator-5554 and booted iOS simulator |
25
+
26
+ Node >=22 required (local v23.11.0); existing TypeScript/tsx dependencies. Use
27
+ `node --import tsx` for focused tests if tsx IPC is restricted. Native checks need
28
+ ADB/emulator and Xcode/simctl/idb. Before native runs inspect connected devices and
29
+ fixture availability. Start from Settings or isolated fixture app; exercise harmless
30
+ dispatch-only input, post-observation, blocked selector, journey and lookup. Capture
31
+ server commit+working diff, device/OS, response bytes, evidence freshness, unknown
32
+ states, failures and cleanup. Restore starting screen and shut down simulators booted
33
+ for this task. Use deterministic fixtures for unsafe native failure/cancellation paths.
34
+
35
+ CI uses Node 22 on Ubuntu, lint/build/unit, Java worker compilation and package-file
36
+ checks. Android integration is workflow_dispatch only; iOS checks are not in CI.
37
+ Local verify additionally runs agent-plugin consistency. No publish/push authorised.
38
+
39
+ ## Results
40
+
41
+ `npm run verify` and final `npm run test:device` passed. See
42
+ [verification record](verification.md) for exact coverage, byte measurements,
43
+ the intermittent trace-shutdown investigation and unrun optional fixtures.
@@ -0,0 +1,118 @@
1
+ # Specification: compact interaction results
2
+
3
+ Status: approved. Intent approved by the user's “ok” in
4
+ this chat on 2026-11-05; see [intent](intent.md). Source: issue #99.
5
+
6
+ ## Behaviour and scope
7
+
8
+ Apply one compact projection after final evidence assembly to existing actionHandler
9
+ interactions (including lifecycle actions using that wrapper) and run_journey.
10
+ Keep responseMode defaults, inputs, execution, targeting, budgets, verification,
11
+ conditional-action protection and journey stop behaviour unchanged. Other tools,
12
+ including debugger and UI-tree observation output, retain their existing contracts.
13
+
14
+ Retain action_id, action_type, success, lifecycle_state, delivery_status,
15
+ dispatch_started, verification, failure_code/retryable when applicable, and total
16
+ elapsed time. No dispatch acknowledgement becomes verified success. Retain
17
+ verification-unavailable diagnostics and condition status/reason. Replace raw
18
+ condition observations, state_delta element arrays and repeated evidence metadata
19
+ with bounded summaries and a diagnostics reference. This intentionally changes
20
+ opt-in compact shapes; debug remains compatible. Update existing callers and
21
+ fixtures that inspect compact evidence, conditions or deltas.
22
+
23
+ Evidence retains session_id, correlation_id, action_id, device and linked trace_id
24
+ when present; action_id remains usable as actionRef with the evidence session ID.
25
+ Retain association failures/reasons where applicable. Readiness retains wakefulness,
26
+ lock_state, input_ready, blockers and limitations, omitting probe evidence entries.
27
+ Never infer input_ready=true from awake/unlocked or treat unknown as ready.
28
+
29
+ Add observed_state: status observed or unknown. Observed requires an actual
30
+ successful same-device post-dispatch observation; include kind, captured_at_ms,
31
+ freshness and snapshot session/revision when available. A precondition tree is
32
+ pre-action evidence, never resulting state. No observation, failed capture,
33
+ unknown timing, overlap or supersession must be represented conservatively with a
34
+ reason. Only fresh post-action evidence permits status observed; other cases use
35
+ unknown while retaining the evidence classification. Fingerprint evidence describes
36
+ an observation, not a named screen or proof of an intended outcome. State deltas
37
+ retain revision IDs, counts of added/removed/changed items, truncation and omitted
38
+ counts; detailed elements are retrieved separately. No new hierarchy read is added.
39
+
40
+ Journey retains success, stopped_at_step_id and every step's id/type/status/success,
41
+ reason for unrun steps and compact result. Preserve assertion outcomes, matched
42
+ counts and bounded actual-state summaries. Finalize shared light-verification
43
+ and child evidence before projection. Do not project a child twice or lose its
44
+ original diagnostics. Trace linking and cleanup remain unchanged.
45
+
46
+ ## Bounds and diagnostics
47
+
48
+ Measure UTF-8 bytes of the final MCP text item after correlation and serialization,
49
+ not just an internal result. Caller-ID allowances count their UTF-8 JSON wire
50
+ encoding, including necessary escapes, so IDs are preserved verbatim. Each standalone compact result must fit 1,280 bytes
51
+ plus device-ID bytes. Each journey must fit 1,280 + 1,280 per supplied step, plus
52
+ UTF-8 bytes of supplied step IDs and device ID occurrences. Routine four-fixture
53
+ results must also reduce bytes by at least 20% each against the baseline below.
54
+ Report bytes and ceil(bytes/4) as a labelled token estimate, never actual tokens.
55
+
56
+ Use allowlists, bounded scalar strings (128 UTF-8 bytes per display value) and
57
+ count summaries; mark omitted display data with truncated=true. Preserve original
58
+ caller IDs, fixed outcome/status codes, all known blocker codes and correlation
59
+ references. If optional summaries would exceed the budget, omit them with
60
+ truncated=true and observed_state unknown when necessary; never silently drop
61
+ outcomes, blockers or diagnostics access. Test multibyte strings, huge trees,
62
+ conditions, deltas and all 50 journey steps. Debug output has no new output cap.
63
+
64
+ Add get_interaction_diagnostics({sessionId,resultId}), both UUID strings, strict
65
+ runtime validation and matching tool JSON schema. Every compact action/journey
66
+ and executed child result carries diagnostics {session_id,result_id,available}.
67
+ The lookup returns success:true and result containing the original diagnostic
68
+ payload and final full evidence, without replaying or observing the device.
69
+ Retain the pre-projection payload, including details already available internally
70
+ but previously omitted by compact mode; do not fabricate omitted debug captures.
71
+ Explicit debug mode remains the path for requesting additional diagnostic capture
72
+ at execution time. Lookup does not promise a debug rerun's additional observations.
73
+
74
+ Store at most 100 results, ten minutes from completion, and 16 MiB total in process
75
+ memory; cap each entry at 1 MiB. Serialize once and use oldest-completed eviction.
76
+ Oversized entries return available:false, reason:RESULT_TOO_LARGE in the compact
77
+ reference; never evict the useful summary. Lookup errors use success:false and
78
+ error {code,message}: SESSION_MISMATCH, RESULT_UNAVAILABLE (expired, evicted,
79
+ unknown or restarted), INVALID_ARGUMENT. No disk persistence, automatic retries,
80
+ subprocesses or device selection. Concurrent results receive unique IDs; reads do
81
+ not extend retention. Return explicit unavailability rather than rerunning input.
82
+
83
+ ## Platform, failure and privacy
84
+
85
+ Projection is platform-neutral; preserve Android/iOS readiness unknown/unsupported
86
+ semantics. Route guarded failures and thrown errors through the same compact
87
+ boundary where these tools currently return errors, preserving MCP error signalling.
88
+ Timeouts retain uncertain delivery and retryability. Cancellation retains existing
89
+ execution semantics and never triggers replay; completed retained results expire
90
+ normally. No new permissions, device actions or native dependencies are introduced.
91
+
92
+ Diagnostic payloads may contain UI text, paths and errors. Retention is session-local,
93
+ bounded and nonpersistent; compact mode is not redaction. Do not log stored content
94
+ or expose unrelated sessions. Document expiry and that lookup is read-only.
95
+
96
+ ## Acceptance and verification
97
+
98
+ 1. Record baseline/projection sizes and field differences, including successful,
99
+ failed, blocked, conditional, delta-heavy and journey cases.
100
+ 2. Assert byte bounds on final serialized results and >=20% fixture reduction;
101
+ check semantic fields, unknown observations and freshness independently.
102
+ 3. Verify lookup fidelity, expiry, size rejection, eviction, session mismatch,
103
+ concurrency, validation and absence of device calls or replay.
104
+ 4. Verify registration/dispatch/schema parity, existing callers, debug compatibility,
105
+ docs and plugin instructions together. Run npm run verify and test:device;
106
+ inspect current CI for coverage differences during implementation planning.
107
+ 5. Exercise updated local server on Android and a booted iOS simulator: dispatch-only,
108
+ actual post-observation, failed/blocked action, journey and diagnostics lookup.
109
+ Record build/device, evidence and cleanup. Native failure paths unsafe to induce
110
+ use deterministic fixtures, labelled separately. iOS is currently unrun: listed
111
+ simulators are shut down; boot one during implementation verification.
112
+
113
+ Affected areas: action-execution, correlation, journey, evidence assembly, new bounded
114
+ result store and diagnostics handler/schema/definition, tool dispatch, tests and docs.
115
+ Main risks are compact consumers relying on removed metadata, freshness mistakes,
116
+ projection before journey evidence finalization and unintended diagnostic retention.
117
+ The user approved this complete specification with “ok” in this chat on
118
+ 2026-11-05; implementation within this scope is authorised.
@@ -0,0 +1,111 @@
1
+ # Verification record — 2026-11-05
2
+
3
+ Implementation is local on feature/compact-interact-results, based on commit
4
+ 04f082a4c03f20b64a8fb13aed2b155225cad6cc plus this ticket's working-tree changes.
5
+ Nothing was committed, pushed, published or installed as a released package.
6
+
7
+ ## Automated checks
8
+
9
+ - `npm run verify`: PASS; ESLint, structural limits, architecture, TypeScript,
10
+ 108 unit-test files, and agent-plugin consistency.
11
+ - Focused compact tests: PASS; final serialized budgets, >=20% reduction for
12
+ each baseline fixture, huge conditions/deltas, multibyte/control-character IDs,
13
+ maximal 50-step results, retained diagnostics, automatic expiry, count/byte
14
+ eviction, oversized rejection, session mismatch, concurrency and strict UUID
15
+ schema, no replay, debug compatibility, guarded failures and MCP error signalling.
16
+ - Journey evidence regression: PASS; shared assertion observations attach to the
17
+ preceding light tap; later actions invalidate both tap/assertion freshness before
18
+ projection and diagnostics retention. Missing capture times remain unknown.
19
+ - Tool-definition compatibility fixture intentionally updated for the new tool and
20
+ revised compact descriptions. Existing conditional, selector, debugger-guard,
21
+ correlation and trace assertions now retrieve detailed metadata through diagnostics.
22
+ - Relative documentation links, whitespace/diff checks and plugin mirror: PASS.
23
+
24
+ Local runtime: Node v23.11.0; CI uses Node 22. CI additionally compiles the Java
25
+ worker and checks package contents; those CI-specific steps were not run locally.
26
+ No Java or packaging configuration was changed.
27
+
28
+ ## Native evidence
29
+
30
+ `npm run test:device`: PASS on final retry; 16 test files loaded. Seven optional
31
+ fixture files reported UNRUN: Android coroutine/Kotlin/runtime debugger, iOS runtime
32
+ debugger, isolated Android interaction fixture, disposable-device readiness, and
33
+ iOS system trace. Their explicit environment variables/toolchain selections were
34
+ not supplied. This does not establish coverage for those journeys or physical devices.
35
+
36
+ The new compact smoke uses MCP stdio against rebuilt dist/server.js (server
37
+ 0.36.0), rather than the connected older MCP instance. Settings was the starting
38
+ and ending app; no settings or app data were modified. Checks passed on:
39
+
40
+ | Platform/device | Observed evidence | Status |
41
+ | --- | --- | --- |
42
+ | Android 16, emulator-5554 | Dispatch-only launch unknown; light launch fresh post-action UI tree; absent selector fails before dispatch; two-step launch/assert journey; original/child lookup | PASS |
43
+ | iOS 26.4, iPhone 17 Pro simulator F9243BAF-62A8-4990-8A99-17F527F56FDA | Same structured checks, preserving unknown/unsupported iOS readiness signals | PASS |
44
+
45
+ These are UI-tree semantic/state checks, not screenshot layout assertions. The
46
+ older baseline screenshot established only the initial Settings layout.
47
+
48
+ Final fixture sizes were 830–864 bytes versus 1,106–1,639 baseline bytes (25–48%
49
+ reduction, timing-dependent by a few bytes). Token counts use ceil(bytes/4), not a
50
+ tokenizer. Device response sizes are recorded below after the final focused run.
51
+
52
+ The compact build hash is SHA-256
53
+ c2f93bf6a45b774f1fd2d57d721c855cb91e69f6ecbee46d860c12a00f2d151a,
54
+ computed over dist/server.js, dist/server/handlers/compact-interaction.js,
55
+ dist/server/handlers/compact-state.js,
56
+ dist/server/handlers/interaction-diagnostics.js, and dist/observe/evidence.js
57
+ in that order. This identifies a local build, not a release.
58
+
59
+ ## Failure investigation and review
60
+
61
+ An earlier device-suite attempt found one Android trace-shutdown file-removal
62
+ failure. A complete unmodified HEAD trace smoke passed; the modified trace smoke
63
+ then passed in isolation and within the final full device suite. Root cause remains
64
+ unproven; no trace implementation or assertion was weakened. The exact task-owned
65
+ leftover file was removed after its capture duration elapsed and absence verified.
66
+ This intermittent failure is recorded rather than classified as pre-existing.
67
+
68
+ Focused review checked final projection after guards/correlation and journey
69
+ refresh, post-dispatch/same-device/freshness requirements, fixed outcome/blocker
70
+ preservation, optional-summary truncation, retained-original fidelity, strict lookup
71
+ validation, bounded memory/automatic expiry, and absence of replay/native work in
72
+ lookup. Debug payloads and execution controls remain compatible. Compact clients
73
+ must migrate detailed metadata reads to the new lookup. Diagnostics may expire or
74
+ be evicted and oversized entries are explicitly unavailable; this is documented.
75
+
76
+ Simulator shutdown and final focused build confirmation are recorded below.
77
+
78
+ ## Final focused build run
79
+
80
+ | Platform | Dispatch-only bytes | Observed bytes | Blocked bytes | Journey bytes |
81
+ | --- | ---: | ---: | ---: | ---: |
82
+ | android | 839 | 972 | 952 | 2184 |
83
+ | ios | 893 | 1034 | 925 | 2284 |
84
+
85
+ Both platform journeys and original/child lookups passed on the final rebuilt
86
+ server. Android Settings remains foreground with no data/settings changes.
87
+ The iPhone 17 Pro simulator was shut down and booted-device inventory checked,
88
+ restoring its initial state.
89
+
90
+ ## PR #106 review repairs — 2026-11-06
91
+
92
+ Both attached review findings were confirmed against PR head 0fe5720. Failed compact
93
+ wait/assert operations now carry their step-scoped acquisition evidence through a
94
+ typed error wrapper into the failure result and retained diagnostics. The original
95
+ failure remains the cause; no mutation of thrown values is required. Wait operations
96
+ are awaited so rejected promises reach the step failure handler. Successful operations
97
+ and returned timeout payloads retain their existing behaviour. Shortened journey error
98
+ messages now set truncated=true even when the whole result fits its byte budget.
99
+
100
+ `compact-review-regressions.test.ts` covers a captured tree followed by a deterministic
101
+ remainingBudget() rejection, child/journey diagnostics fidelity, no replay, returned
102
+ timeouts, debug compatibility, and ASCII/UTF-8 truncation boundaries. These thrown
103
+ failure paths are fixture evidence, not induced native timeouts.
104
+
105
+ `npm run verify`: PASS (109 unit-test files, lint/architecture, build, plugin consistency).
106
+ `npm run test:device`: PASS (16 files; the same seven optional fixture files reported
107
+ UNRUN for missing explicit environment selections). Rebuilt-server compact journeys,
108
+ lookup, screenshots, logs and UI-tree checks passed on Android 16 emulator-5554 and
109
+ iOS 26.4 simulator F9243BAF-62A8-4990-8A99-17F527F56FDA; Android trace lifecycle,
110
+ cancellation and shutdown passed. No settings/app data changes or layout claims were
111
+ made. The iOS simulator was restored to its initial shut-down state after the run.
@@ -0,0 +1,60 @@
1
+ # Android debug snapshot tree reuse
2
+
3
+ Status: accepted on 2026-11-10. The user replied “yes” when asked to approve
4
+ this amendment in this chat.
5
+
6
+ The [ticket #100 measurements](../../benchmarks/end-to-end-latency/investigation.md)
7
+ recorded 36 physical read attempts across nine successful Android debug snapshots
8
+ with screenshots and logs disabled. Eighteen reads failed before recovery. The
9
+ snapshot median was 4.19 s. The snapshot currently starts a tree read and a
10
+ fingerprint request in parallel, and the Android fingerprint request reads its
11
+ own tree. The Android run ended before the planned tenth sample per case.
12
+
13
+ ## Proposed behavior
14
+
15
+ For `capture_debug_snapshot` on a resolved Android target, collect one fresh
16
+ tree using the existing acquisition path. Return that tree in `raw.ui_tree` and
17
+ derive `raw.fingerprint` from the same tree using the existing Android hash
18
+ algorithm and its post-tree activity lookup. Preserve the independent Android
19
+ `raw.activity` result and its error handling. This applies when the platform
20
+ is inferred as well as when Android is specified explicitly. It covers all
21
+ screenshot and log flag combinations.
22
+
23
+ Keep sharing scoped to the resolved device and the current snapshot request.
24
+ Each new snapshot starts its own acquisition. Preserve the captured tree's
25
+ revision, timestamp, and evidence provenance. The tree and fingerprint share
26
+ a source observation. Other snapshot components can still describe different
27
+ instants within the request. Keep the public inputs and response shape, iOS
28
+ collection, standalone fingerprint and tree tools, and journey verification
29
+ paths as they are.
30
+
31
+ The existing tree acquisition owns its retries, deadlines, and child-process
32
+ cleanup. If it fails, report both the tree error and fingerprint unavailability
33
+ using the existing per-component error fields. A second tree collection solely
34
+ for the fingerprint would defeat the intended sharing. Preserve independent
35
+ screenshot, activity, and log results. Preserve the existing fingerprint
36
+ fallback when the post-tree activity query fails, and report a fingerprint
37
+ calculation failure without discarding a successful tree. Capture only
38
+ timing, counts, build identity, and sanitized failure categories in the paired
39
+ benchmark artifacts.
40
+
41
+ ## Acceptance
42
+
43
+ 1. A successful Android snapshot makes one logical tree acquisition. Verify
44
+ that the returned fingerprint matches the existing algorithm applied to
45
+ the returned tree and the post-tree activity. Verify repeated captures
46
+ after a state change, device isolation, and unchanged response fields.
47
+ 2. Verify tree failure, activity failure, timeout, and partial results without
48
+ an extra fingerprint-driven tree acquisition. Retain the current native
49
+ acquisition and its cleanup path. Verify the unchanged iOS dispatch path
50
+ in unit coverage and report native iOS availability separately.
51
+ 3. Run a focused paired comparison of screenshot/log-free snapshots on the same
52
+ stable Android emulator and fixture screen. Use three warm-ups and ten
53
+ measured attempts per build, alternate order, and retain failures and read
54
+ attempts. Require fewer physical read attempts and a lower p95 with no
55
+ p50 regression or additional tool failures. Record build and fixture hashes.
56
+ The historical partial run motivates the candidate. The acceptance comparison
57
+ uses a newly measured baseline and candidate under matching conditions.
58
+ 4. Run `npm run verify`, applicable `npm run test:device` coverage, and a focused
59
+ native snapshot check. Record blocked checks and withhold any speedup claim
60
+ if the paired run is incomplete or correctness checks fail.
@@ -0,0 +1,32 @@
1
+ # Android debug snapshot verification plan
2
+
3
+ The user accepted the [amendment](android-snapshot-amendment.md) on 2026-11-10.
4
+
5
+ 1. Build and freeze the current baseline before editing production source.
6
+ 2. Share the Android fingerprint calculation with snapshot collection. Use the
7
+ existing tree handler and retain the Android activity lookups and iOS branch.
8
+ 3. Extend snapshot tests to cover hashing, ordering, target resolution, fresh
9
+ requests, partial errors, timeouts, and iOS dispatch. Keep native subprocess
10
+ ownership with the existing acquisition path.
11
+ 4. Run `node --import tsx test/unit/observe/capture_debug_snapshot.test.ts`,
12
+ `npm run verify`, and `npm run test:device` on the candidate.
13
+ 5. Use Node 22 or newer and the existing Android API 36 fixture tooling for
14
+ paired measurement. Run `node --import tsx test/device/automated/latency/snapshot-pair.ts`
15
+ with `LATENCY_DEVICE_ID`, `SNAPSHOT_BASELINE_SERVER`, and
16
+ `SNAPSHOT_BASELINE_SOURCE_SHA` set. Use the same dedicated fixture screen and
17
+ flags for both builds. Count acquisitions and physical attempts, assert the
18
+ candidate fingerprint and tree, record p50/p95 and failures, and close owned
19
+ server groups. Restore fixture state and stop any emulator started for testing.
20
+
21
+ ## Verification results
22
+
23
+ - The focused snapshot unit test and `npm run verify` passed locally on Node
24
+ 23.11.0. Hosted CI was not run.
25
+ - The [paired Android benchmark](../../benchmarks/end-to-end-latency/android-snapshot-pair.md)
26
+ passed with ten measured snapshots per build. Median latency fell from
27
+ 3.805 s to 2.364 s, and p95 fell from 3.949 s to 2.423 s. The candidate
28
+ performed one tree acquisition per call and returned fresh evidence after
29
+ navigation. Both server groups exited and the fixture was cleaned up.
30
+ - Android compact results and correlated evidence passed. The full device suite
31
+ and the separate correlated evidence smoke both stopped at the iOS simulator
32
+ prerequisite. Environment-gated debugger fixtures were skipped.